Yalantis/uCrop · error · CImgInstanceException

RGBtoYUV(): Instance is not a RGB image.

Error message

RGBtoYUV(): Instance is not a RGB image.

What it means

RGBtoYUV() performs an in-place RGB to YUV channel conversion and requires a 3-channel image. CImg throws this CImgInstanceException when _spectrum!=3 because the transform reads and writes exactly the three channel planes p1/p2/p3.

Source

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

          R = (298*Y + 409*Cr + 128)/256,
          G = (298*Y - 100*Cb - 208*Cr + 128)/256,
          B = (298*Y + 516*Cb + 128)/256;
        p1[N] = (T)cimg::cut(R,(Tfloat)0,(Tfloat)255),
        p2[N] = (T)cimg::cut(G,(Tfloat)0,(Tfloat)255),
        p3[N] = (T)cimg::cut(B,(Tfloat)0,(Tfloat)255);
      }
      return *this;
    }

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

    //! Convert pixel values from RGB to YUV color spaces.
    CImg<T>& RGBtoYUV() {
      if (_spectrum!=3)
        throw CImgInstanceException(_cimg_instance
                                    "RGBtoYUV(): 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,16384))
      for (longT N = 0; N<whd; ++N) {
        const Tfloat
          R = (Tfloat)p1[N]/255,
          G = (Tfloat)p2[N]/255,
          B = (Tfloat)p3[N]/255,
          Y = 0.299f*R + 0.587f*G + 0.114f*B;
        p1[N] = (T)Y;
        p2[N] = (T)(0.492f*(B - Y));
        p3[N] = (T)(0.877*(R - Y));
      }
      return *this;
    }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Guard with if (img.spectrum()==3) before the call.
  2. For grayscale, expand: img = img.get_append(img,img,'c');
  3. For RGBA, strip alpha: img.channels(0,2).
  4. Catch CImgInstanceException and convert or reject the frame.

Example fix

// before
CImg<float> frame = nextFrame(); // may be RGBA
frame.RGBtoYUV();
// after
CImg<float> frame = nextFrame();
if (frame.spectrum()==4) frame.channels(0,2);
if (frame.spectrum()!=3) throw std::runtime_error("RGB required");
frame.RGBtoYUV();
Defensive patterns

Strategy: validation

Validate before calling

if (img.spectrum()!=3) {
  if (img.spectrum()==4) img.channels(0,2);
  else if (img.spectrum()==1) img.append(img,img,img,'c');
}

Type guard

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

Try / catch

try {
  img.RGBtoYUV();
} catch (const cimg_library::CImgInstanceException& e) {
  std::cerr << "RGB required; spectrum=" << img.spectrum() << std::endl;
}

Prevention

When it happens

Trigger: Calling img.RGBtoYUV() on a grayscale (spectrum=1), RGBA (spectrum=4), or empty image.

Common situations: Video-frame pipelines fed 4-channel frames; grayscale webcam frames; images built with wrong channel count via CImg(w,h,d,s) constructor.

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