use super::FreqImage;
use rustfft::{FftDirection, FftPlanner, num_complex::Complex};
impl FreqImage {
pub fn fft_forward(&mut self) {
let (w, h) = (self.width as usize, self.height as usize);
let mut planner = FftPlanner::new();
let fft_width = planner.plan_fft(w, FftDirection::Forward);
let mut scratch = vec![Complex::default(); fft_width.get_inplace_scratch_len()];
for row in self.data.chunks_exact_mut(w) {
fft_width.process_with_scratch(row, &mut scratch);
}
let mut transposed = transpose(w, h, &self.data);
let fft_height = planner.plan_fft(h, FftDirection::Forward);
scratch.resize(fft_height.get_inplace_scratch_len(), Complex::default());
for col in transposed.chunks_exact_mut(h) {
fft_height.process_with_scratch(col, &mut scratch);
}
self.data = transpose(h, w, &transposed);
}
pub fn fft_inverse(&mut self) {
let (w, h) = (self.width as usize, self.height as usize);
let mut planner = FftPlanner::new();
let mut transposed = transpose(w, h, &self.data);
let fft_height = planner.plan_fft(h, FftDirection::Inverse);
let mut scratch = vec![Complex::default(); fft_height.get_inplace_scratch_len()];
for col in transposed.chunks_exact_mut(h) {
fft_height.process_with_scratch(col, &mut scratch);
}
self.data = transpose(h, w, &transposed);
let fft_width = planner.plan_fft(w, FftDirection::Inverse);
scratch.resize(fft_width.get_inplace_scratch_len(), Complex::default());
for row in self.data.chunks_exact_mut(w) {
fft_width.process_with_scratch(row, &mut scratch);
}
let norm = (w * h) as f64;
for c in self.data.iter_mut() {
*c /= norm;
}
}
}
pub(crate) fn transpose<T: Copy + Default>(width: usize, height: usize, matrix: &[T]) -> Vec<T> {
let mut transposed = vec![T::default(); matrix.len()];
for row in 0..height {
for col in 0..width {
transposed[col * height + row] = matrix[row * width + col];
}
}
transposed
}