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
- Guard with if (img.spectrum()==3) before the call.
- For grayscale, expand: img = img.get_append(img,img,'c');
- For RGBA, strip alpha: img.channels(0,2).
- 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
- Normalize frame channel count at ingestion (video frames are often 4-channel)
- Check spectrum() after every crop/append operation
- Use explicit spectrum=3 in CImg constructors when allocating color buffers
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
- RGBtoYCbCr(): Instance is not a RGB image.
- YCbCrtoRGB(): Instance is not a YCbCr image.
- YUVtoRGB(): Instance is not a YUV image.
- RGBtoCMY(): Instance is not a RGB image.
- CMYtoRGB(): Instance is not a CMY image.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/788b796d26f07fe2.
Report an issue: GitHub.