Yalantis/uCrop · error · CImgInstanceException

linear_atXY(): Empty instance.

Error message

linear_atXY(): Empty instance.

What it means

CImg<T>::linear_atXY(fx,fy,z,c) returns a bilinearly interpolated pixel value with Neumann boundary conditions on X and Y. It throws CImgInstanceException when the image is empty, as no buffer exists for interpolation. Z and C are not bounds-checked here.

Source

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

        dx = fx - x,
        dy = fy - y;
      const Tfloat
        Icc = (Tfloat)atXY(x,y,z,c,out_value),  Inc = (Tfloat)atXY(nx,y,z,c,out_value),
        Icn = (Tfloat)atXY(x,ny,z,c,out_value), Inn = (Tfloat)atXY(nx,ny,z,c,out_value);
      return Icc + (Inc - Icc + (Icc + Inn - Icn - Inc)*dy)*dx + (Icn - Icc)*dy;
    }

    //! Return pixel value, using linear interpolation and Neumann boundary conditions for the X and Y-coordinates.
    /**
       Similar to linear_atX(float,int,int,int) const, except that the linear interpolation and the boundary checking
       are achieved both for X and Y-coordinates.
       \note
       - If you know your image instance is \e not empty, you may rather use the slightly faster method
         \c _linear_atXY(float,float,int,int).
    **/
    Tfloat linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "linear_atXY(): Empty instance.",
                                    cimg_instance);

      return _linear_atXY(fx,fy,z,c);
    }

    Tfloat _linear_atXY(const float fx, const float fy, const int z=0, const int c=0) const {
      const float
        nfx = cimg::cut(fx,0.f,width() - 1.f),
        nfy = cimg::cut(fy,0.f,height() - 1.f);
      const unsigned int
        x = (unsigned int)nfx,
        y = (unsigned int)nfy;
      const float
        dx = nfx - x,
        dy = nfy - y;
      const unsigned int
        nx = dx>0?x + 1:x,

View on GitHub (pinned to f788b534b4)

Solutions

  1. Guard with if (!img.is_empty()) before calling linear_atXY.
  2. Check that load()/imread() produced a non-empty image (dimensions > 0).
  3. Allocate the image explicitly with assign(w,h) when constructed by default.
  4. Use _linear_atXY() in hot loops only after a single upfront emptiness check.

Example fix

// before
CImg<unsigned char> frame; // never filled
float v = frame.linear_atXY(10.2f, 5.7f);
// after
cimg_for(img, ...) or:
if (!frame.is_empty()) {
  float v = frame.linear_atXY(10.2f, 5.7f);
}
Defensive patterns

Strategy: validation

Validate before calling

if (img.is_empty()) { img.assign(w, h); /* or load */ } float v = img.linear_atXY(fx, fy);

Type guard

inline bool ready(const cimg_library::CImg<T>& img) { return !img.is_empty(); }

Try / catch

try { float v = img.linear_atXY(fx, fy); } catch (cimg_library::CImgInstanceException& e) { std::cerr << e.what() << '\n'; /* reload image */ }

Prevention

When it happens

Trigger: Calling linear_atXY() on an empty CImg instance (default-constructed, failed load, zero-sized dimensions).

Common situations: Image registration or feature sampling code fed an unloaded image; reading from a video frame that was never captured; empty ROI extraction upstream.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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