use archmage::prelude::*;
use yuv::{YuvPlanarImage, YuvRange as YuvCrateRange, YuvStandardMatrix, yuv420_to_rgb};
use zenavif::yuv_convert::{YuvMatrix, YuvRange, yuv420_to_rgb8};
use zenavif::yuv_convert_fast::yuv420_to_rgb8_fast;
fn main() {
let width = 256;
let height = 256;
let mut y_plane = vec![0u8; width * height];
let uv_size = width.div_ceil(2) * height.div_ceil(2);
let mut u_plane = vec![0u8; uv_size];
let mut v_plane = vec![0u8; uv_size];
for y in 0..height {
for x in 0..width {
y_plane[y * width + x] = ((x + y) % 256) as u8;
}
}
for y in 0..height / 2 {
for x in 0..width / 2 {
u_plane[y * width / 2 + x] = ((x * 2) % 256) as u8;
v_plane[y * width / 2 + x] = ((y * 2) % 256) as u8;
}
}
let float_result = yuv420_to_rgb8(
&y_plane,
width,
&u_plane,
width / 2,
&v_plane,
width / 2,
width,
height,
YuvRange::Full,
YuvMatrix::Bt709,
);
let fast_result = if let Some(token) = Desktop64::summon() {
yuv420_to_rgb8_fast(
token,
&y_plane,
width,
&u_plane,
width / 2,
&v_plane,
width / 2,
width,
height,
)
} else {
panic!("AVX2 not available");
};
let yuv_image = YuvPlanarImage {
y_plane: &y_plane,
y_stride: width as u32,
u_plane: &u_plane,
u_stride: (width / 2) as u32,
v_plane: &v_plane,
v_stride: (width / 2) as u32,
width: width as u32,
height: height as u32,
};
let mut yuv_crate_rgb = vec![0u8; width * height * 3];
yuv420_to_rgb(
&yuv_image,
&mut yuv_crate_rgb,
(width * 3) as u32,
YuvCrateRange::Full,
YuvStandardMatrix::Bt709,
)
.unwrap();
let mut max_diff_float = 0i32;
let mut total_diff_float = 0i64;
let mut pixels_different_float = 0;
for i in 0..(width * height) {
let fast = fast_result.buf()[i];
let float = float_result.buf()[i];
let diff_r = (fast.r as i32 - float.r as i32).abs();
let diff_g = (fast.g as i32 - float.g as i32).abs();
let diff_b = (fast.b as i32 - float.b as i32).abs();
let max_channel_diff = diff_r.max(diff_g).max(diff_b);
max_diff_float = max_diff_float.max(max_channel_diff);
total_diff_float += (diff_r + diff_g + diff_b) as i64;
if max_channel_diff > 1 {
pixels_different_float += 1;
}
}
let mut max_diff_yuv = 0i32;
let mut total_diff_yuv = 0i64;
let mut pixels_different_yuv = 0;
for i in 0..(width * height) {
let fast = fast_result.buf()[i];
let yuv_r = yuv_crate_rgb[i * 3];
let yuv_g = yuv_crate_rgb[i * 3 + 1];
let yuv_b = yuv_crate_rgb[i * 3 + 2];
let diff_r = (fast.r as i32 - yuv_r as i32).abs();
let diff_g = (fast.g as i32 - yuv_g as i32).abs();
let diff_b = (fast.b as i32 - yuv_b as i32).abs();
let max_channel_diff = diff_r.max(diff_g).max(diff_b);
max_diff_yuv = max_diff_yuv.max(max_channel_diff);
total_diff_yuv += (diff_r + diff_g + diff_b) as i64;
if max_channel_diff > 1 {
pixels_different_yuv += 1;
}
}
println!(
"Accuracy Check ({}x{}, {} pixels)",
width,
height,
width * height
);
println!();
println!("Fast Integer vs Float SIMD:");
println!(" Max difference: {}", max_diff_float);
println!(
" Avg difference: {:.3}",
total_diff_float as f64 / (width * height * 3) as f64
);
println!(
" Pixels with >1 diff: {} ({:.2}%)",
pixels_different_float,
100.0 * pixels_different_float as f64 / (width * height) as f64
);
println!();
println!("Fast Integer vs yuv crate:");
println!(" Max difference: {}", max_diff_yuv);
println!(
" Avg difference: {:.3}",
total_diff_yuv as f64 / (width * height * 3) as f64
);
println!(
" Pixels with >1 diff: {} ({:.2}%)",
pixels_different_yuv,
100.0 * pixels_different_yuv as f64 / (width * height) as f64
);
if max_diff_float <= 1 && max_diff_yuv <= 1 {
println!();
println!("✅ PASS: All differences within ±1 (rounding tolerance)");
} else if max_diff_float <= 2 && max_diff_yuv <= 2 {
println!();
println!("⚠️ ACCEPTABLE: Small differences (±2), likely rounding");
} else {
println!();
println!("❌ FAIL: Significant differences detected");
}
}