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

  1. 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.
  2. Use ~0U only for 'until the end' and never on a dimension that may be 0.
  3. 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

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


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