private static void Filter2D(Bitmap input, ref Bitmap output, FilterFunction filterFunction) { int[] dims = new int[2] { input.Width, input.Height }; kiss_fft_cpx <float>[] timeDomain = new kiss_fft_cpx <float> [input.Width * input.Height]; kiss_fft_cpx <float>[] frequencyDomain = new kiss_fft_cpx <float> [input.Width * input.Height]; for (int i = 0; i < input.Width * input.Height; ++i) { timeDomain[i] = new kiss_fft_cpx <float>(); frequencyDomain[i] = new kiss_fft_cpx <float>(); } { // FFT for (int x = 0; x < input.Width; ++x) { for (int y = 0; y < input.Height; ++y) { timeDomain[y * input.Width + x].r = input.GetPixel(x, y).R; timeDomain[y * input.Width + x].i = 0.0f; } } KissFFTnd <float> kissFftnd = new KissFFTnd <float>(dims, 2, false, new FloatArithmetic()); kissFftnd.kiss_fftnd(new Array <kiss_fft_cpx <float> >(timeDomain), new Array <kiss_fft_cpx <float> >(frequencyDomain)); for (int i = 0; i < input.Width * input.Height; ++i) { frequencyDomain[i].r /= input.Width * input.Height; frequencyDomain[i].i /= input.Width * input.Height; } } { // filter for (int x = 0; x < input.Width; ++x) { for (int y = 0; y < input.Height; ++y) { float q = filterFunction(x, y, input.Width, input.Height); frequencyDomain[y * input.Width + x].r *= q; frequencyDomain[y * input.Width + x].i *= q; } } } { // IFFT output = new Bitmap(input.Width, input.Height); KissFFTnd <float> kissFftnd = new KissFFTnd <float>(dims, 2, true, new FloatArithmetic()); kissFftnd.kiss_fftnd(new Array <kiss_fft_cpx <float> >(frequencyDomain), new Array <kiss_fft_cpx <float> >(timeDomain)); for (int x = 0; x < input.Width; ++x) { for (int y = 0; y < input.Height; ++y) { int intensity = (int)timeDomain[y * input.Width + x].r; intensity = Math.Min(255, Math.Max(0, intensity)); output.SetPixel(x, y, Color.FromArgb(intensity, intensity, intensity)); } } } }
private static void Filter2D(Bitmap input, ref Bitmap output, FilterFunction filterFunction) { int[] dims = new int[2] { input.Width, input.Height }; kiss_fft_cpx<float>[] timeDomain = new kiss_fft_cpx<float>[input.Width * input.Height]; kiss_fft_cpx<float>[] frequencyDomain = new kiss_fft_cpx<float>[input.Width * input.Height]; for (int i = 0; i < input.Width * input.Height; ++i) { timeDomain[i] = new kiss_fft_cpx<float>(); frequencyDomain[i] = new kiss_fft_cpx<float>(); } { // FFT for (int x = 0; x < input.Width; ++x) { for (int y = 0; y < input.Height; ++y) { timeDomain[y * input.Width + x].r = input.GetPixel(x, y).R; timeDomain[y * input.Width + x].i = 0.0f; } } KissFFTnd<float> kissFftnd = new KissFFTnd<float>(dims, 2, false, new FloatArithmetic()); kissFftnd.kiss_fftnd(new Array<kiss_fft_cpx<float>>(timeDomain), new Array<kiss_fft_cpx<float>>(frequencyDomain)); for (int i = 0; i < input.Width * input.Height; ++i) { frequencyDomain[i].r /= input.Width * input.Height; frequencyDomain[i].i /= input.Width * input.Height; } } { // filter for (int x = 0; x < input.Width; ++x) { for (int y = 0; y < input.Height; ++y) { float q = filterFunction(x, y, input.Width, input.Height); frequencyDomain[y * input.Width + x].r *= q; frequencyDomain[y * input.Width + x].i *= q; } } } { // IFFT output = new Bitmap(input.Width, input.Height); KissFFTnd<float> kissFftnd = new KissFFTnd<float>(dims, 2, true, new FloatArithmetic()); kissFftnd.kiss_fftnd(new Array<kiss_fft_cpx<float>>(frequencyDomain), new Array<kiss_fft_cpx<float>>(timeDomain)); for (int x = 0; x < input.Width; ++x) { for (int y = 0; y < input.Height; ++y) { int intensity = (int) timeDomain[y * input.Width + x].r; intensity = Math.Min(255, Math.Max(0, intensity)); output.SetPixel(x, y, Color.FromArgb(intensity, intensity, intensity)); } } } }