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 X-axis.
What it means
When FFTW3 is not available, CImg falls back to a built-in radix-2 FFT that only works when the dimension along the transform axis is a power of 2 (or exactly 1). For the X-axis it checks real._width via ((N-1)&N) && N!=1 and throws if width is not 2^N. This is a hard requirement of the built-in algorithm.
Solutions
- Pad the image width to the next power of 2 (e.g. with CImg::resize or zero-padding) before FFT.
- Build CImg with cimg_use_fftw3 so arbitrary dimensions are supported by FFTW.
- Crop the image to a power-of-two width if padding is unacceptable.
- Verify image dimensions with code before calling FFT.
Example fix
// before CImg<float> img(100, 100); img.FFT(); // width 100 is not 2^N // after CImg<float> img(100, 100); CImg<float> padded(img.get_resize(128, 128, -100, -100, 0)); padded.FFT();
Defensive patterns
Strategy: validation
Validate before calling
unsigned int w = img.width(); bool isPow2 = w == 1 || ((w & (w - 1)) == 0); if (!isPow2) img.resize(nextPow2(w), img.height(), img.depth(), img.spectrum(), 0); // or reject
Type guard
bool isPowerOfTwo(unsigned int n) { return n == 1 || (n && !(n & (n - 1))); } Try / catch
try { img.FFT(is_inverse, false, 'x'); }
catch (CImgInstanceException& e) { /* pad to power of two and retry */ } Prevention
- Pad width to a power of two before FFT when FFTW3 is not compiled in
- Verify which build you ship: check cimg_use_fftw3 macro availability
- Write a preprocessing step that resizes arbitrary images to 2^N dimensions
When it happens
Trigger: Calling CImgList<T>::FFT()/CImg<T>::FFT() along the X-axis (axis='x') without cimg_use_fftw3 defined, on an image whose _width is not a power of two (e.g. 100, 333, 1000).
Common situations: Feeding camera frames or natural images of arbitrary width into FFT, forgetting to pad to a power of two, or a build that silently lacks FFTW3 so the fallback path is active.
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
- CImgList< >::FFT(): Specified real and imaginary parts…
- CImgList< >::FFT(): Specified real and imaginary parts…
- CImg< >::FFT(): Specified real part is empty.
- CImg< >::FFT(): Specified real part (%u,%u,%u,%u,%p) and…
- CImgList< >::FFT(): Empty specified real part.
AI-assisted analysis of Yalantis/uCrop@f788b534b4 (2026-09-08).
Data as JSON: /api/errors/1b6fe09cb641ae31.
Report an issue: GitHub.
Appendix: source
Thrown at ucrop/src/main/jni/CImg.h:47780
j = realc.offset(x,y,z);
realc[j] = (T)(a*ptrf[i]);
imagc[j] = (T)(a*ptrf[i + 1]);
}
}
}
fftw_destroy_plan(data_plan);
fftw_free(data_in);
#ifndef cimg_use_fftw3_singlethread
fftw_cleanup_threads();
#endif
cimg::mutex(12,0);
#else
switch (_axis) {
case 'x' : { // Fourier along X, using built-in functions
const unsigned int N = real._width, 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 X-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_forYZC(real,y,z,c) {
cimg::swap(real(i,y,z,c),real(j,y,z,c));
cimg::swap(imag(i,y,z,c),imag(j,y,z,c));
if (j<N2) {
const unsigned int ri = N - 1 - i, rj = N - 1 - j;
cimg::swap(real(ri,y,z,c),real(rj,y,z,c));
cimg::swap(imag(ri,y,z,c),imag(rj,y,z,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)