Yalantis/uCrop · error · CImgInstanceException

haar(): Sub-image height %u is not even.

Error message

haar(): Sub-image height %u is not even.

What it means

CImg::haar() performing the single-scale Haar transform along the Y axis requires the sub-image height (h = _height/2) to be even or equal to 1; otherwise the pairwise splitting of rows cannot proceed and it throws CImgInstanceException.

Solutions

  1. Pad or resize the height to a power of two before the transform.
  2. Choose an axis ('x' or 'z') whose dimension satisfies the evenness constraint if the data allows.
  3. Use the multi-scale form (nb_scales>1) if appropriate for your sizes.
  4. Crop to a size where height/2 is even or 1.

Example fix

// before
CImg<> out = img.get_haar('y', false, 1); // height 6 -> h=3, odd
// after
CImg<> padded = img.get_resize(img.width(), 8);
CImg<> out = padded.get_haar('y', false, 1);
Defensive patterns

Strategy: validation

Validate before calling

if (unsigned h = img.height()/2; (h % 2) && h != 1) img = img.get_resize(img.width(), nextPow2(img.height()));

Type guard

bool haarYOk(const CImg<T>& img) {
  unsigned h = img.height()/2;
  return h == 0 || !(h % 2) || h == 1;
}

Try / catch

try {
  res = img.get_haar('y', invert, nb_scales);
} catch (const CImgInstanceException& e) {
  res = img.get_resize(img.width(), pow2ceil(img.height())).get_haar('y', invert, nb_scales);
}

Prevention

When it happens

Trigger: Calling img.get_haar('y', invert, 1) when height/2 is odd and >1 — e.g. height of 6, 10, 14, 22.

Common situations: Images with non-power-of-two heights (cropped photos, sensor frames), multichannel volume processing where depth/slice count is odd, mixing transforms across axes where only one dimension is a power of two.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

              for (unsigned int x = 0, xw = w, x2 = 0; x<w; ++x, ++xw) {
                const Tfloat val0 = (Tfloat)(*this)(x,y,z,c), val1 = (Tfloat)(*this)(xw,y,z,c);
                res(x2++,y,z,c) = (val0 - val1)/sqrt2;
                res(x2++,y,z,c) = (val0 + val1)/sqrt2;
              }
            } else cimg_forYZC(*this,y,z,c) { // Direct transform along X
              for (unsigned int x = 0, xw = w, x2 = 0; x<w; ++x, ++xw) {
                const Tfloat val0 = (Tfloat)(*this)(x2++,y,z,c), val1 = (Tfloat)(*this)(x2++,y,z,c);
                res(x,y,z,c) = (val0 + val1)/sqrt2;
                res(xw,y,z,c) = (val1 - val0)/sqrt2;
              }
            }
          } else return *this;
        } break;
        case 'y' : {
          const unsigned int h = _height/2;
          if (h) {
            if ((h%2) && h!=1)
              throw CImgInstanceException(_cimg_instance
                                          "haar(): Sub-image height %u is not even.",
                                          cimg_instance,
                                          h);

            res.assign(_width,_height,_depth,_spectrum);
            if (invert) cimg_forXZC(*this,x,z,c) { // Inverse transform along Y
              for (unsigned int y = 0, yh = h, y2 = 0; y<h; ++y, ++yh) {
                const Tfloat val0 = (Tfloat)(*this)(x,y,z,c), val1 = (Tfloat)(*this)(x,yh,z,c);
                res(x,y2++,z,c) = (val0 - val1)/sqrt2;
                res(x,y2++,z,c) = (val0 + val1)/sqrt2;
              }
            } else cimg_forXZC(*this,x,z,c) {
              for (unsigned int y = 0, yh = h, y2 = 0; y<h; ++y, ++yh) { // Direct transform along Y
                const Tfloat val0 = (Tfloat)(*this)(x,y2++,z,c), val1 = (Tfloat)(*this)(x,y2++,z,c);
                res(x,y,z,c)  = (val0 + val1)/sqrt2;
                res(x,yh,z,c) = (val1 - val0)/sqrt2;
              }
            }

View on GitHub (pinned to f788b534b4)