Yalantis/uCrop · error · CImgArgumentException

load_tiff(): Unable to read sub-images from file '%s' unless

Error message

load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.

What it means

When CImg is built without libtiff (cimg_use_tiff undefined), load_tiff() can only load a single-image file via load_other(). If the caller requests any sub-image selection (non-zero first_frame, a bounded last_frame, or step_frame > 1), the library refuses with this argument error because multi-frame reading requires libtiff.

Source

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

     **/
    CImg<T>& load_tiff(const char *const filename,
                       const unsigned int first_frame=0, const unsigned int last_frame=~0U,
                       const unsigned int step_frame=1, unsigned int *const bits_per_value=0,
                       float *const voxel_size=0, CImg<charT> *const description=0) {
      if (!filename)
        throw CImgArgumentException(_cimg_instance
                                    "load_tiff(): Specified filename is (null).",
                                    cimg_instance);

      const unsigned int
        nfirst_frame = first_frame<last_frame?first_frame:last_frame,
        nstep_frame = step_frame?step_frame:1;
      unsigned int nlast_frame = first_frame<last_frame?last_frame:first_frame;

#ifndef cimg_use_tiff
      cimg::unused(bits_per_value,voxel_size,description);
      if (nfirst_frame || nlast_frame!=~0U || nstep_frame>1)
        throw CImgArgumentException(_cimg_instance
                                    "load_tiff(): Unable to read sub-images from file '%s' unless libtiff is enabled.",
                                    cimg_instance,
                                    filename);
      return load_other(filename);
#else
#if cimg_verbosity<3
      TIFFSetWarningHandler(0);
      TIFFSetErrorHandler(0);
#endif
      TIFF *tif = TIFFOpen(filename,"r");
      if (tif) {
        unsigned int nb_images = 0;
        do ++nb_images; while (TIFFReadDirectory(tif));
        if (nfirst_frame>=nb_images || (nlast_frame!=~0U && nlast_frame>=nb_images))
          cimg::warn(_cimg_instance
                     "load_tiff(): File '%s' contains %u image(s) while specified frame range is [%u,%u] (step %u).",
                     cimg_instance,
                     filename,nb_images,nfirst_frame,nlast_frame,nstep_frame);

View on GitHub (pinned to f788b534b4)

Solutions

  1. Build CImg with cimg_use_tiff defined and link against libtiff to enable multi-frame reads.
  2. If single-image loading suffices, call load_tiff(filename) with default frame arguments (0, ~0U, 1).
  3. Pre-decode the TIFF with another library and pass raw data to CImg.

Example fix

// before (no libtiff build)
img.load_tiff("stack.tif", 3);
// after: default args work without libtiff
img.load_tiff("stack.tif");
Defensive patterns

Strategy: fallback

Validate before calling

#ifndef cimg_use_tiff
  if (firstFrame != 0 || stepFrame > 1) throw std::logic_error("sub-image reads need libtiff build");
#endif

Try / catch

try { img.load_tiff(f, frame); }
catch (CImgArgumentException &e) { img.load_tiff(f); /* single-image fallback */ }

Prevention

When it happens

Trigger: img.load_tiff("file.tif", 2) or load_tiff("f.tif", 0, 5) or load_tiff("f.tif", 0, ~0U, 2) compiled without cimg_use_tiff.

Common situations: Building the Android/JNI project without libtiff linked, then attempting to read a specific page of a multi-page TIFF stack; a build that previously had libtiff was rebuilt without it.

Understand the failure class

Background: "X is not installed. Please install it with pip install Y": missing optional dependency errors — ImportError/ValueError raised when a library's optional extra was never installed — this error's family across 22 libraries.

Related errors


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