Yalantis/uCrop · error · CImgIOException

load_exr(): Unable to load EXR file

Error message

load_exr(): Unable to load EXR file '%s'.

What it means

load_exr() delegates to an EXR backend (OpenEXR or tinyexr). With tinyexr, LoadEXR() returns a nonzero error code; CImg then throws CImgIOException reporting that the EXR file could not be loaded. This fires after the filename was valid enough to attempt decoding, so it points at corrupt, missing, or malformed EXR content.

Solutions

  1. Verify the file exists and is readable (stat/fopen check) and is a real EXR (magic number 0x76 0x2f 0x31 0x01)
  2. Re-export the file from its source with standard (e.g. ZIP/PIZ) compression and no deep data
  3. Re-download/copy the file if it is truncated or corrupted
  4. Rebuild CImg with cimg_use_openexr for broader EXR support, or use a different EXR library/tool to convert

Example fix

// before
img.load_exr(path); // throws if unreadable
// after
std::FILE *f = std::fopen(path, "rb");
if (!f) throw std::runtime_error(std::string("cannot open ") + path);
unsigned char magic[4]; std::fread(magic,1,4,f); std::fclose(f);
if (!(magic[0]==0x76 && magic[1]==0x2f && magic[2]==0x31 && magic[3]==0x01))
  throw std::runtime_error("not a valid EXR file");
img.load_exr(path);
Defensive patterns

Strategy: try-catch

Validate before calling

std::FILE *f = std::fopen(path, "rb");
if (!f) throw std::runtime_error("cannot open EXR file");
unsigned char magic[4]; bool ok = std::fread(magic,1,4,f)==4;
std::fclose(f);
if (!ok || magic[0]!=0x76 || magic[1]!=0x2f || magic[2]!=0x31 || magic[3]!=0x01)
  throw std::runtime_error("not a valid EXR file");

Try / catch

try { img.load_exr(path); } catch (const cimg_library::CImgIOException &e) { /* unreadable/corrupt EXR */ fall_back_to_alternate_loader(path); }

Prevention

When it happens

Trigger: LoadEXR() returns nonzero: file does not exist or is unreadable, the file is truncated, it is not actually an EXR (e.g. renamed PNG), or it uses EXR features tinyexr cannot decode.

Common situations: Wrong path / permission problems; files corrupted in transfer; non-EXR data saved with an .exr extension; EXR variants (deep, exotic compression) unsupported by the built backend.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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

Appendix: source

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

      Imf::Array2D<Imf::Rgba> pixels;
      pixels.resizeErase(inheight,inwidth);
      file.setFrameBuffer(&pixels[0][0] - dw.min.x - dw.min.y*inwidth, 1, inwidth);
      file.readPixels(dw.min.y, dw.max.y);
      assign(inwidth,inheight,1,4);
      T *ptr_r = data(0,0,0,0), *ptr_g = data(0,0,0,1), *ptr_b = data(0,0,0,2), *ptr_a = data(0,0,0,3);
      cimg_forXY(*this,x,y) {
        *(ptr_r++) = (T)pixels[y][x].r;
        *(ptr_g++) = (T)pixels[y][x].g;
        *(ptr_b++) = (T)pixels[y][x].b;
        *(ptr_a++) = (T)pixels[y][x].a;
      }
      return *this;
#elif defined(cimg_use_tinyexr)
      float *res;
      const char *err = 0;
      int width = 0, height = 0;
      const int ret = LoadEXR(&res,&width,&height,filename,&err);
      if (ret) throw CImgIOException(_cimg_instance
                                     "load_exr(): Unable to load EXR file '%s'.",
                                     cimg_instance,filename);
      CImg<floatT>(res,4,width,height,1,true).get_permute_axes("yzcx").move_to(*this);
      std::free(res);
      return *this;
#else
      return load_other(filename);
#endif
    }

    //! Load image from a EXR file \newinstance.
    static CImg<T> get_load_exr(const char *const filename) {
      return CImg<T>().load_exr(filename);
    }

    //! Load image from a PANDORE-5 file.
    /**
      \param filename Filename, as a C-string.

View on GitHub (pinned to f788b534b4)