Yalantis/uCrop · error · CImgInstanceException
haar(): Sub-image width %u is not even.
Error message
haar(): Sub-image width %u is not even.
What it means
CImg::haar() performs a Haar wavelet transform along the X axis. For a single-scale transform it splits the width in half (w = _width/2) and requires each sub-image width to be even (w%2==0) or equal to 1; otherwise the recursive sub-division of the signal is impossible and it throws CImgInstanceException.
Solutions
- Use an image width that is a power of two (or ensure width/2 is even or 1).
- Resize/pad the image to the next power of two before calling: img.get_resize(w2,h2) or pad with zeros.
- Increase nb_scales to use the multi-scale version, which handles sizes differently.
- Compute the largest valid scale: only descend while (dim/2) is even.
Example fix
// before
CImg<> out = img6x8.get_haar('x', false, 1); // width 6 -> half 3, odd
// after
CImg<> padded = img6x8.get_resize(8, img6x8.height());
CImg<> out = padded.get_haar('x', false, 1); Defensive patterns
Strategy: validation
Validate before calling
if (unsigned w = img.width()/2; (w % 2) && w != 1) img = img.get_resize(nextPow2(img.width()), img.height());
Type guard
bool haarXOk(const CImg<T>& img) {
unsigned w = img.width()/2;
return w == 0 || !(w % 2) || w == 1;
} Try / catch
try {
res = img.get_haar('x', invert, nb_scales);
} catch (const CImgInstanceException& e) {
res = img.get_resize(pow2ceil(img.width()), img.height()).get_haar('x', invert, nb_scales);
} Prevention
- Prefer power-of-two image widths for wavelet work.
- Pad with zeros to the next power of two before transforming.
- Remember the constraint applies to width/2, not width itself.
When it happens
Trigger: Calling img.get_haar('x', invert, nb_scales=1) when the half-width (width/2) is odd and greater than 1 — e.g. width = 6, 10, 14 (half = 3, 5, 7) or any width where width/2 is odd.
Common situations: Applying the Haar transform to arbitrarily sized images (e.g. odd or non-power-of-two widths from a camera or crop), passing nb_scales=1 on an image whose width/2 is odd, inverting a transform applied to a resized image.
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
- haar(): Sub-image height %u is not even.
- blur_anisotropic(): Invalid specified diffusion tensor…
- blur_bilateral(): Invalid size for specified guide image…
- blur_guided(): Invalid size for specified guide image…
- blur_patch(): Invalid size for specified guide image…
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/b9600333a88c1200.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:47390
\param invert Set inverse of direct transform.
\param nb_scales Number of scales used for the transform.
**/
CImg<T>& haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) {
return get_haar(axis,invert,nb_scales).move_to(*this);
}
//! Compute Haar multiscale wavelet transform \newinstance.
CImg<Tfloat> get_haar(const char axis, const bool invert=false, const unsigned int nb_scales=1) const {
if (is_empty() || !nb_scales) return +*this;
CImg<Tfloat> res;
const Tfloat sqrt2 = std::sqrt(2.f);
if (nb_scales==1) {
switch (cimg::lowercase(axis)) { // Single scale transform
case 'x' : {
const unsigned int w = _width/2;
if (w) {
if ((w%2) && w!=1)
throw CImgInstanceException(_cimg_instance
"haar(): Sub-image width %u is not even.",
cimg_instance,
w);
res.assign(_width,_height,_depth,_spectrum);
if (invert) cimg_forYZC(*this,y,z,c) { // Inverse transform along X
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;
}
}View on GitHub (pinned to f788b534b4)