Yalantis/uCrop · error · CImgArgumentException

draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p

Error message

draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have different dimensions.

What it means

When drawing a 3D line with depth testing, the caller must supply a Z-buffer image with exactly the same width and height as the target image (checked via is_sameXY). If the zbuffer argument has different dimensions (or is empty), the library throws this CImgArgumentException because depth writes would be out of bounds.

Source

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

       \param z1 Z-coordinate of the ending point.
       \param color Pointer to \c spectrum() consecutive values of type \c T, defining the drawing color.
       \param opacity Drawing opacity.
       \param pattern An integer whose bits describe the line pattern.
       \param init_hatch Tells if a reinitialization of the hash state must be done.
    **/
    template<typename tz, typename tc>
    CImg<T>& draw_line(CImg<tz>& zbuffer,
                       int x0, int y0, const float z0,
                       int x1, int y1, const float z1,
                       const tc *const color, const float opacity=1,
                       const unsigned int pattern=~0U, const bool init_hatch=true) {
      if (is_empty() || z0<=0 || z1<=0 || !opacity || !pattern) return *this;
      if (!color)
        throw CImgArgumentException(_cimg_instance
                                    "draw_line(): Specified color is (null).",
                                    cimg_instance);
      if (!is_sameXY(zbuffer))
        throw CImgArgumentException(_cimg_instance
                                    "draw_line(): Instance and specified Z-buffer (%u,%u,%u,%u,%p) have "
                                    "different dimensions.",
                                    cimg_instance,
                                    zbuffer._width,zbuffer._height,zbuffer._depth,zbuffer._spectrum,zbuffer._data);

      if (std::min(y0,y1)>=height() || std::max(y0,y1)<0 || std::min(x0,x1)>=width() || std::max(x0,x1)<0)
        return *this;
      int
        w1 = width() - 1, h1 = height() - 1,
        dx01 = x1 - x0, dy01 = y1 - y0;
      float iz0 = 1/z0, iz1 = 1/z1, diz01 = iz1 - iz0;

      const bool is_horizontal = cimg::abs(dx01)>cimg::abs(dy01);
      if (is_horizontal) cimg::swap(x0,y0,x1,y1,w1,h1,dx01,dy01);
      if (pattern==~0U && y0>y1) {
        cimg::swap(x0,x1,y0,y1,iz0,iz1);
        dx01*=-1; dy01*=-1; diz01*=-1;
      }

View on GitHub (pinned to f788b534b4)

Solutions

  1. Allocate the Z-buffer with the same dimensions as the target: CImg<float> zbuffer(img.width(),img.height(),1,1,0).
  2. Re-resize the zbuffer whenever the target image changes size: zbuffer.assign(img.width(),img.height(),1,1,0); zbuffer.fill(0);
  3. Guard the call: if (zbuffer && img.is_sameXY(zbuffer)) img.draw_line(...,zbuffer);
  4. If no depth testing is needed, call the 2D draw_line overload that does not take a zbuffer.

Example fix

// before
CImg<float> zbuffer; // empty
img.draw_line(0,0,1,50,50,1,color,zbuffer); // throws

// after
CImg<float> zbuffer(img.width(),img.height(),1,1,0);
zbuffer.fill(0);
img.draw_line(0,0,1,50,50,1,color,zbuffer);
Defensive patterns

Strategy: validation

Validate before calling

if (zbuffer && img.is_sameXY(zbuffer)) {
  img.draw_line(x0,y0,z0,x1,y1,z1,color,zbuffer);
} else {
  zbuffer.assign(img.width(),img.height(),1,1,0);
}

Type guard

bool usable_zbuffer(const CImg<float>& zb, const CImg<unsigned char>& img) {
  return !zb.is_empty() && img.is_sameXY(zb);
}

Try / catch

try {
  img.draw_line(x0,y0,z0,x1,y1,z1,color,zbuffer);
} catch (CImgArgumentException& e) {
  zbuffer.assign(img.width(),img.height(),1,1,0);
  std::fprintf(stderr, "zbuffer resized: %s\n", e.what());
}

Prevention

When it happens

Trigger: Calling img.draw_line(x0,y0,z0,x1,y1,z1,color,zbuffer) where zbuffer was allocated with a different size than img, or is a default-constructed/empty CImg, or was resized after img was resized (e.g. image loaded/assign() later while zbuffer kept old dimensions).

Common situations: Resizing the target image (resize/assign/load) without also resizing the Z-buffer; reusing one zbuffer across images of different sizes; forgetting to initialize the zbuffer before the first draw call; mixing images from different loads in a render loop.

Related errors


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