{"record":{"id":"085c2fc26bf51d76","repo":"Yalantis/uCrop","slug":"cmytorgb-instance-is-not-a-cmy-image","errorCode":null,"errorMessage":"CMYtoRGB(): Instance is not a CMY image.","messagePattern":"CMYtoRGB\\(\\): Instance is not a CMY image\\.","errorType":"exception","errorClass":"CImgInstanceException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":37432,"sourceCode":"          C = 255 - R,\n          M = 255 - G,\n          Y = 255 - B;\n        p1[N] = (T)cimg::cut(C,0,255),\n        p2[N] = (T)cimg::cut(M,0,255),\n        p3[N] = (T)cimg::cut(Y,0,255);\n      }\n      return *this;\n    }\n\n    //! Convert pixel values from RGB to CMY color spaces \\newinstance.\n    CImg<Tuchar> get_RGBtoCMY() const {\n      return CImg<Tfloat>(*this,false).RGBtoCMY();\n    }\n\n    //! Convert pixel values from CMY to RGB color spaces.\n    CImg<T>& CMYtoRGB() {\n      if (_spectrum!=3)\n        throw CImgInstanceException(_cimg_instance\n                                    \"CMYtoRGB(): Instance is not a CMY image.\",\n                                    cimg_instance);\n\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,2048))\n      for (longT N = 0; N<whd; ++N) {\n        const Tfloat\n          C = (Tfloat)p1[N],\n          M = (Tfloat)p2[N],\n          Y = (Tfloat)p3[N],\n          R = 255 - C,\n          G = 255 - M,\n          B = 255 - Y;\n        p1[N] = (T)cimg::cut(R,0,255),\n        p2[N] = (T)cimg::cut(G,0,255),\n        p3[N] = (T)cimg::cut(B,0,255);\n      }","sourceCodeStart":37414,"sourceCodeEnd":37450,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L37414-L37450","documentation":"CMYtoRGB() converts CMY channels back to RGB in place and requires exactly 3 channels; the same _spectrum!=3 check triggers the exception. The message 'not a CMY image' reflects the expected source color space, but the check is purely channel-count based.","triggerScenarios":"Calling img.CMYtoRGB() on grayscale, RGBA, 4-channel CMYK, or empty images.","commonSituations":"Print workflows where a 4-channel CMYK buffer is passed directly instead of being reduced to CMY; RGB images converted twice; images loaded with unexpected channel counts.","solutions":["Check spectrum()==3 before calling.","If the image is CMYK (4 channels), call CMYKtoCMY() first, then CMYtoRGB().","Expand grayscale to 3 channels with get_append before treating as CMY.","Catch CImgInstanceException and log the actual spectrum."],"exampleFix":"// before\nCImg<float> img = loadCMYK(); // spectrum 4\nimg.CMYtoRGB();\n// after\nCImg<float> img = loadCMYK();\nif (img.spectrum()==4) img.CMYKtoCMY().CMYtoRGB();\nelse if (img.spectrum()==3) img.CMYtoRGB();","handlingStrategy":"validation","validationCode":"if (img.spectrum()==4) img.CMYKtoCMY();\nif (img.spectrum()!=3) throw std::runtime_error(\"CMY image with 3 channels required\");","typeGuard":"bool isCMY(const cimg_library::CImg<T>& img) { return img.spectrum()==3; }","tryCatchPattern":"try {\n  img.CMYtoRGB();\n} catch (const cimg_library::CImgInstanceException& e) {\n  std::cerr << \"CMY required; spectrum=\" << img.spectrum() << std::endl;\n}","preventionTips":["Route by spectrum: 4 channels => CMYK path, 3 channels => CMY path","Only convert from CMY that was produced by RGBtoCMY()","Log spectrum values when conversion pipelines fail"],"tags":["cimg","image-processing","color-space","spectrum"],"backgroundTag":"type-mismatch","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"}