Yalantis/uCrop · error · CImgIOException

load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %

Error message

load_cimg(): Invalid specified size (%u,%u,%u,%u) of image %u in file '%s'.

What it means

While reading a multi-image .cimg file, load_cimg() parses each image's header line '%u %u %u %u #<csiz>' and throws if fewer than 4 unsigned dimensions can be extracted (CImg.h:66745). The file is corrupt, truncated, or not a valid .cimg stream.

Source

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

}
#else
#define _cimgz_load_cimg_case(Tss) \
   throw CImgIOException(_cimglist_instance \
                         "load_cimg(): Unable to load compressed data from file '%s' unless zlib is enabled.", \
                         cimglist_instance, \
                         filename?filename:"(FILE*)");
#endif

#define _cimg_load_cimg_case(Ts1,Ts2,Ts3,Tss) \
      if (!loaded && ((Ts1 && !cimg::strcasecmp(Ts1,str_pixeltype)) || \
                      (Ts2 && !cimg::strcasecmp(Ts2,str_pixeltype)) || \
                      (Ts3 && !cimg::strcasecmp(Ts3,str_pixeltype)))) { \
        const bool is_bool = cimg::type<Tss>::string()==cimg::type<bool>::string(); \
        for (unsigned int l = 0; l<N; ++l) { \
          j = 0; while ((i=std::fgetc(nfile))!='\n' && i>=0 && j<255) tmp[j++] = (char)i; tmp[j] = 0; \
          W = H = D = C = 0; csiz = 0; \
          if ((err = cimg_sscanf(tmp,"%u %u %u %u #" cimg_fuint64,&W,&H,&D,&C,&csiz))<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) { \
            CImg<T> &img = _data[l]; \
            if (err==5) _cimgz_load_cimg_case(Tss) \
            else { \
              img.assign(W,H,D,C); \
              T *ptrd = img._data; \
              if (is_bool) { \
                CImg<ucharT> raw; \
                for (ulongT to_read = img.size(); to_read; ) { \
                  raw.assign((unsigned int)std::min(to_read,cimg_iobuffer)); \
                  cimg::fread(raw._data,raw._width,nfile); \
                  CImg<T>(ptrd,std::min(8*raw._width,(unsigned int)(img.end() - ptrd)),1,1,1,true).\
                    _uchar2bool(raw,raw._width,false); \
                  to_read-=raw._width; \
                } \

View on GitHub (pinned to f788b534b4)

Solutions

  1. Regenerate or re-download the .cimg file and verify its integrity (size vs. header-declared csiz).
  2. Open the file in a hex editor and check the header lines match 'W H D C #csiz'.
  3. Confirm the transfer used binary mode and no line-ending mangling.
  4. Validate the header yourself before loading and fall back to re-export from the source.

Example fix

// before
CImgList<unsigned char> imgs;
imgs.load_cimg(partialFilePath); // throws on truncated header

// after
std::FILE* f = std::fopen(partialFilePath, "rb");
char line[256];
unsigned W, H, D, C; unsigned long long csiz;
bool ok = std::fgets(line, sizeof line, f) &&
          std::sscanf(line, "%u %u %u %u #%llu", &W, &H, &D, &C, &csiz) >= 4;
std::fclose(f);
if (ok) imgs.load_cimg(partialFilePath);
else reExportCimgFile(partialFilePath);
Defensive patterns

Strategy: validation

Validate before calling

bool validCimgHeader(const char* path) {
  std::FILE* f = std::fopen(path, "rb"); if (!f) return false;
  char line[256] = {0};
  bool ok = std::fgets(line, sizeof line, f) != nullptr;
  unsigned N, W, H, D, C; unsigned long long csiz; char pt[64], en[64];
  if (ok && std::sscanf(line, "%u %63s %63s", &N, pt, en) == 3) {
    ok = true;
    for (unsigned l = 0; l < N && ok; ++l) {
      if (!std::fgets(line, sizeof line, f)) { ok = false; break; }
      ok = std::sscanf(line, "%u %u %u %u #%llu", &W,&H,&D,&C,&csiz) >= 4;
    }
  } else ok = false;
  std::fclose(f);
  return ok;
}

Try / catch

try {
  imgs.load_cimg(path);
} catch (cimg_library::CImgIOException& e) {
  logError("corrupt .cimg (bad size header): %s", e.what());
  reFetchOrReExport(path);
}

Prevention

When it happens

Trigger: Calling CImgList::load_cimg(filename) on a file whose per-image header line contains non-numeric or missing dimension fields (sscanf returns <4), e.g. a truncated download or a file corrupted mid-transfer.

Common situations: Interrupted FTP/HTTP transfer leaving a partial .cimg; text-mode transfer on Windows corrupting binary data; hand-edited or concatenated .cimg files; using a plain binary file that happens to be passed as .cimg.

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


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