Yalantis/uCrop · error · CImgArgumentException

save_cpp(): Specified filename is (null).

Error message

save_cpp(): Specified filename is (null).

What it means

save_cpp() exports the image as C++ source; _save_cpp() throws CImgArgumentException when both the FILE* and filename are null, since it needs an output stream and also derives the variable name from the filename. Same shared-implementation pattern as the other _save_* helpers.

Source

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

      return *this;
    }

    //! Save image as a .cpp source file.
    /**
      \param filename Filename, as a C-string.
    **/
    const CImg<T>& save_cpp(const char *const filename) const {
      return _save_cpp(0,filename);
    }

    //! Save image as a .cpp source file \overloading.
    const CImg<T>& save_cpp(std::FILE *const file) const {
      return _save_cpp(file,0);
    }

    const CImg<T>& _save_cpp(std::FILE *const file, const char *const filename) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_cpp(): Specified filename is (null).",
                                    cimg_instance);
      std::FILE *const nfile = file?file:cimg::fopen(filename,"w");
      CImg<charT> varname(1024); *varname = 0;
      if (filename) cimg_sscanf(cimg::basename(filename),"%1023[a-zA-Z0-9_]",varname._data);
      if (!*varname) cimg_snprintf(varname,varname._width,"unnamed");
      std::fprintf(nfile,
                   "/* Define image '%s' of size %ux%ux%ux%u and type '%s' */\n"
                   "%s data_%s[] = { %s\n  ",
                   varname._data,_width,_height,_depth,_spectrum,pixel_type(),pixel_type(),varname._data,
                   is_empty()?"};":"");
      if (!is_empty()) for (ulongT off = 0, siz = size() - 1; off<=siz; ++off) {
        std::fprintf(nfile,cimg::type<T>::format(),cimg::type<T>::format((*this)[off]));
        if (off==siz) std::fprintf(nfile," };\n");
        else if (!((off + 1)%16)) std::fprintf(nfile,",\n  ");
        else std::fprintf(nfile,", ");
      }
      if (!file) cimg::fclose(nfile);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Provide a valid filename so the variable name can be derived.
  2. Open the FILE* successfully before the FILE*-overload call.
  3. Null-check both arguments at the call site.
  4. Default the output to a fixed name like "image.cpp" when unset.

Example fix

// before
img.save_cpp(NULL); // no destination
// after
img.save_cpp("image.cpp");
Defensive patterns

Strategy: type-guard

Validate before calling

if (!file && (!filename || !*filename)) { filename = "unnamed.cpp"; }

Type guard

bool hasDestination(std::FILE* f, const char* n){ return f!=nullptr || (n!=nullptr && *n!='\0'); }

Try / catch

try { img.save_cpp(f); } catch (CImgArgumentException& e) { img.save_cpp("unnamed.cpp"); }

Prevention

When it happens

Trigger: Calling img.save_cpp((std::FILE*)NULL) or img.save_cpp((const char*)NULL); forwarding a NULL FILE* from a failed fopen without a filename fallback.

Common situations: Code-generation tooling with optional output paths, refactored calls that dropped the filename argument, fopen errors silently propagating NULL.

Related errors


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