{"record":{"id":"e3fc58bd9aaa2ced","repo":"Yalantis/uCrop","slug":"xyztolab-instance-is-not-a-xyz-image","errorCode":null,"errorMessage":"XYZtoLab(): Instance is not a XYZ image.","messagePattern":"XYZtoLab\\(\\): Instance is not a XYZ image\\.","errorType":"exception","errorClass":"CImgInstanceException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":37603,"sourceCode":"          p1[N] = (T)cimg::cut(3.134274799724*X  - 1.617275708956*Y - 0.490724283042*Z,0,255);\n          p2[N] = (T)cimg::cut(-0.978795575994*X + 1.916161689117*Y + 0.033453331711*Z,0,255);\n          p3[N] = (T)cimg::cut(0.071976988401*X - 0.228984974402*Y + 1.405718224383*Z,0,255);\n        }\n      }\n      return *this;\n    }\n\n    //! Convert pixel values from XYZ to RGB color spaces \\newinstance.\n    CImg<Tuchar> get_XYZtoRGB(const bool use_D65=true) const {\n      return CImg<Tuchar>(*this,false).XYZtoRGB(use_D65);\n    }\n\n    //! Convert pixel values from XYZ to Lab color spaces.\n    CImg<T>& XYZtoLab(const bool use_D65=true) {\n#define _cimg_Labf(x) (24389*(x)>216?cimg::cbrt(x):(24389*(x)/27 + 16)/116)\n\n      if (_spectrum!=3)\n        throw CImgInstanceException(_cimg_instance\n                                    \"XYZtoLab(): Instance is not a XYZ image.\",\n                                    cimg_instance);\n      const CImg<Tfloat> white = CImg<Tfloat>(1,1,1,3,255).RGBtoXYZ(use_D65);\n      T *p1 = data(0,0,0,0), *p2 = data(0,0,0,1), *p3 = data(0,0,0,2);\n      const longT whd = (longT)width()*height()*depth();\n      cimg_pragma_openmp(parallel for cimg_openmp_if_size(whd,128))\n      for (longT N = 0; N<whd; ++N) {\n        const Tfloat\n          X = (Tfloat)(p1[N]/white[0]),\n          Y = (Tfloat)(p2[N]/white[1]),\n          Z = (Tfloat)(p3[N]/white[2]),\n          fX = (Tfloat)_cimg_Labf(X),\n          fY = (Tfloat)_cimg_Labf(Y),\n          fZ = (Tfloat)_cimg_Labf(Z);\n        p1[N] = (T)cimg::cut(116*fY - 16,0,100);\n        p2[N] = (T)(500*(fX - fY));\n        p3[N] = (T)(200*(fY - fZ));\n      }","sourceCodeStart":37585,"sourceCodeEnd":37621,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L37585-L37621","documentation":"CImg's XYZtoLab() converts pixel values from CIE XYZ to CIE Lab color space, which requires exactly 3 channels (X, Y, Z). The library throws CImgInstanceException when the image's _spectrum (channel count) is not 3, because the conversion reads exactly three channel planes via data(0,0,0,0..2). It is an instance-state precondition check, not a per-pixel value check.","triggerScenarios":"Calling img.XYZtoLab() (or the RGBtoXYZ->XYZtoLab chain, or get_XYZtoLab()) on an image whose _spectrum != 3, e.g. a grayscale (_spectrum==1), RGBA (_spectrum==4), or multi-spectral image. Also triggered by chaining XYZtoLab after a conversion that did not yield 3 channels.","commonSituations":"Loading a grayscale PNG/JPG and applying color conversions directly; forgetting that an alpha channel makes _spectrum 4; applying XYZtoLab twice (second time the image is already Lab); building images with append_channels that produced the wrong channel count.","solutions":["Ensure the image has exactly 3 channels before calling: if (img.spectrum()!=3) img.channels(0,2) is wrong — instead convert or rebuild the image so spectrum()==3 (e.g. call RGBtoXYZ first for genuine XYZ data).","For grayscale sources, replicate the channel first: if (img.spectrum()==1) img = img.get_shared_channels(0,0).get_append(CImg<float>::vector(img), 'x') or construct a 3-channel image explicitly.","For 4-channel (RGBA) images, strip alpha into a separate image and convert only the RGB portion.","Wrap in try/catch on CImgInstanceException to surface a clear message instead of crashing in JNI/native code."],"exampleFix":"// before\nimg.XYZtoLab(); // throws if img.spectrum()!=3 (e.g. grayscale logo)\n// after\nif (img.spectrum()==1) img = CImg<float>(img.width(),img.height(),1,3).draw_image(0,0,img).draw_image(1,0,img).draw_image(2,0,img);\nimg.XYZtoLab();","handlingStrategy":"validation","validationCode":"cimg_library::CImg<float> img = source.get_channels(0, source.spectrum() >= 3 ? 2 : source.spectrum()-1);\nif (img.spectrum() != 3) { /* handle */ }","typeGuard":"template<class T> bool has3Channels(const cimg_library::CImg<T>& i){ return i.spectrum()==3; }","tryCatchPattern":"try { img.XYZtoLab(); } catch (cimg_library::CImgInstanceException& e) { /* repair */ }","preventionTips":["Check spectrum() before color conversions","Normalize grayscale/RGBA inputs at load"],"tags":["cimg","color-space","image-processing","instance-check"],"backgroundTag":"incompatible-source-type","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}