Yalantis/uCrop · error · CImgArgumentException

save_jpeg(): Specified filename is (null).

Error message

save_jpeg(): Specified filename is (null).

What it means

CImg's save_jpeg() throws a CImgArgumentException when both the FILE* and the filename pointer are null. The JPEG saving path needs either an open file stream or a path string; with neither, there is no destination and the call cannot proceed.

Source

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

    }

    //! Save image as a JPEG file.
    /**
      \param filename Filename, as a C-string.
      \param quality Image quality (in %)
    **/
    const CImg<T>& save_jpeg(const char *const filename, const unsigned int quality=100) const {
      return _save_jpeg(0,filename,quality);
    }

    //! Save image as a JPEG file \overloading.
    const CImg<T>& save_jpeg(std::FILE *const file, const unsigned int quality=100) const {
      return _save_jpeg(file,0,quality);
    }

    const CImg<T>& _save_jpeg(std::FILE *const file, const char *const filename, const unsigned int quality) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "save_jpeg(): Specified filename is (null).",
                                    cimg_instance);
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      if (_depth>1)
        cimg::warn(_cimg_instance
                   "save_jpeg(): Instance is volumetric, only the first slice will be saved in file '%s'.",
                   cimg_instance,
                   filename?filename:"(FILE*)");

#ifndef cimg_use_jpeg
      if (!file) return save_other(filename,quality);
      else throw CImgIOException(_cimg_instance
                                 "save_jpeg(): Unable to save data in '(*FILE)' unless libjpeg is enabled.",
                                 cimg_instance);
#else
      unsigned int dimbuf = 0;
      J_COLOR_SPACE colortype = JCS_RGB;

View on GitHub (pinned to f788b534b4)

Solutions

  1. Pass a valid filename string: img.save_jpeg("out.jpg").
  2. Open the file first with fopen and pass the non-null FILE* to save_jpeg(file).
  3. Guard the call site: check the FILE*/filename for null before calling and fail early with your own error.

Example fix

// before
std::FILE *f = fopen(path, "wb"); // may be null
img.save_jpeg(f);
// after
std::FILE *f = fopen(path, "wb");
if (!f) throw std::runtime_error("cannot open " + std::string(path));
img.save_jpeg(f);
fclose(f);
Defensive patterns

Strategy: type-guard

Type guard

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

Try / catch

try {
  img.save_jpeg(file, quality);
} catch (const cimg_library::CImgArgumentException &e) {
  std::fprintf(stderr, "jpeg dest missing: %s\n", e.what());
}

Prevention

When it happens

Trigger: Calling img.save_jpeg((std::FILE*)nullptr) (the FILE*-only overload) with a null pointer, or invoking the internal _save_jpeg with file==nullptr and filename==nullptr.

Common situations: Programmatically constructing the destination from a variable that turned out to be null — e.g. a FILE* from a failed fopen passed straight to save_jpeg, or an optional filename that was never assigned.

Related errors


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