Yalantis/uCrop · error · CImgIOException
load_bmp(): Unable to load compressed data from '(*FILE)' in
Error message
load_bmp(): Unable to load compressed data from '(*FILE)' inputs.
What it means
BMP RLE compression (types 1 and 2, i.e. 8-bit and 4-bit RLE) cannot be decoded when the image was opened from a C stdio FILE* rather than a filename, because CImg falls back to a generic decoder that needs to reopen the file by path. It throws CImgIOException in this case.
Source
Thrown at ucrop/src/main/jni/CImg.h:56856
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;
if (buf_size<cimg_iobuffer) {
buffer.assign(buf_size,1,1,1,0);
cimg::fread(buffer._data,buf_size,nfile);
} else buffer.assign(dx_bytes + align_bytes);
unsigned char *ptrs = buffer;
// Decompress buffer (if necessary).
if (compression==1 || compression==2) {
if (file)
throw CImgIOException(_cimg_instance
"load_bmp(): Unable to load compressed data from '(*FILE)' inputs.",
cimg_instance);
else {
if (!file) cimg::fclose(nfile);
return load_other(filename);
}
}
// Read pixel data.
assign(dx,cimg::abs(dy),1,3,0);
switch (bpp) {
case 1 : { // Monochrome
if (colormap._width>=2) for (int y = height() - 1; y>=0; --y) {
if (buf_size>=cimg_iobuffer) {
if (!cimg::fread(ptrs=buffer._data,dx_bytes,nfile)) break;
cimg::fseek(nfile,align_bytes,SEEK_CUR);
}
unsigned char mask = 0x80, val = 0;View on GitHub (pinned to f788b534b4)
Solutions
- Pass the filename string instead of a FILE* so CImg can route to load_other()
- Re-encode the BMP uncompressed (BI_RGB) before loading
- Convert the image to PNG and load that
- Read the FILE* into memory and decode with a different library
Example fix
// before
std::FILE* f = fopen("rle.bmp","rb");
img.load_bmp(f);
// after
img.load_bmp("rle.bmp"); // path allows RLE fallback path Defensive patterns
Strategy: fallback
Validate before calling
unsigned compression = readU32LE(path,30);
bool isRle = compression == 1 || compression == 2;
if (isRle) { /* prefer filename-based load or re-encode */ } Type guard
bool isUncompressedBmp(unsigned biCompression) { return biCompression == 0; } Try / catch
try { img.load_bmp(fileHandle); }
catch (CImgIOException&) { img.load_bmp("rle.bmp"); // path-based fallback
}
// or catch (CImgIOException&) { img.assign(); } Prevention
- Pass filenames, not FILE*, when RLE BMPs are possible
- Re-encode RLE BMPs to uncompressed BI_RGB
- Convert to PNG for in-memory/asset loading
- Document that FILE*-based loading is limited for compressed formats
When it happens
Trigger: Calling load_bmp(std::FILE*) or load_bmp from an in-memory/FILE handle on an RLE-compressed BMP (biCompression == BI_RLE8 or BI_RLE4).
Common situations: Passing a memory-backed or already-opened FILE* (common in JNI/uCrop pipelines) instead of a filename when the BMP is RLE compressed.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- load_bmp(): Invalid offset %d specified in filename '%s'.
- load_bmp(): File size %lu for filename '%s' does not match e
- load_bmp(): Malformed header in filename '%s'.
- load(): Failed to open file '%s'.
- load(): Failed to recognize format of file '%s'.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/db895f5e620f4ebf.
Report an issue: GitHub.