Yalantis/uCrop · error · CImgInstanceException

CImgList< >::FFT(): Specified real and imaginary parts…

Error message

CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) have non 2^N dimension along the Z-axis.

What it means

Built-in radix-2 FFT constraint applied to real._depth: computing along the Z-axis (the default case of the axis switch) without FFTW3 requires the image depth to be 1 or a power of 2. Otherwise this CImgInstanceException is thrown. Z-axis FFT is used for volumetric (3D) data.

Solutions

  1. Pad the volume depth to the next power of 2 (zero-pad slices) before FFT.
  2. Build CImg with cimg_use_fftw3 to support arbitrary depths.
  3. Crop the volume to a power-of-two number of slices.
  4. Pre-check depth before calling FFT and pad programmatically.

Example fix

// before
vol.FFT(true, false, 'z'); // depth 120 not 2^N
// after
unsigned int d2 = 1; while (d2 < vol.depth()) d2 <<= 1;
vol.get_resize(vol.width(), vol.height(), d2, -100, 0).FFT(true, false, 'z');
Defensive patterns

Strategy: validation

Validate before calling

unsigned int d = vol.depth();
bool isPow2 = d == 1 || ((d & (d - 1)) == 0);
if (!isPow2) vol.resize(vol.width(), vol.height(), nextPow2(d), vol.spectrum(), 0);

Type guard

bool isPowerOfTwo(unsigned int n) { return n == 1 || (n && !(n & (n - 1))); }

Try / catch

try { vol.FFT(is_inverse, false, 'z'); }
catch (CImgInstanceException& e) { /* zero-pad slices to 2^N and retry */ }

Prevention

When it happens

Trigger: Calling FFT() along the Z-axis on a 3D image (CImg with _depth>1, e.g. a MRI/CT volume or image sequence) whose depth is not a power of two, in a build without cimg_use_fftw3.

Common situations: Medical volumes with arbitrary slice counts (e.g. 120 slices), temporal stacks of N frames that are not 2^N, or 2D images accidentally treated as volumes.

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/8aca6803481bb360. Report an issue: GitHub.

Appendix: source

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

                T &ir = real(x,j,z,c), &ii = imag(x,j,z,c), &nir = real(x,nj,z,c), &nii = imag(x,nj,z,c);
                const float tmpr = (float)(wr*nir - wi*nii), tmpi = (float)(wr*nii + wi*nir);
                nir = (T)(ir - tmpr);
                nii = (T)(ii - tmpi);
                ir+=(T)tmpr;
                ii+=(T)tmpi;
              }
              const float nwr = wr*ca-wi*sa;
              wi = wi*ca + wr*sa;
              wr = nwr;
            }
          }
        }
        if (is_inverse) { real/=N; imag/=N; }
      } break;
      default : { // Fourier along Z, using built-in functions
        const unsigned int N = real._depth, N2 = N>>1;
        if (((N - 1)&N) && N!=1)
          throw CImgInstanceException("CImgList<%s>::FFT(): Specified real and imaginary parts (%u,%u,%u,%u) "
                                      "have non 2^N dimension along the Z-axis.",
                                      pixel_type(),
                                      real._width,real._height,real._depth,real._spectrum);

        for (unsigned int i = 0, j = 0; i<N2; ++i) {
          if (j>i) cimg_forXYC(real,x,y,c) {
              cimg::swap(real(x,y,i,c),real(x,y,j,c));
              cimg::swap(imag(x,y,i,c),imag(x,y,j,c));
              if (j<N2) {
                const unsigned int ri = N - 1 - i, rj = N - 1 - j;
                cimg::swap(real(x,y,ri,c),real(x,y,rj,c));
                cimg::swap(imag(x,y,ri,c),imag(x,y,rj,c));
              }
            }
          for (unsigned int m = N, n = N2; (j+=n)>=m; j-=m, m = n, n>>=1) {}
        }
        for (unsigned int delta = 2; delta<=N; delta<<=1) {
          const unsigned int delta2 = (delta>>1);

View on GitHub (pinned to f788b534b4)