agb/emulator/test-runner/src/image_compare.rs
2024-04-09 20:56:19 +01:00

51 lines
1.3 KiB
Rust

use std::path::Path;
use image::io::Reader;
pub struct ComparisonResult {
matches: bool,
}
impl ComparisonResult {
pub fn success(&self) -> bool {
self.matches
}
}
const WIDTH: usize = 240;
const HEIGHT: usize = 160;
fn convert_rgba_to_nearest_gba_colour(c: [u8; 4]) -> [u8; 4] {
let mut n = c;
n.iter_mut()
.for_each(|a| *a = ((((*a as u32 >> 3) << 3) * 0x21) >> 5) as u8);
n
}
pub fn compare_image(
image: impl AsRef<Path>,
video_buffer: &[u32],
) -> anyhow::Result<ComparisonResult> {
let expected = Reader::open(image)?.decode()?;
let expected_buffer = expected.to_rgba8();
let (exp_dim_x, exp_dim_y) = expected_buffer.dimensions();
if exp_dim_x != WIDTH as u32 || exp_dim_y != HEIGHT as u32 {
return Ok(ComparisonResult { matches: false });
}
for y in 0..HEIGHT {
for x in 0..WIDTH {
let video_pixel = video_buffer[x + y * WIDTH];
let image_pixel = expected_buffer.get_pixel(x as u32, y as u32);
let image_pixel = convert_rgba_to_nearest_gba_colour(image_pixel.0);
if image_pixel[0..3] != video_pixel.to_le_bytes()[0..3] {
return Ok(ComparisonResult { matches: false });
}
}
}
Ok(ComparisonResult { matches: true })
}