Yalantis/uCrop · error · CImgInstanceException

CImg<%s>::%s() [%u]: cubic_atXY(): Empty instance.

Error message

CImg<%s>::%s() [%u]: cubic_atXY(): Empty instance.

What it means

cubic_atXY() performs bicubic interpolation at floating-point (x,y) coordinates. The empty-instance check throws CImgInstanceException if the image has no pixel data, since bicubic sampling of a null buffer is meaningless and would read out of bounds.

Source

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

    /**
       Similar to cubic_atXY(float,float,int,int,const T) const, except that the return value is clamped to stay in the
       min/max range of the datatype \c T.
    **/
    T cubic_atXY_c(const float fx, const float fy, const int z, const int c, const T& out_value) const {
      return cimg::type<T>::cut(cubic_atXY(fx,fy,z,c,out_value));
    }

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

    Tfloat _cubic_atXY(const float fx, const float fy, const int z=0, const int c=0) const {
      const float
        nfx = cimg::type<float>::is_nan(fx)?0:cimg::cut(fx,0.f,width() - 1.f),
        nfy = cimg::type<float>::is_nan(fy)?0:cimg::cut(fy,0.f,height() - 1.f);
      const int x = (int)nfx, y = (int)nfy;
      const float dx = nfx - x, dy = nfy - y;
      const int
        px = x - 1<0?0:x - 1, nx = dx<=0?x:x + 1, ax = x + 2>=width()?width() - 1:x + 2,
        py = y - 1<0?0:y - 1, ny = dy<=0?y:y + 1, ay = y + 2>=height()?height() - 1:y + 2;
      const Tfloat
        Ipp = (Tfloat)(*this)(px,py,z,c), Icp = (Tfloat)(*this)(x,py,z,c), Inp = (Tfloat)(*this)(nx,py,z,c),
        Iap = (Tfloat)(*this)(ax,py,z,c),
        Ip = Icp + 0.5f*(dx*(-Ipp + Inp) + dx*dx*(2*Ipp - 5*Icp + 4*Inp - Iap) + dx*dx*dx*(-Ipp + 3*Icp - 3*Inp + Iap)),

View on GitHub (pinned to f788b534b4)

Solutions

  1. Check img.is_empty() (or operator bool) before any interpolation call.
  2. Handle load failures explicitly and propagate an error instead of passing the empty image on.
  3. Assert non-empty dimensions in the crop/transform entry point.
  4. Catch CImgInstanceException at the API boundary and return a meaningful error to the caller.

Example fix

// before
CImg<float> img = src.get_crop(0,0,-1,-1); // src empty -> crop also empty
float v = img.cubic_atXY(10.2f, 5.7f); // throws
// after
if (!src.is_empty()) {
  CImg<float> img = src.get_crop(0,0,src.width()-1,src.height()-1);
  float v = img.cubic_atXY(10.2f, 5.7f);
}
Defensive patterns

Strategy: validation

Validate before calling

if (img.is_empty()) throw std::runtime_error("source image not loaded");
float v = img.cubic_atXY(fx, fy, z, c);

Type guard

explicit operator bool exists in CImg: if (!img) { /* empty */ }

Try / catch

try {
  float v = img.cubic_atXY(fx, fy);
} catch (const CImgInstanceException& e) {
  Log("bicubic on empty image: %s", e.what());
  return kFallbackPixel;
}

Prevention

When it happens

Trigger: Calling cubic_atXY(fx,fy,...) on a default-constructed CImg, an image after clear(), or one where load() failed (e.g. missing/corrupt file), including calls made indirectly through get_resize/warp-style helpers that use it internally.

Common situations: Image warping/undistortion code fed an image that failed to load; crop pipelines in Android JNI (ucrop) where a bitmap decode failed before CImg was filled.

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/52235c0d53865d84. Report an issue: GitHub.