Yalantis/uCrop · error · CImgInstanceException
xyYtoXYZ(): Instance is not a xyY image.
Error message
xyYtoXYZ(): Instance is not a xyY image.
What it means
xyYtoXYZ() converts xyY chromaticity values back to CIE XYZ and requires exactly 3 channels (x, y, Y). It throws CImgInstanceException when _spectrum != 3, since the transform indexes three channel planes. This is the inverse of XYZtoxyY and is only valid on images in xyY layout.
Source
Thrown at ucrop/src/main/jni/CImg.h:37695
Z = (Tfloat)p3[N],
sum = X + Y + Z,
nsum = sum>0?sum:1;
p1[N] = (T)(X/nsum);
p2[N] = (T)(Y/nsum);
p3[N] = (T)Y;
}
return *this;
}
//! Convert pixel values from XYZ to xyY color spaces \newinstance.
CImg<Tfloat> get_XYZtoxyY() const {
return CImg<Tfloat>(*this,false).XYZtoxyY();
}
//! Convert pixel values from xyY pixels to XYZ color spaces.
CImg<T>& xyYtoXYZ() {
if (_spectrum!=3)
throw CImgInstanceException(_cimg_instance
"xyYtoXYZ(): Instance is not a xyY 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,4096))
for (longT N = 0; N<whd; ++N) {
const Tfloat
px = (Tfloat)p1[N],
py = (Tfloat)p2[N],
Y = (Tfloat)p3[N],
ny = py>0?py:1;
p1[N] = (T)(px*Y/ny);
p2[N] = (T)Y;
p3[N] = (T)((1 - px - py)*Y/ny);
}
return *this;
}View on GitHub (pinned to f788b534b4)
Solutions
- Check img.spectrum()==3 before the call and fix the pipeline so xyY data is stored as exactly 3 channels.
- Only call xyYtoXYZ on the result of XYZtoxyY(); for raw RGB use RGBtoXYZ() instead.
- Remove or separate extra channels: get_channels(0,2) for RGBA, or duplicate gray channels for 1-channel images.
- Wrap the call in try/catch for CImgInstanceException in native code.
Example fix
// before img.xyYtoXYZ(); // img is grayscale, spectrum==1 -> throws // after if (img.spectrum()==1) img = img.get_resize(img.width(),img.height(),1,3); // replicate to 3 channels after ensuring data is xyY img.xyYtoXYZ();
Defensive patterns
Strategy: validation
Validate before calling
if (img.spectrum()!=3) { /* repair before xyYtoXYZ */ } Type guard
template<class T> bool has3Channels(const cimg_library::CImg<T>& i){ return i.spectrum()==3; } Try / catch
try { img.xyYtoXYZ(); } catch (cimg_library::CImgInstanceException& e) { /* recover */ } Prevention
- Only invert xyY on XYZtoxyY output
- Keep xyY data alpha-free
When it happens
Trigger: Calling img.xyYtoXYZ() on an image with spectrum != 3 — grayscale images, RGB/RGBA images not in xyY form, or images where the alpha channel makes the count 4.
Common situations: Reversing a chromaticity conversion on an image that still carries an alpha channel; applying xyYtoXYZ to raw RGB data (never converted to xyY); loading multi-channel spectral data and forgetting to reduce to 3 channels.
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.
- LabtoXYZ(): Instance is not a Lab image.
- XYZtoxyY(): Instance is not a XYZ 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/1d5ba0b35251e7ce.
Report an issue: GitHub.