Yalantis/uCrop · error · CImgInstanceException
RGBtoHSL(): Instance is not a RGB image.
Error message
RGBtoHSL(): Instance is not a RGB image.
What it means
CImg<T>::RGBtoHSL() converts pixel values from RGB to the HSL color space and requires exactly 3 channels (R, G, B planes). Images with any other spectrum throw CImgInstanceException. The check verifies channel count only — 3-channel non-RGB data will convert without error but yield wrong colors.
Source
Thrown at ucrop/src/main/jni/CImg.h:37142
case 4 : R = X; G = 0; B = C; break;
default : R = C; G = 0; B = X;
}
p1[N] = (T)((R + m)*3*255);
p2[N] = (T)((G + m)*3*255);
p3[N] = (T)((B + m)*3*255);
}
return *this;
}
//! Convert pixel values from HSI to RGB color spaces \newinstance.
CImg<Tfloat> get_HSItoRGB() const {
return CImg< Tuchar>(*this,false).HSItoRGB();
}
//! Convert pixel values from RGB to HSL color spaces.
CImg<T>& RGBtoHSL() {
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"RGBtoHSL(): 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,256))
for (longT N = 0; N<whd; ++N) {
const Tfloat
R = (Tfloat)p1[N],
G = (Tfloat)p2[N],
B = (Tfloat)p3[N],
m = cimg::min(R,G,B),
M = cimg::max(R,G,B),
C = M - m,
H = 60*(C==0?0:M==R?cimg::mod((G - B)/C,(Tfloat)6):M==G?(B - R)/C + 2:(R - G)/C + 4),
L = 0.5f*(m + M)/255,
S = L==1 || L==0?0:C/(1 - cimg::abs(2*L - 1))/255;
p1[N] = (T)H;View on GitHub (pinned to f788b534b4)
Solutions
- Check img.spectrum()==3 first; convert grayscale to 3 channels by replication.
- For RGBA, call img.channels(0,2) to drop alpha before converting.
- Use get_RGBtoHSL() on a properly prepared copy if the original must stay untouched.
- Normalize image loading so all inputs are converted to RGB once, at load time.
Example fix
// before
CImg<unsigned char> img("scan.png"); // grayscale, spectrum=1
img.RGBtoHSL(); // throws
// after
CImg<unsigned char> img("scan.png");
if (img.spectrum() == 1) img.resize(-100,-100,-100,3); // replicate gray to RGB
img.RGBtoHSL(); Defensive patterns
Strategy: type-guard
Validate before calling
template<typename T> bool isRgb(const CImg<T>& img) { return img.spectrum() == 3; }
if (isRgb(img)) img.RGBtoHSL(); Type guard
template<typename T> bool isRgb(const CImg<T>& img) { return img.spectrum() == 3; } Try / catch
try {
img.RGBtoHSL();
} catch (const CImgInstanceException& e) {
std::fprintf(stderr, "RGBtoHSL requires 3 channels, image has %d\n", img.spectrum());
} Prevention
- Guard every conversion with a spectrum()==3 check.
- Normalize inputs to RGB at load time.
- Drop alpha channels early in the pipeline.
- Track spectrum changes through resize/channel operations.
When it happens
Trigger: Calling img.RGBtoHSL() on grayscale (spectrum=1), RGBA (spectrum=4), or otherwise non-3-channel images.
Common situations: Single-channel medical/scientific images; PNG with alpha; images loaded via loaders that return indexed or grayscale formats; forgetting channels(0,2) after compositing with an alpha layer.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- RGBtoHSI(): Instance is not a RGB image.
- HSItoRGB(): Instance is not a HSI image.
- HSLtoRGB(): Instance is not a HSL image.
- RGBtoHSV(): Instance is not a RGB image.
- HSVtoRGB(): Instance is not a HSV image.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/af91e3134a3ab7c9.
Report an issue: GitHub.