Yalantis/uCrop · error · CImgArgumentException
load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u)
Error message
load_cimg(): Invalid specified coordinates [%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) because image [%u] in file '%s' has size (%u,%u,%u,%u).
What it means
The ROI load_cimg() overload normalizes ~0U ('to the end') bounds to W-1/H-1/D-1/C-1 and throws CImgArgumentException when any upper bound still exceeds the actual image dimensions in the file (CImg.h:66915). The requested coordinate window is outside the stored image.
Source
Thrown at ucrop/src/main/jni/CImg.h:66915
(Ts3 && !cimg::strcasecmp(Ts3,str_pixeltype)))) { \
for (unsigned int l = 0; l<=nn1; ++l) { \
j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0) tmp[j++] = (char)i; tmp[j] = 0; \
W = H = D = C = 0; \
if (cimg_sscanf(tmp,"%u %u %u %u",&W,&H,&D,&C)!=4) \
throw CImgIOException(_cimglist_instance \
"load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'", \
cimglist_instance, \
W,H,D,C,l,filename?filename:"(FILE*)"); \
if (W*H*D*C>0) { \
if (l<nn0 || nx0>=W || ny0>=H || nz0>=D || nc0>=C) cimg::fseek(nfile,W*H*D*C*sizeof(Tss),SEEK_CUR); \
else { \
const unsigned int \
_nx1 = nx1==~0U?W - 1:nx1, \
_ny1 = ny1==~0U?H - 1:ny1, \
_nz1 = nz1==~0U?D - 1:nz1, \
_nc1 = nc1==~0U?C - 1:nc1; \
if (_nx1>=W || _ny1>=H || _nz1>=D || _nc1>=C) \
throw CImgArgumentException(_cimglist_instance \
"load_cimg(): Invalid specified coordinates " \
"[%u](%u,%u,%u,%u) -> [%u](%u,%u,%u,%u) " \
"because image [%u] in file '%s' has size (%u,%u,%u,%u).", \
cimglist_instance, \
n0,x0,y0,z0,c0,n1,x1,y1,z1,c1,l,filename?filename:"(FILE*)",W,H,D,C); \
CImg<Tss> raw(1 + _nx1 - nx0); \
CImg<T> &img = _data[l - nn0]; \
img.assign(1 + _nx1 - nx0,1 + _ny1 - ny0,1 + _nz1 - nz0,1 + _nc1 - nc0); \
T *ptrd = img._data; \
ulongT skipvb = nc0*W*H*D*sizeof(Tss); \
if (skipvb) cimg::fseek(nfile,skipvb,SEEK_CUR); \
for (unsigned int c = 1 + _nc1 - nc0; c; --c) { \
const ulongT skipzb = nz0*W*H*sizeof(Tss); \
if (skipzb) cimg::fseek(nfile,skipzb,SEEK_CUR); \
for (unsigned int z = 1 + _nz1 - nz0; z; --z) { \
const ulongT skipyb = ny0*W*sizeof(Tss); \
if (skipyb) cimg::fseek(nfile,skipyb,SEEK_CUR); \
for (unsigned int y = 1 + _ny1 - ny0; y; --y) { \View on GitHub (pinned to f788b534b4)
Solutions
- Read the target image's W,H,D,C from the .cimg header first and clamp x1<=W-1, y1<=H-1, z1<=D-1, c1<=C-1.
- Use ~0U only for 'until the end' and never on a dimension that may be 0.
- Fix hardcoded ROI constants to match the actual dataset geometry.
Example fix
// before
imgs.load_cimg(path, 0,0, 0,255, 0,255, 0,0, 0,3); // image has 3 channels
// after
unsigned W,H,D,C; readCimgHeader(path, 0, W,H,D,C);
imgs.load_cimg(path, 0,0,
0, std::min(255u, W-1),
0, std::min(255u, H-1),
0,0,
0, std::min(3u, C-1)); Defensive patterns
Strategy: validation
Validate before calling
bool roiInBounds(const char* path, unsigned imgIdx,
unsigned x0,unsigned x1, unsigned y0,unsigned y1,
unsigned z0,unsigned z1, unsigned c0,unsigned c1) {
std::FILE* f = std::fopen(path, "rb"); if (!f) return false;
char line[256] = {0};
unsigned N = 0, W = 0, H = 0, D = 0, C = 0;
bool ok = std::fgets(line, sizeof line, f) && std::sscanf(line, "%u", &N) == 1;
for (unsigned l = 0; ok && l <= imgIdx; ++l)
ok = std::fgets(line, sizeof line, f) &&
std::sscanf(line, "%u %u %u %u", &W,&H,&D,&C) == 4;
std::fclose(f);
if (!ok) return false;
return (x1 == ~0U || x1 < W) && (y1 == ~0U || y1 < H) &&
(z1 == ~0U || z1 < D) && (c1 == ~0U || c1 < C) &&
x0 < W && y0 < H && z0 < D && c0 < C;
} Try / catch
try {
imgs.load_cimg(path, n0,n1, x0,x1, y0,y1, z0,z1, c0,c1);
} catch (cimg_library::CImgArgumentException& e) {
logError("ROI out of bounds: %s", e.what());
// clamp ROI from actual header dims and retry
} Prevention
- Read W,H,D,C from the header and clamp explicit upper bounds to dim-1
- Treat ~0U as 'to the end' only; never on possibly-zero dimensions
- Don't assume channel count (RGB vs RGBA) — read it from the header
- Keep ROI constants in one config validated against dataset geometry
When it happens
Trigger: Calling load_cimg(file, n0,n1, x0,x1, ...) where x1/y1/z1/c1 (explicit or ~0U) is >= the image's W/H/D/C read from the header, e.g. asking for channels 0..3 of a 3-channel image, or hardcoding ~0U for a dimension that is 0.
Common situations: Assuming RGBA (4 channels) when data was saved RGB; hardcoded crop sizes larger than the actual volume; images dimension-mismatched after a pipeline change; off-by-one using W instead of W-1 as inclusive max.
Related errors
- load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %
- cimg::mod(): Specified modulo value is 0.
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'swap()':
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()':
- "[" cimg_appname "_math_parser] CImg<%s>: Function 'copy()':
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/5e536c44431788d0.
Report an issue: GitHub.