// this function does nothing, but without it, when first plan is created using real images, for some parameters // the first output image is empty and the rest is fine, so it's better to create here this no-use plan just // to be sure that everything works private void PreparePlan(int w, int h) { double[] d1 = new double[w * h * 2]; double[] d2 = new double[w * h * 2]; IntPtr plan = FFTW.PlanDFT2D(h, w, d1, d2, FFTW.Direction.Forward, 0); FFTW.DestroyPlan(plan); }
private IImage FFT(IImage img) { double[] datain = new double[img.W * img.H * 2]; double[] dataout = new double[img.W * img.H * 2]; for (int y = 0; y < img.H; y++) { for (int x = 0; x < img.W; x++) { datain[(x + y * img.W) * 2] = (byte)img[x, y]; datain[(x + y * img.W) * 2 + 1] = 0; } } IntPtr plan = FFTW.PlanDFT2D(img.H, img.W, datain, dataout, FFTW.Direction.Forward, 0); FFTW.Execute(plan); FFTW.DestroyPlan(plan); IImage ret = new IImage(BPP.Float, img.W, img.H); for (int y = 0; y < img.H; y++) { for (int x = 0; x < img.W; x++) { double re = dataout[(x + y * img.W) * 2]; double im = dataout[(x + y * img.W) * 2 + 1]; double val = Math.Sqrt(re * re + im * im); int newx = (x + img.W / 2) % img.W; int newy = (y + img.H / 2) % img.H; ret[newx, newy] = (float)val / 255f; } } if (zero) { ret[img.W / 2, img.H / 2] = 0f; } return(ret); }
private IImage DCT(IImage img) { double[] datain = new double[img.W * img.H]; double[] dataout = new double[img.W * img.H]; for (int y = 0; y < img.H; y++) { for (int x = 0; x < img.W; x++) { datain[x + y * img.W] = (byte)img[x, y]; } } IntPtr plan = FFTW.PlanR2R2D(img.H, img.W, datain, dataout, FFTW.Kind.FFTW_REDFT10, FFTW.Kind.FFTW_REDFT10, 0); FFTW.Execute(plan); FFTW.DestroyPlan(plan); IImage ret = new IImage(BPP.Float, img.W, img.H); for (int y = 0; y < img.H; y++) { for (int x = 0; x < img.W; x++) { ret[x, y] = (float)dataout[x + y * img.W] / 255f; } } if (zero) { ret[0, 0] = 0f; } return(ret); }