use scirs2_core::Complex64;
use scirs2_fft::{fft2_adaptive, ifft2_adaptive, simd_support_available};
use std::f64::consts::PI;
use std::time::Instant;
#[allow(dead_code)]
fn main() {
println!("SIMD-accelerated 2D FFT Image Processing Example");
println!("------------------------------------------------");
let simd_available = simd_support_available();
println!("SIMD support available: {simd_available}");
let width = 128;
let height = 128;
println!("\nGenerating test image ({width} x {height})");
let test_image = generate_test_image(width, height);
println!("\nApplying frequency domain filtering with a lowpass filter...");
let start = Instant::now();
let _filtered_image = frequency_domain_filter(&test_image, width, height, "lowpass");
let lowpass_time = start.elapsed();
println!("Lowpass filter processing time: {lowpass_time:?}");
println!("\nApplying frequency domain filtering with a highpass filter...");
let start = Instant::now();
let _filtered_image = frequency_domain_filter(&test_image, width, height, "highpass");
let highpass_time = start.elapsed();
println!("Highpass filter processing time: {highpass_time:?}");
println!("\nApplying frequency domain filtering with a bandpass filter...");
let start = Instant::now();
let _filtered_image = frequency_domain_filter(&test_image, width, height, "bandpass");
let bandpass_time = start.elapsed();
println!("Bandpass filter processing time: {bandpass_time:?}");
println!("\nPerformance comparison with larger images:");
for &size in &[256, 512] {
println!("\nGenerating test image ({size} x {size})");
let large_image = generate_test_image(size, size);
let start = Instant::now();
let _filtered = frequency_domain_filter(&large_image, size, size, "lowpass");
let time = start.elapsed();
println!("Processing time for {size} x {size} image: {time:?}");
let start = Instant::now();
let _filtered = frequency_domain_filter(&large_image, size, size, "highpass");
let highpass_time = start.elapsed();
println!("Highpass filter time for {size} x {size} image: {highpass_time:?}");
}
}
#[allow(dead_code)]
fn generate_test_image(width: usize, height: usize) -> Vec<f64> {
let mut image = vec![0.0; width * height];
for y in 0..height {
for x in 0..width {
let x_norm = x as f64 / width as f64;
let y_norm = y as f64 / height as f64;
let low_freq = (2.0 * PI * x_norm).sin() * (2.0 * PI * y_norm).cos();
let mid_freq = 0.5 * (8.0 * PI * x_norm).sin() * (8.0 * PI * y_norm).cos();
let high_freq = 0.25 * (16.0 * PI * x_norm).sin() * (16.0 * PI * y_norm).cos();
image[y * width + x] = low_freq + mid_freq + high_freq;
}
}
image
}
#[allow(dead_code)]
fn frequency_domain_filter(
image: &[f64],
width: usize,
height: usize,
filter_type: &str,
) -> Vec<f64> {
let spectrum = fft2_adaptive(image, Some((height, width)), None).expect("Operation failed");
let mut filter = vec![Complex64::new(0.0, 0.0); width * height];
let center_x = width / 2;
let center_y = height / 2;
let max_distance = (center_x.pow(2) + center_y.pow(2)) as f64;
for y in 0..height {
for x in 0..width {
let freq_x = if x < center_x { x } else { x - width };
let freq_y = if y < center_y { y } else { y - height };
let distance = ((freq_x.pow(2) + freq_y.pow(2)) as f64) / max_distance;
let filter_value = match filter_type {
"lowpass" => {
let cutoff = 0.1;
if distance <= cutoff {
1.0
} else if distance <= cutoff * 2.0 {
0.5 * (1.0 + (PI * (distance - cutoff) / cutoff).cos())
} else {
0.0
}
}
"highpass" => {
let cutoff = 0.1;
if distance <= cutoff {
0.0
} else if distance <= cutoff * 2.0 {
0.5 * (1.0 - (PI * (distance - cutoff) / cutoff).cos())
} else {
1.0
}
}
"bandpass" => {
let low_cutoff = 0.1;
let high_cutoff = 0.3;
if distance <= low_cutoff {
0.0
} else if distance <= low_cutoff * 2.0 {
0.5 * (1.0 - (PI * (distance - low_cutoff) / low_cutoff).cos())
} else if distance <= high_cutoff {
1.0
} else if distance <= high_cutoff * 2.0 {
0.5 * (1.0 + (PI * (distance - high_cutoff) / high_cutoff).cos())
} else {
0.0
}
}
_ => 1.0, };
filter[y * width + x] = Complex64::new(filter_value, 0.0);
}
}
let filtered_spectrum: Vec<Complex64> = spectrum
.iter()
.zip(filter.iter())
.map(|(&s, &f)| s * f)
.collect();
let filtered_image_complex =
ifft2_adaptive(&filtered_spectrum, Some((height, width)), None).expect("Operation failed");
let filtered_image: Vec<f64> = filtered_image_complex.iter().map(|c| c.re).collect();
filtered_image
}