Yalantis/uCrop · error · CImgInstanceException

RGBtoCMY(): Instance is not a RGB image.

Error message

RGBtoCMY(): Instance is not a RGB image.

What it means

RGBtoCMY() converts RGB channels to CMY in place and requires exactly 3 channels; CImg throws CImgInstanceException when _spectrum!=3. The three channel planes are accessed directly, so any other channel count is invalid input for this operation.

Source

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

          R = (Y + 1.140f*V)*255,
          G = (Y - 0.395f*U - 0.581f*V)*255,
          B = (Y + 2.032f*U)*255;
        p1[N] = (T)cimg::cut(R,0,255),
        p2[N] = (T)cimg::cut(G,0,255),
        p3[N] = (T)cimg::cut(B,0,255);
      }
      return *this;
    }

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

    //! Convert pixel values from RGB to CMY color spaces.
    CImg<T>& RGBtoCMY() {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "RGBtoCMY(): Instance is not a RGB image.",
                                    cimg_instance);

      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);
      const longT whd = (longT)width()*height()*depth();
      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,2048))
      for (longT N = 0; N<whd; ++N) {
        const Tfloat
          R = (Tfloat)p1[N],
          G = (Tfloat)p2[N],
          B = (Tfloat)p3[N],
          C = 255 - R,
          M = 255 - G,
          Y = 255 - B;
        p1[N] = (T)cimg::cut(C,0,255),
        p2[N] = (T)cimg::cut(M,0,255),
        p3[N] = (T)cimg::cut(Y,0,255);
      }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Guard with if (img.spectrum()==3).
  2. Convert grayscale to RGB: img.get_append(img,img,'c').
  3. Convert CMYK input via CMYKtoCMY() first, then CMYtoRGB(), before RGBtoCMY() if needed.
  4. Catch CImgInstanceException to handle non-RGB inputs gracefully.

Example fix

// before
CImg<unsigned char> img("scan.png"); // grayscale
img.RGBtoCMY();
// after
CImg<unsigned char> img("scan.png");
if (img.spectrum()==1) img.append(img,img,img,'c');
img.RGBtoCMY();
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum()==1) img.append(img,img,img,'c');
if (img.spectrum()!=3) throw std::runtime_error("RGBtoCMY requires 3-channel RGB image");

Type guard

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

Try / catch

try {
  img.RGBtoCMY();
} catch (const cimg_library::CImgInstanceException& e) {
  std::cerr << "Non-RGB input: spectrum=" << img.spectrum() << std::endl;
}

Prevention

When it happens

Trigger: Calling img.RGBtoCMY() on a 1-channel grayscale image, a 4-channel RGBA/CMYK image, or an empty CImg.

Common situations: Print pipelines where scanned images may be grayscale or CMYK; loading JPEGs with alpha or PNGs with alpha; forgetting to normalize input to RGB before conversion.

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/e4be9e9bf96ae177. Report an issue: GitHub.