{"record":{"id":"274212c189abc0d6","repo":"Yalantis/uCrop","slug":"save-jxl-bytes-per-pixel-must-be-in-0-2-and","errorCode":null,"errorMessage":"save_jxl(): bytes_per_pixel must be in [0, 2] and less than or equal to sizeof(T)","messagePattern":"save_jxl\\(\\): bytes_per_pixel must be in \\[0, 2\\] and less than or equal to sizeof\\(T\\)","errorType":"exception","errorClass":"CImgArgumentException","httpStatus":null,"severity":"error","filePath":"ucrop/src/main/jni/CImg.h","lineNumber":61780,"sourceCode":"\n    const CImg<T>& _save_jxl(const char *const filename, const float distance=1.0f,\n                             const unsigned int bytes_per_pixel=0) const {\n      if (!filename)\n        throw CImgArgumentException(_cimg_instance\n                                    \"save_jxl(): Specified filename is (null).\",\n                                    cimg_instance);\n      if (_spectrum > 4)\n        throw CImgArgumentException(_cimg_instance\n                                    \"save_jxl(): JPEG XL only supports at most 4 channels.\",\n                                    cimg_instance);\n      double stmin, stmax = (double)max_min(stmin);\n      if (stmin<0 || (bytes_per_pixel==1 && stmax>=256) || stmax>=65536)\n        cimg::warn(_cimg_instance\n                   \"save_jxl(): Instance has pixel values in [%g,%g], probable type overflow in file '%s'.\",\n                   cimg_instance,\n                   stmin,stmax,filename);\n      if (bytes_per_pixel>2 || sizeof(T)<bytes_per_pixel)\n        throw CImgArgumentException(_cimg_instance\n                                    \"save_jxl(): bytes_per_pixel must be in [0, 2] and less than or equal to sizeof(T)\",\n                                    cimg_instance);\n      if (_depth>1)\n        cimg::warn(_cimg_instance\n                   \"save_jxl(): Instance is volumetric, only the first slice will be saved in file '%s'.\",\n                   cimg_instance,\n                   filename);\n#ifndef cimg_use_jxl\n      cimg::unused(distance);\n      return save_other(filename);\n#else\n      std::FILE *file = cimg::fopen(filename, \"wb\");\n      cimg_uint32 nChannels = _spectrum;\n      bool hasAlpha = _spectrum==2 || _spectrum==4;\n      if (hasAlpha) --nChannels;\n      unsigned int bytesPerPixel = bytes_per_pixel;\n      if (bytesPerPixel==0)\n          bytesPerPixel = stmax<256?1:2;","sourceCodeStart":61762,"sourceCodeEnd":61798,"githubUrl":"https://github.com/Yalantis/uCrop/blob/f788b534b48c144edf786c8cddbf0e029e637804/ucrop/src/main/jni/CImg.h#L61762-L61798","documentation":"save_jxl() accepts bytes_per_pixel of 0 (auto), 1 (8-bit), or 2 (16-bit), and it must not exceed sizeof(T) of the image's pixel type. Otherwise CImg throws CImgArgumentException, because the requested output bit depth cannot be represented from the underlying storage type.","triggerScenarios":"Calling img.save_jxl(path, distance, bpp) with bpp==3 or higher, or with bpp larger than sizeof(T) — e.g. bytes_per_pixel==2 on a CImg<char>/CImg<unsigned char> (sizeof(T)==1).","commonSituations":"Copy-pasted save calls where the bpp parameter was tuned for float images (sizeof 4) then reused on byte images, or hardcoded 16-bit output requested on 8-bit data.","solutions":["Pass bytes_per_pixel within [0,2] and <= sizeof(T): use 0 (auto) unless you specifically need 8/16-bit output.","If you need 16-bit JXL from byte data, first convert the image: CImg<unsigned short> out = img * 257; then save with bytes_per_pixel=2.","Clamp the parameter at the call site based on the image type."],"exampleFix":"// before\nCImg<unsigned char> img(...);\nimg.save_jxl(\"out.jxl\", 1.0f, 2); // sizeof(T)=1 < 2 -> throw\n// after\nCImg<unsigned short> out = img * 257;\nout.save_jxl(\"out.jxl\", 1.0f, 2);","handlingStrategy":"validation","validationCode":"if (bytesPerPixel > 2 || sizeof(T) < bytesPerPixel) {\n  throw std::invalid_argument(\"bytes_per_pixel must be in [0,2] and <= sizeof(T)\");\n}\nimg.save_jxl(\"out.jxl\", 1.0f, bytesPerPixel);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Default to bytes_per_pixel=0 (auto) unless bit depth matters.","Compute bpp from the image type, never hardcode.","Convert pixel type first if 16-bit JXL output is required."],"tags":["cimg","jxl","bytes-per-pixel","validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"f788b534b48c144edf786c8cddbf0e029e637804","analyzedAt":"2026-09-08T08:36:04.887Z","contentChangedAt":"2026-09-08T08:36:04.887Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}