Yalantis/uCrop · error · CImgArgumentException

save_yuv(): Specified filename is (null).

Error message

save_yuv(): Specified filename is (null).

What it means

CImgList::_save_yuv() throws CImgArgumentException when both the FILE* and the filename are null — at least one output target must be provided. (A subsequent check in the same function separately validates the chroma_subsampling value.) This is the yuv equivalent of the null-filename guards in other save methods.

Solutions

  1. Provide either a valid filename string or an opened std::FILE* to save_yuv().
  2. Validate output parameters (file or path) at the call site before invoking.
  3. Default to a standard output filename when neither is configured.

Example fix

// before
const char *path = cfg.output; // may be NULL
list.save_yuv(path, 420); // throws when both null
// after
list.save_yuv(cfg.output ? cfg.output : "out.yuv", 420);
Defensive patterns

Strategy: validation

Validate before calling

if (!file && !filename) {
  fprintf(stderr, "save_yuv needs a FILE* or a filename\n");
  return false;
}

Type guard

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

Try / catch

try { list.save_yuv(file_or_name, subsampling); }
catch (CImgArgumentException &e) { fprintf(stderr, "Provide an output file for YUV save\n"); }

Prevention

When it happens

Trigger: Calling save_yuv(filename,...) with a null filename and no open FILE*; a wrapper that forwards an optional FILE* and optional path where both ended up unset.

Common situations: Config/CLI supplying neither an output file nor a stream; optional argument plumbing where a default output path was removed; JNI bridge passing null for both file handle and path.

Related errors


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

Appendix: source

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

    }

    //! Save image sequence into a YUV file.
    /**
      \param file File to write data to.
      \param chroma_subsampling Type of chroma subsampling. Can be <tt>{ 420 | 422 | 444 }</tt>.
      \param is_rgb Tells if the RGB to YUV conversion must be done for saving.
    **/
    const CImgList<T>& save_yuv(std::FILE *const file,
                                const unsigned int chroma_subsampling=444,
                                const bool is_rgb=true) const {
      return _save_yuv(file,0,chroma_subsampling,is_rgb);
    }

    const CImgList<T>& _save_yuv(std::FILE *const file, const char *const filename,
                                 const unsigned int chroma_subsampling,
                                 const bool is_rgb) const {
      if (!file && !filename)
        throw CImgArgumentException(_cimglist_instance
                                    "save_yuv(): Specified filename is (null).",
                                    cimglist_instance);
      if (chroma_subsampling!=420 && chroma_subsampling!=422 && chroma_subsampling!=444)
        throw CImgArgumentException(_cimglist_instance
                                    "save_yuv(): Specified chroma subsampling %u is invalid, for file '%s'.",
                                    cimglist_instance,
                                    chroma_subsampling,filename?filename:"(FILE*)");
      if (is_empty()) { cimg::fempty(file,filename); return *this; }
      const unsigned int
        cfx = chroma_subsampling==420 || chroma_subsampling==422?2:1,
        cfy = chroma_subsampling==420?2:1,
        w0 = (*this)[0]._width, h0 = (*this)[0]._height,
        width0 = w0 + (w0%cfx), height0 = h0 + (h0%cfy);
      std::FILE *const nfile = file?file:cimg::fopen(filename,"wb");
      cimglist_for(*this,l) {
        const CImg<T> &frame = (*this)[l];
        cimg_forZ(frame,z) {
          CImg<ucharT> YUV;

View on GitHub (pinned to f788b534b4)