Yalantis/uCrop · error · CImgIOException

load_jpeg(): Failed to load JPEG data from file '%s'.

Error message

load_jpeg(): Failed to load JPEG data from file '%s'.

What it means

After jpeg_start_decompress, CImg only handles 1 (grayscale), 3 (RGB), or 4 (CMYK) output components; any other channel count triggers this error when reading from a FILE* (with a filename it silently falls back to load_other). It indicates the JPEG's color space/configuration is not directly decodable.

Source

Thrown at ucrop/src/main/jni/CImg.h:57055

      jerr.original.error_exit = _cimg_jpeg_error_exit;
      if (setjmp(jerr.setjmp_buffer)) { // JPEG error
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                             "load_jpeg(): Error message returned by libjpeg: %s.",
                             cimg_instance,jerr.message);
      }

      jpeg_create_decompress(&cinfo);
      jpeg_stdio_src(&cinfo,nfile);
      jpeg_read_header(&cinfo,TRUE);
      jpeg_start_decompress(&cinfo);

      if (cinfo.output_components!=1 && cinfo.output_components!=3 && cinfo.output_components!=4) {
        if (!file) {
          cimg::fclose(nfile);
          return load_other(nfilename);
        } else
          throw CImgIOException(_cimg_instance
                                "load_jpeg(): Failed to load JPEG data from file '%s'.",
                                cimg_instance,nfilename?nfilename:"(FILE*)");
      }
      CImg<ucharT> buffer(cinfo.output_width*cinfo.output_components);
      JSAMPROW row_pointer[1];
      try { assign(cinfo.output_width,cinfo.output_height,1,cinfo.output_components); }
      catch (...) { if (!file) cimg::fclose(nfile); throw; }
      T *ptr_r = _data, *ptr_g = _data + 1UL*_width*_height, *ptr_b = _data + 2UL*_width*_height,
        *ptr_a = _data + 3UL*_width*_height;
      while (cinfo.output_scanline<cinfo.output_height) {
        *row_pointer = buffer._data;
        if (jpeg_read_scanlines(&cinfo,row_pointer,1)!=1) {
          cimg::warn(_cimg_instance
                     "load_jpeg(): Incomplete data in file '%s'.",
                     cimg_instance,nfilename?nfilename:"(FILE*)");
          break;
        }
        const unsigned char *ptrs = buffer._data;

View on GitHub (pinned to f788b534b4)

Solutions

  1. Convert the JPEG to standard RGB (e.g. convert in.jpg -colorspace sRGB out.jpg) and reload
  2. Pass a filename instead of a FILE* so CImg can fall back to load_other()
  3. Re-export the image from a standard encoder
  4. Use an alternate decoder supporting exotic color spaces (libvips, libmagick)

Example fix

// before
std::FILE* f = fopen("cmyk.jpg","rb");
img.load_jpeg(f);
// after
img.load_jpeg("cmyk.jpg"); // allows fallback
// or convert first: convert cmyk.jpg -colorspace sRGB cmyk_rgb.jpg
img.load_jpeg("cmyk_rgb.jpg");
Defensive patterns

Strategy: fallback

Validate before calling

// prefer filename-based load so CImg can fall back automatically
img.load_jpeg("image.jpg"); // not load_jpeg(FILE*)

Try / catch

try { img.load_jpeg(file, filename); }
catch (CImgIOException&) { img.load("image_converted.png"); }

Prevention

When it happens

Trigger: load_jpeg(FILE*) on JPEGs whose decompressed output_components is not 1/3/4, e.g. unusual color spaces, separated CMYK with Adobe markers producing odd counts, or non-JPEG data misdetected.

Common situations: Scanned/print-shop CMYK JPEGs with Adobe APP14 markers, images transcoded by odd tools, wrong-format files named .jpg.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08). Data as JSON: /api/errors/e2e3b7db24b91580. Report an issue: GitHub.