Yalantis/uCrop · error · CImgInstanceException

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

Error message

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

What it means

CImg's cubic_atX() performs cubic interpolation along the X-axis of an image. Before doing so it checks is_empty(); if the image instance has zero width/height/depth/spectrum (never assigned or constructed empty), it throws CImgInstanceException. The library refuses to interpolate on an image with no pixel buffer.

Source

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

    /**
       Return a cubicly-interpolated pixel value of the image instance located at (\c fx,\c y,\c z,\c c),
       or the value of the nearest pixel location in the image instance in case of out-of-bounds access
       along the X-axis. The cubic interpolation uses Hermite splines.
       \param fx X-coordinate of the pixel value (float-valued).
       \param y Y-coordinate of the pixel value.
       \param z Z-coordinate of the pixel value.
       \param c C-coordinate of the pixel value.
       \note
       - Similar to cubic_atX(float,int,int,int,const T) const, except that the returned pixel value is
         approximated by a cubic interpolation along the X-axis.
       - If you know your image instance is \e not empty, you may rather use the slightly faster method
         \c _cubic_atX(float,int,int,int).
       \warning
       - There is \e no boundary checking performed for the Y,Z and C-coordinates, so they must be inside image bounds.
    **/
    Tfloat cubic_atX(const float fx, const int y=0, const int z=0, const int c=0) const {
      if (is_empty())
        throw CImgInstanceException(_cimg_instance
                                    "cubic_atX(): Empty instance.",
                                    cimg_instance);
      return _cubic_atX(fx,y,z,c);
    }

    Tfloat _cubic_atX(const float fx, const int y=0, 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);
      const int
        x = (int)nfx;
      const float
        dx = nfx - x;
      const int
        px = x - 1<0?0:x - 1, nx = dx>0?x + 1:x, ax = x + 2>=width()?width() - 1:x + 2;
      const Tfloat
        Ip = (Tfloat)(*this)(px,y,z,c), Ic = (Tfloat)(*this)(x,y,z,c),
        In = (Tfloat)(*this)(nx,y,z,c), Ia = (Tfloat)(*this)(ax,y,z,c);
      return Ic + 0.5f*(dx*(-Ip + In) + dx*dx*(2*Ip - 5*Ic + 4*In - Ia) + dx*dx*dx*(-Ip + 3*Ic - 3*In + Ia));

View on GitHub (pinned to f788b534b4)

Solutions

  1. Verify the image is non-empty before interpolating: if (img.is_empty()) handle/abort before calling cubic_atX().
  2. Check the return value of load()/assign() so a failed load doesn't leave an empty image flowing into interpolation.
  3. Ensure the crop/resize code never produces zero-dimension images (clamp width/height to >=1).
  4. Wrap the interpolation call in try/catch for CImgInstanceException as a last-resort guard.

Example fix

// before
CImg<float> img;
float v = img.cubic_atX(2.5f, 0, 0, 0); // throws: empty instance
// after
CImg<float> img;
img.load("in.png");
if (!img.is_empty()) {
  float v = img.cubic_atX(2.5f, 0, 0, 0);
}
Defensive patterns

Strategy: validation

Validate before calling

if (img.is_empty()) { /* handle: skip, use default, or report error */ return; }
float v = img.cubic_atX(fx, y, z, c);

Type guard

bool usable(const CImg<T>& img) { return !img.is_empty() && img.width() > 0; }

Try / catch

try {
  float v = img.cubic_atX(fx, y, z, c);
} catch (const CImgInstanceException& e) {
  // log e.what(); fall back to nearest-neighbor or abort the crop
}

Prevention

When it happens

Trigger: Calling cubic_atX(fx,...) on a CImg constructed with the default constructor or with zero-size dimensions (e.g. CImg<float> img; img.cubic_atX(2.5f)); also when an image became empty after a failed load or clear()/assign() call.

Common situations: An image failed to load from disk (load() returned an empty image) and cropping/resampling code proceeds anyway; a crop rect computed to zero size before passing the image to ucrop interpolation; uninitialized member images in a class.

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/0c4a13601142be08. Report an issue: GitHub.