Yalantis/uCrop · error · CImgIOException
CImg<%s>::load_inr(): INRIMAGE-4 header not found.
Error message
CImg<%s>::load_inr(): INRIMAGE-4 header not found.
What it means
CImg's INR (INRIMAGE-4) loader requires the file to begin with the magic token '#INRIMAGE-4#{'. _load_inr_header() reads the first token via fscanf and, if strncasecmp against that magic fails, throws this exception. It means the file is not an INRIMAGE-4 file (or the magic line is corrupted).
Source
Thrown at ucrop/src/main/jni/CImg.h:58649
}
//! Load image from an INRIMAGE-4 file \overloading.
CImg<T>& load_inr(std::FILE *const file, float *const voxel_size=0) {
return _load_inr(file,0,voxel_size);
}
//! Load image from an INRIMAGE-4 file \newinstance.
static CImg<T> get_load_inr(std::FILE *const file, float *voxel_size=0) {
return CImg<T>().load_inr(file,voxel_size);
}
static void _load_inr_header(std::FILE *file, int out[8], float *const voxel_size) {
CImg<charT> item(1024), tmp1(64), tmp2(64);
*item = *tmp1 = *tmp2 = 0;
out[0] = std::fscanf(file,"%63s",item._data);
out[0] = out[1] = out[2] = out[3] = out[5] = 1; out[4] = out[6] = out[7] = -1;
if (cimg::strncasecmp(item,"#INRIMAGE-4#{",13)!=0)
throw CImgIOException("CImg<%s>::load_inr(): INRIMAGE-4 header not found.",
pixel_type());
while (std::fscanf(file," %63[^\n]%*c",item._data)!=EOF && std::strncmp(item,"##}",3)) {
cimg_sscanf(item," XDIM%*[^0-9]%d",out);
cimg_sscanf(item," YDIM%*[^0-9]%d",out + 1);
cimg_sscanf(item," ZDIM%*[^0-9]%d",out + 2);
cimg_sscanf(item," VDIM%*[^0-9]%d",out + 3);
cimg_sscanf(item," PIXSIZE%*[^0-9]%d",out + 6);
if (voxel_size) {
cimg_sscanf(item," VX%*[^0-9.+-]%f",voxel_size);
cimg_sscanf(item," VY%*[^0-9.+-]%f",voxel_size + 1);
cimg_sscanf(item," VZ%*[^0-9.+-]%f",voxel_size + 2);
}
if (cimg_sscanf(item," CPU%*[ =]%s",tmp1._data)) out[7] = cimg::strncasecmp(tmp1,"sun",3)?0:1;
switch (cimg_sscanf(item," TYPE%*[ =]%s %s",tmp1._data,tmp2._data)) {
case 0 : break;
case 2 :
out[5] = cimg::strncasecmp(tmp1,"unsigned",8)?1:0;View on GitHub (pinned to f788b534b4)
Solutions
- Check the first 13 bytes of the file equal '#INRIMAGE-4#{' before calling load_inr().
- Convert the file to INRIMAGE-4 (or another supported format) using the original tool (e.g. InrImage/Greyscale conversion utilities).
- Verify the extension matches the real format and let CImg auto-detect via load() with the correct extension.
- If the file starts with a BOM or extra whitespace/newline, strip it — the magic must be the first token.
- Catch CImgIOException and attempt alternative loaders based on magic-byte sniffing.
Example fix
// before
img.load_inr("volume.inr"); // actually a DICOM file renamed
// after
std::FILE* f = std::fopen("volume.inr","rb"); char magic[14] = {0};
std::fread(magic,1,13,f); std::fclose(f);
if (std::strncmp(magic, "#INRIMAGE-4#{", 13) == 0) img.load_inr("volume.inr");
else img.load_medcon_external("volume.inr"); // or proper converter Defensive patterns
Strategy: validation
Validate before calling
bool isInrImage(const std::string& path) {
std::FILE* f = std::fopen(path.c_str(), "rb"); if (!f) return false;
char magic[14] = {0}; std::fread(magic, 1, 13, f); std::fclose(f);
return cimg::strncasecmp(magic, "#INRIMAGE-4#{", 13) == 0;
} Type guard
bool hasInrMagic(const char* magic) { return magic && std::strncmp(magic, "#INRIMAGE-4#{", 13) == 0; } Try / catch
try { img.load_inr(path); }
catch (CImgIOException& e) { fprintf(stderr, "Not INRIMAGE-4, sniffing real format...\n"); img.load(path.c_str()); } Prevention
- Sniff magic bytes before choosing a loader.
- Keep file extensions truthful — never rename to .inr.
- Re-export via the original InrImage toolchain if headers were stripped.
- Strip BOMs/leading whitespace from converted files.
When it happens
Trigger: Calling CImg::load_inr() or load() on a file dispatched as .inr/.inr.gz whose first bytes are not '#INRIMAGE-4#{' — e.g. a DICOM/PNM file renamed to .inr, or an older INRIMAGE-3 header.
Common situations: Wrong extension routing in load(): a data file with .inr extension that is actually another format; gzipped INR handled elsewhere and passed raw; files re-saved by tools that dropped the header comment block.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- load(): Failed to recognize format of file '%s'.
- load_ascii(): Invalid ascii header in file '%s', image dimen
- load_dlm(): Invalid DLM file '%s'.
- load_bmp(): Invalid BMP file '%s'.
- load_analyze(): Invalid header size (%u) specified in file '
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/38774b50ac945a03.
Report an issue: GitHub.