use std::path::Path;
use image::imageops::FilterType;
use mlx_rs::Array;
use crate::InferenceError;
pub fn load_rgb_image(path: &Path, width: u32, height: u32) -> Result<Array, InferenceError> {
assert!(
width > 0 && height > 0,
"image target dims must be non-zero"
);
let img = image::open(path)
.map_err(|e| InferenceError::InferenceFailed(format!("open {}: {e}", path.display())))?;
let (src_w, src_h) = (img.width(), img.height());
let target_aspect = width as f64 / height as f64;
let src_aspect = src_w as f64 / src_h as f64;
let cropped = if (src_aspect - target_aspect).abs() < 1e-6 {
img
} else if src_aspect > target_aspect {
let crop_w = (src_h as f64 * target_aspect).round() as u32;
let x = (src_w - crop_w) / 2;
img.crop_imm(x, 0, crop_w, src_h)
} else {
let crop_h = (src_w as f64 / target_aspect).round() as u32;
let y = (src_h - crop_h) / 2;
img.crop_imm(0, y, src_w, crop_h)
};
let resized = if cropped.width() == width && cropped.height() == height {
cropped.to_rgb8()
} else {
cropped
.resize_exact(width, height, FilterType::Lanczos3)
.to_rgb8()
};
let mut pixels: Vec<f32> = Vec::with_capacity((width * height * 3) as usize);
for p in resized.pixels() {
pixels.push(p[0] as f32 / 255.0);
pixels.push(p[1] as f32 / 255.0);
pixels.push(p[2] as f32 / 255.0);
}
Ok(Array::from_slice(
&pixels,
&[1, height as i32, width as i32, 3],
))
}