use crate::error::{CalibrationError, CalibrationResult};
pub fn estimate_color_temperature(image_data: &[u8]) -> CalibrationResult<u32> {
if image_data.is_empty() || image_data.len() % 3 != 0 {
return Err(CalibrationError::TemperatureEstimationFailed(
"Invalid image data".to_string(),
));
}
let mut r_sum: u64 = 0;
let mut g_sum: u64 = 0;
let mut b_sum: u64 = 0;
let pixel_count = image_data.len() / 3;
for chunk in image_data.chunks_exact(3) {
r_sum += u64::from(chunk[0]);
g_sum += u64::from(chunk[1]);
b_sum += u64::from(chunk[2]);
}
let r_avg = r_sum as f64 / pixel_count as f64;
let _g_avg = g_sum as f64 / pixel_count as f64;
let b_avg = b_sum as f64 / pixel_count as f64;
let rb_ratio = r_avg / b_avg.max(1.0);
let temperature = estimate_from_rb_ratio(rb_ratio);
Ok(temperature)
}
fn estimate_from_rb_ratio(rb_ratio: f64) -> u32 {
if rb_ratio > 1.5 {
2000 } else if rb_ratio > 1.3 {
2500 } else if rb_ratio > 1.1 {
3000 } else if rb_ratio > 1.0 {
4000 } else if rb_ratio >= 0.95 {
5000 } else if rb_ratio > 0.90 {
5500 } else if rb_ratio > 0.85 {
6500 } else if rb_ratio > 0.80 {
7500 } else {
9000 }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_estimate_color_temperature_empty() {
let result = estimate_color_temperature(&[]);
assert!(result.is_err());
}
#[test]
fn test_estimate_color_temperature_invalid_size() {
let result = estimate_color_temperature(&[128, 128]);
assert!(result.is_err());
}
#[test]
fn test_estimate_color_temperature_neutral() {
let image = vec![128; 300]; let result = estimate_color_temperature(&image);
assert!(result.is_ok());
let temp = result.expect("expected successful result");
assert!(temp >= 5000 && temp <= 7000);
}
#[test]
fn test_estimate_color_temperature_warm() {
let mut image = Vec::new();
for _ in 0..100 {
image.extend_from_slice(&[200, 150, 100]); }
let result = estimate_color_temperature(&image);
assert!(result.is_ok());
let temp = result.expect("expected successful result");
assert!(temp <= 4000);
}
#[test]
fn test_estimate_color_temperature_cool() {
let mut image = Vec::new();
for _ in 0..100 {
image.extend_from_slice(&[100, 150, 200]); }
let result = estimate_color_temperature(&image);
assert!(result.is_ok());
let temp = result.expect("expected successful result");
assert!(temp >= 7000);
}
#[test]
fn test_estimate_from_rb_ratio() {
assert_eq!(estimate_from_rb_ratio(1.6), 2000);
assert_eq!(estimate_from_rb_ratio(1.2), 3000);
assert_eq!(estimate_from_rb_ratio(0.95), 5000);
assert_eq!(estimate_from_rb_ratio(0.88), 6500);
assert_eq!(estimate_from_rb_ratio(0.75), 9000);
}
}