void DCT::apply(Image im, bool transformX, bool transformY, bool transformT) { if (im.width == 1) { transformX = false; } if (im.height == 1) { transformY = false; } if (im.frames == 1) { transformT = false; } // rank 0 if (!transformX && !transformY && !transformT) { return; } vector<fftwf_iodim> loop_dims; vector<fftwf_iodim> fft_dims; // X { fftwf_iodim d = {im.width, 1, 1}; if (transformX) fft_dims.push_back(d); else loop_dims.push_back(d); } // Y { fftwf_iodim d = {im.height, im.ystride, im.ystride}; if (transformY) fft_dims.push_back(d); else loop_dims.push_back(d); } // T { fftwf_iodim d = {im.frames, im.tstride, im.tstride}; if (transformT) fft_dims.push_back(d); else loop_dims.push_back(d); } // C { fftwf_iodim d = {im.channels, im.cstride, im.cstride}; loop_dims.push_back(d); } vector<fftw_r2r_kind> kinds(fft_dims.size(), FFTW_REDFT00); fftwf_plan plan = fftwf_plan_guru_r2r((int)fft_dims.size(), &fft_dims[0], (int)loop_dims.size(), &loop_dims[0], im.baseAddress(), im.baseAddress(), &kinds[0], FFTW_ESTIMATE); fftwf_execute(plan); fftwf_destroy_plan(plan); float m = 1.0; if (transformX) m *= 2*(im.width-1); if (transformY) m *= 2*(im.height-1); if (transformT) m *= 2*(im.frames-1); im /= sqrtf(m); }
fftwf_plan plan_transpose(int rows, int cols, float *in, float *out) { // FFTW can be tricked into doing *very* fast transposes // (initial testing showed 6-7x faster than TOMs!) // http://agentzlerich.blogspot.com/2010/01/using-fftw-for-in-place-matrix.html // http://www.fftw.org/faq/section3.html#transpose const unsigned flags = FFTW_MEASURE; /* other flags are possible */ fftwf_iodim howmany_dims[2]; howmany_dims[0].n = rows; howmany_dims[0].is = cols; howmany_dims[0].os = 1; howmany_dims[1].n = cols; howmany_dims[1].is = 1; howmany_dims[1].os = rows; return fftwf_plan_guru_r2r(/*rank=*/ 0, /*dims=*/ NULL, /*howmany_rank=*/ 2, howmany_dims, in, out, /*kind=*/ NULL, flags); }