Yalantis/uCrop · error · CImgArgumentException

save_raw(): Specified filename is (null).

Error message

save_raw(): Specified filename is (null).

What it means

save_raw() dumps raw pixel data to a FILE* or a filename. The internal _save_raw helper requires at least one of the two to be non-null and throws CImgArgumentException otherwise. It is an immediate argument-contract check before any data is written.

Source

Thrown at ucrop/src/main/jni/CImg.h:63410

       \note The .raw format does not store the image dimensions in the output file,
       so you have to keep track of them somewhere to be able to read the file correctly afterwards.
    **/
    const CImg<T>& save_raw(const char *const filename, const bool is_multiplexed=false) const {
      return _save_raw(0,filename,is_multiplexed);
    }

    //! Save image as a raw data file \overloading.
    /**
       Same as save_raw(const char *,bool) const
       with a file stream argument instead of a filename string.
    **/
    const CImg<T>& save_raw(std::FILE *const file, const bool is_multiplexed=false) const {
      return _save_raw(file,0,is_multiplexed);
    }

    const CImg<T>& _save_raw(std::FILE *const file, const char *const filename, const bool is_multiplexed) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_raw(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }

      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      if (pixel_type()==cimg::type<bool>::string()) { // Boolean data (bitwise)
        ulongT siz;
        const unsigned char *const buf = _bool2uchar(siz,is_multiplexed);
        cimg::fwrite(buf,siz,nfile);
        delete[] buf;
      } else { // Non boolean data
        if (!is_multiplexed || _spectrum==1) cimg::fwrite(_data,size(),nfile); // Non-multiplexed
        else { // Multiplexed
          CImg<T> buf(_spectrum);
          cimg_forXYZ(*this,x,y,z) {
            cimg_forC(*this,c) buf[c] = (*this)(x,y,z,c);
            cimg::fwrite(buf._data,_spectrum,nfile);
          }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Pass a filename: img.save_raw("out.cimg", false).
  2. Or open a FILE* yourself and call img.save_raw(fp, is_multiplexed).
  3. Validate the path string is non-null and non-empty before calling.

Example fix

// before
const char *name = getPath(); // may be NULL
img.save_raw(name);
// after
const char *name = getPath();
if (!name) name = "default.raw";
img.save_raw(name);
Defensive patterns

Strategy: validation

Validate before calling

if (!fname || !*fname) fname = "data.raw";
img.save_raw(fname, /*is_multiplexed*/false);

Type guard

bool validPath(const char *p) { return p != nullptr && p[0] != '\0'; }

Try / catch

try { img.save_raw(file?file:path.c_str()); }
catch (cimg_library::CImgArgumentException &e) { std::fprintf(stderr, "save_raw needs FILE* or filename: %s\n", e.what()); }

Prevention

When it happens

Trigger: Calling save_raw() with no filename and no FILE*, or passing NULL explicitly to _save_raw(file=0, filename=0, ...).

Common situations: Building the output path dynamically and passing a null pointer, or calling the FILE*-only overload believing a filename was stored internally.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/a79cec97a0478879. Report an issue: GitHub.