Yalantis/uCrop · error · CImgInstanceException

CMYtoCMYK(): Instance is not a CMY image.

Error message

CMYtoCMYK(): Instance is not a CMY image.

What it means

get_CMYtoCMYK() produces a new 4-channel CMYK image from a CMY image; it requires the source to have exactly 3 channels (_spectrum==3). CImg throws CImgInstanceException otherwise, since it reads three source planes and writes four destination planes.

Solutions

  1. Guard with if (img.spectrum()==3) before conversion.
  2. Convert RGB input first: img.RGBtoCMY() (after ensuring 3 channels).
  3. Expand grayscale with get_append(img,img,'c').
  4. Catch CImgInstanceException for non-CMY inputs.

Example fix

// before
CImg<float> img("photo.png"); // RGB
img.CMYtoCMYK();
// after
CImg<float> img("photo.png");
if (img.spectrum()==3) img.RGBtoCMY().CMYtoCMYK();
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum()!=3) throw std::runtime_error("CMYtoCMYK requires 3-channel CMY image");
CImg<float> cmyk = img.get_CMYtoCMYK();

Type guard

bool isCMY(const cimg_library::CImg<T>& img) { return img.spectrum()==3; }

Try / catch

try {
  img.CMYtoCMYK();
} catch (const cimg_library::CImgInstanceException& e) {
  std::cerr << "Need CMY (3 channels), got " << img.spectrum() << std::endl;
}

Prevention

When it happens

Trigger: Calling img.CMYtoCMYK() or img.get_CMYtoCMYK() on grayscale, RGBA, or empty images.

Common situations: Print pipelines receiving RGB or grayscale scans that must be converted to CMYK; forgetting the RGBtoCMY() step; images loaded with alpha channels.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

        p3[N] = (T)cimg::cut(B,0,255);
      }
      return *this;
    }

    //! Convert pixel values from CMY to RGB color spaces \newinstance.
    CImg<Tuchar> get_CMYtoRGB() const {
      return CImg<Tuchar>(*this,false).CMYtoRGB();
    }

    //! Convert pixel values from CMY to CMYK color spaces.
    CImg<T>& CMYtoCMYK() {
      return get_CMYtoCMYK().move_to(*this);
    }

    //! Convert pixel values from CMY to CMYK color spaces \newinstance.
    CImg<Tuchar> get_CMYtoCMYK() const {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "CMYtoCMYK(): Instance is not a CMY image.",
                                    cimg_instance);

      CImg<Tfloat> res(_width,_height,_depth,4);
      const T *ps1 = data(0,0,0,0), *ps2 = data(0,0,0,1), *ps3 = data(0,0,0,2);
      Tfloat *pd1 = res.data(0,0,0,0), *pd2 = res.data(0,0,0,1), *pd3 = res.data(0,0,0,2), *pd4 = res.data(0,0,0,3);
      const longT whd = (longT)width()*height()*depth();
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,1024))
      for (longT N = 0; N<whd; ++N) {
        Tfloat
          C = (Tfloat)ps1[N],
          M = (Tfloat)ps2[N],
          Y = (Tfloat)ps3[N],
          K = cimg::min(C,M,Y);
        if (K>=255) C = M = Y = 0;
        else { const Tfloat K1 = 255 - K; C = 255*(C - K)/K1; M = 255*(M - K)/K1; Y = 255*(Y - K)/K1; }
        pd1[N] = (Tfloat)cimg::cut(C,0,255),
        pd2[N] = (Tfloat)cimg::cut(M,0,255),

View on GitHub (pinned to f788b534b4)