Yalantis/uCrop · error · CImgInstanceException
LabtoXYZ(): Instance is not a Lab image.
Error message
LabtoXYZ(): Instance is not a Lab image.
What it means
LabtoXYZ() converts pixel values from CIE Lab back to CIE XYZ and requires the image to hold exactly 3 Lab channels (L, a, b). It throws CImgInstanceException when _spectrum != 3, since it accesses three channel pointers directly. This guards against running the inverse transform on images not produced by XYZtoLab (or hand-built with the right layout).
Source
Thrown at ucrop/src/main/jni/CImg.h:37633
fX = (Tfloat)_cimg_Labf(X),
fY = (Tfloat)_cimg_Labf(Y),
fZ = (Tfloat)_cimg_Labf(Z);
p1[N] = (T)cimg::cut(116*fY - 16,0,100);
p2[N] = (T)(500*(fX - fY));
p3[N] = (T)(200*(fY - fZ));
}
return *this;
}
//! Convert pixel values from XYZ to Lab color spaces \newinstance.
CImg<Tfloat> get_XYZtoLab(const bool use_D65=true) const {
return CImg<Tfloat>(*this,false).XYZtoLab(use_D65);
}
//! Convert pixel values from Lab to XYZ color spaces.
CImg<T>& LabtoXYZ(const bool use_D65=true) {
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"LabtoXYZ(): Instance is not a Lab image.",
cimg_instance);
const CImg<Tfloat> white = CImg<Tfloat>(1,1,1,3,255).RGBtoXYZ(use_D65);
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,128))
for (longT N = 0; N<whd; ++N) {
const Tfloat
L = (Tfloat)p1[N],
a = (Tfloat)p2[N],
b = (Tfloat)p3[N],
cY = (L + 16)/116,
cZ = cY - b/200,
cX = a/500 + cY,
X = (Tfloat)(24389*cX>216?cX*cX*cX:(116*cX - 16)*27/24389),
Y = (Tfloat)(27*L>216?cY*cY*cY:27*L/24389),
Z = (Tfloat)(24389*cZ>216?cZ*cZ*cZ:(116*cZ - 16)*27/24389);
p1[N] = (T)(X*white[0]);View on GitHub (pinned to f788b534b4)
Solutions
- Verify img.spectrum()==3 immediately before the call and fix the pipeline so Lab data is actually 3-channel.
- If the image is still RGB, call RGBtoXYZ() then XYZtoLab() before LabtoXYZ() — LabtoXYZ only reverses XYZtoLab.
- Drop or split off alpha channels (spectrum==4) before conversion.
- Guard with try/catch on CImgInstanceException for defensive native code.
Example fix
// before texture.LabtoXYZ(); // texture is RGBA, spectrum==4 -> throws // after CImg<float> lab = texture.get_channels(0,2); // drop alpha lab.LabtoXYZ();
Defensive patterns
Strategy: validation
Validate before calling
if (img.spectrum()!=3) { /* repair before LabtoXYZ */ } Type guard
template<class T> bool has3Channels(const cimg_library::CImg<T>& i){ return i.spectrum()==3; } Try / catch
try { img.LabtoXYZ(); } catch (cimg_library::CImgInstanceException& e) { /* recover */ } Prevention
- Track color state; only invert on Lab images
- Assert spectrum()==3 in debug builds
When it happens
Trigger: Calling img.LabtoXYZ() on an image with spectrum != 3 — typically a grayscale image, an RGBA image, or an image that was never converted to Lab. Also from get_LabtoXYZ() with the same invalid instance.
Common situations: Undoing a Lab conversion on a copy whose alpha channel was re-added; loading a Lab-looking TIFF with 1 or 4 channels; applying LabtoXYZ to an image still in RGB (forgot RGBtoXYZ first).
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
- XYZtoLab(): Instance is not a XYZ image.
- XYZtoxyY(): Instance is not a XYZ image.
- xyYtoXYZ(): Instance is not a xyY image.
- RGBtoYCbCr(): Instance is not a RGB image.
- YCbCrtoRGB(): Instance is not a YCbCr image.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/890a540ab1ee8f00.
Report an issue: GitHub.