Yalantis/uCrop · error · CImgIOException

load_bmp(): Invalid offset %d specified in filename '%s'.

Error message

load_bmp(): Invalid offset %d specified in filename '%s'.

What it means

CImg's load_bmp() rejects a BMP whose header-declared pixel-data offset is negative or extends beyond the file size. The offset field of the BMP header tells where image bits start; a nonsensical value means the file is corrupt or not a valid BMP. CImg throws CImgIOException naming the offending file.

Source

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

        dy = header[0x16] + (header[0x17]<<8) + (header[0x18]<<16) + (header[0x19]<<24),
        compression = header[0x1E] + (header[0x1F]<<8) + (header[0x20]<<16) + (header[0x21]<<24),
        nb_colors = header[0x2E] + (header[0x2F]<<8) + (header[0x30]<<16) + (header[0x31]<<24),
        bpp = header[0x1C] + (header[0x1D]<<8);

      if ((ulongT)file_size!=fsiz)
        throw CImgIOException(_cimg_instance
                              "load_bmp(): Invalid file_size %d specified in filename '%s' (expected %lu).",
                              cimg_instance,
                              file_size,filename?filename:"(FILE*)",fsiz);

      if (header_size<0 || header_size>=file_size)
        throw CImgIOException(_cimg_instance
                              "load_bmp(): Invalid header size %d specified in filename '%s'.",
                              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);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Verify the BMP file opens correctly in another tool (e.g. identify from ImageMagick); re-export or re-obtain the file
  2. Re-export the image as BMP from a reliable encoder or convert to PNG and load that
  3. Check that the asset was not truncated during copy/download (compare file size with source)
  4. Validate header fields (bfOffBits <= file size) before handing the file to CImg

Example fix

// before
img.load_bmp("corrupt.bmp");
// after
std::FILE* f = std::fopen("corrupt.bmp","rb");
unsigned char hdr[26];
if (fread(hdr,1,26,f)!=26) { /* handle */ }
unsigned off = hdr[10] | (hdr[11]<<8) | (hdr[12]<<16) | ((unsigned)hdr[13]<<24);
fseek(f,0,SEEK_END); long size = ftell(f); fclose(f);
if (off < (unsigned)size) img.load_bmp("corrupt.bmp");
Defensive patterns

Strategy: validation

Validate before calling

long fileSize = getFileSize(path);
unsigned off = readU32LE(path, 10); // bfOffBits
if (off == 0 || off >= (unsigned)fileSize) throw std::runtime_error("bad bmp offset");

Type guard

bool isValidBmpOffset(long fileSize, unsigned offset) { return offset > 0 && offset < fileSize; }

Try / catch

try { img.load_bmp(path); }
catch (CImgIOException&) { img.assign(); /* fallback */ }

Prevention

When it happens

Trigger: Calling load_bmp()/CImg<T>::load_bmp on a truncated or corrupted .bmp file, or a file whose BITMAPFILEHEADER::bfOffBits exceeds the actual byte count, or passing a non-BMP file with a .bmp extension.

Common situations: Partially downloaded BMP, BMP produced by a buggy encoder, renamed file, data corrupted during resource bundling in an Android project (ucrop JNI).

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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