Yalantis/uCrop · error · CImgIOException

load_bmp(): Invalid BMP file '%s'.

Error message

load_bmp(): Invalid BMP file '%s'.

What it means

load_bmp() reads the first 54 bytes and checks the 'BM' magic; a mismatch throws CImgIOException because the file is not a BMP. This fires before any header parsing, so it is purely a signature check.

Source

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

    //! Load image from a BMP file \newinstance.
    static CImg<T> get_load_bmp(std::FILE *const file) {
      return CImg<T>().load_bmp(file);
    }

    CImg<T>& _load_bmp(std::FILE *const file, const char *const filename) {
      if (!file && !filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_bmp(): Specified filename is (null).",
                                    cimg_instance);

      const ulongT fsiz = (ulongT)(file?cimg::fsize(file):cimg::fsize(filename));
      std::FILE *const nfile = file?file:cimg::fopen(filename,"rb");
      CImg<ucharT> header(54);
      cimg::fread(header._data,54,nfile);
      if (*header!='B' || header[1]!='M') {
        if (!file) cimg::fclose(nfile);
        throw CImgIOException(_cimg_instance
                              "load_bmp(): Invalid BMP file '%s'.",
                              cimg_instance,
                              filename?filename:"(FILE*)");
      }

      // Read header and pixel buffer.
      int
        file_size = header[0x02] + (header[0x03]<<8) + (header[0x04]<<16) + (header[0x05]<<24),
        offset = header[0x0A] + (header[0x0B]<<8) + (header[0x0C]<<16) + (header[0x0D]<<24),
        header_size = header[0x0E] + (header[0x0F]<<8) + (header[0x10]<<16) + (header[0x11]<<24),
        dx = header[0x12] + (header[0x13]<<8) + (header[0x14]<<16) + (header[0x15]<<24),
        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

View on GitHub (pinned to f788b534b4)

Solutions

  1. Verify the file's first two bytes are 'BM' before calling load_bmp.
  2. Use img.load(path) to auto-detect the real format instead of forcing the BMP loader.
  3. Re-export or re-download the image if it is corrupt.
  4. Decode with a tolerant loader (e.g. BitmapFactory) and convert to BMP if BMP input is required.

Example fix

// before
img.load_bmp(path);
// after
std::ifstream f(path, std::ios::binary); char m[2]; f.read(m,2);
if (m[0]=='B' && m[1]=='M') img.load_bmp(path);
else img.load(path); // auto-detect
Defensive patterns

Strategy: validation

Validate before calling

bool isBmpMagic(const char* p){ std::ifstream f(p,std::ios::binary); char m[2]={0}; f.read(m,2); return m[0]=='B'&&m[1]=='M'; }

Try / catch

try { img.load_bmp(path); } catch (cimg_library::CImgIOException& e) { /* not a BMP: fall back to auto-detect */ img.load(path); }

Prevention

When it happens

Trigger: img.load_bmp(path) on a file whose first two bytes are not 'B','M' — e.g. a PNG/JPEG renamed to .bmp, a corrupted download, or a file starting with a BOM.

Common situations: Relying on file extension instead of actual content; build scripts copying wrong assets; partial writes that truncated the header.

Related errors


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