Yalantis/uCrop · error · CImgArgumentException

save_yuv(): Specified chroma subsampling %u is invalid, for…

Error message

save_yuv(): Specified chroma subsampling %u is invalid, for file '%s'.

What it means

CImgList::save_yuv validates that the chroma subsampling parameter is one of the YUV formats it can write: 420, 422 or 444. Any other unsigned value is rejected before any I/O happens, thrown as a CImgArgumentException naming both the invalid value and the target file. This is pure argument validation on the caller side.

Solutions

  1. Set chroma_subsampling to one of 420, 422 or 444 (e.g. imglist.save_yuv("out.yuv", 420)).
  2. Check where the value originates and clamp/default it to 420 before the call.
  3. If you need other subsamplings, convert/upsample the data yourself first, since the writer only supports these three.

Example fix

// before
list.save_yuv("video.yuv", subsampling); // subsampling == 0
// after
if (subsampling != 420 && subsampling != 422 && subsampling != 444) subsampling = 420;
list.save_yuv("video.yuv", subsampling);
Defensive patterns

Strategy: validation

Validate before calling

bool validChroma(unsigned s){ return s==420 || s==422 || s==444; }
// call only if validChroma(chroma_subsampling)

Type guard

bool isChromaValid(unsigned s) { return s == 420 || s == 422 || s == 444; }

Try / catch

try { list.save_yuv(file, chroma); } catch (CImgArgumentException &e) { std::fprintf(stderr, "bad chroma: %s", e.what()); chroma = 420; }

Prevention

When it happens

Trigger: Calling save_yuv(filename, chroma_subsampling) or the std::ostream variant with chroma_subsampling set to e.g. 0, 411, 410 or any value not in {420,422,444}.

Common situations: Passing an uninitialized or default-zero subsampling variable; confusing 4:1:1-style values with the supported set; loading subsampling from config where 4:2:0 is written as '420' string parsed incorrectly or as 4:2:2 variant codes.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

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

      \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;
          if (sizeof(T)==1 && !is_rgb &&
              frame._width==width0 && frame._height==height0 && frame._depth==1 && frame._spectrum==3)
            YUV.assign((unsigned char*)frame._data,width0,height0,1,3,true);
          else {

View on GitHub (pinned to f788b534b4)