Yalantis/uCrop · error · CImgIOException

load_bmp(): File size %lu for filename '%s' does not match e

Error message

load_bmp(): File size %lu for filename '%s' does not match encoded image dimensions (%d,%d).

What it means

CImg's load_bmp() computes the buffer size implied by the header's width/height and rejects the file when this buffer is not smaller than the actual file size, i.e. the declared dimensions are inconsistent with the file's length. This guards against corrupted or fabricated headers.

Source

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

                              cimg_instance,
                              header_size,filename?filename:"(FILE*)");

      if (offset<0 || offset>=file_size)
        throw CImgIOException(_cimg_instance
                              "load_bmp(): Invalid offset %d specified in filename '%s'.",
                              cimg_instance,
                              offset,filename?filename:"(FILE*)");

      if (header_size>40) cimg::fseek(nfile,header_size - 40,SEEK_CUR);
      const int
        dx_bytes = (bpp==1)?(dx/8 + (dx%8?1:0)):((bpp==4)?(dx/2 + (dx%2)):(int)((longT)dx*bpp/8)),
        align_bytes = (4 - dx_bytes%4)%4;
      const ulongT
        cimg_iobuffer = (ulongT)24*1024*1024,
        buf_size = (ulongT)cimg::abs(dy)*(dx_bytes + align_bytes);

      if (buf_size>=fsiz)
        throw CImgIOException(_cimg_instance
                              "load_bmp(): File size %lu for filename '%s' does not match "
                              "encoded image dimensions (%d,%d).",
                              cimg_instance,
                              (long)fsiz,filename?filename:"(FILE*)",dx,dy);

      CImg<intT> colormap;
      if (bpp<16) { if (!nb_colors) nb_colors = 1<<bpp; } else nb_colors = 0;
      if (nb_colors) { colormap.assign(nb_colors); cimg::fread(colormap._data,nb_colors,nfile); }

      const int xoffset = offset - 14 - header_size - 4*nb_colors;
      if (xoffset<0 || xoffset>=file_size)
        throw CImgIOException(_cimg_instance
                              "load_bmp(): Malformed header in filename '%s'.",
                              cimg_instance,
                              filename?filename:"(FILE*)");
      cimg::fseek(nfile,xoffset,SEEK_CUR);

      CImg<ucharT> buffer;

View on GitHub (pinned to f788b534b4)

Solutions

  1. Re-obtain or re-export the BMP from a trustworthy source
  2. Check the actual file size against the header dimensions with a tool like `identify` before loading
  3. Convert the image to PNG/JPEG and load that format instead
  4. Catch CImgIOException and fall back to another decoder

Example fix

// before
img.load_bmp("truncated.bmp");
// after
try { img.load_bmp("truncated.bmp"); }
catch (CImgIOException&) { img.load("truncated.png"); } // re-export a complete file
Defensive patterns

Strategy: validation

Validate before calling

unsigned dx = readS32LE(path,18), dy = readS32LE(path,22);
long fsiz = getFileSize(path);
if ((long)dx*dy*4 + 54 > fsiz) throw std::runtime_error("bmp size mismatch");

Type guard

bool bmpDimensionsMatchSize(long fsiz, int dx, int dy) { return (long)dy*((dx*4+3)/4*4)+54 < fsiz; }

Try / catch

try { img.load_bmp(path); }
catch (CImgIOException& e) { fprintf(stderr,"%s\n",e.what()); img.assign(); }

Prevention

When it happens

Trigger: Loading a .bmp whose BITMAPINFOHEADER width/height imply more pixel bytes than the file actually contains (e.g. dy*dx*(bytes/row+align) >= file size); truncated download or a hand-edited header.

Common situations: Incomplete downloads, files modified by scripts, BMPs truncated by asset packaging tools, malicious/fuzzed inputs to uCrop's native loader.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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