use anyhow::Result;
use image::ImageReader;
use std::io::Cursor;
const SAMPLE_GRID_SIZE: u32 = 200;
const LUMA_R: f32 = 0.2126;
const LUMA_G: f32 = 0.7152;
const LUMA_B: f32 = 0.0722;
const DARK_PIXEL_THRESHOLD: f32 = 0.9;
const MEAN_BRIGHTNESS_MIN: f32 = 0.99;
const DARK_RATIO_MAX: f32 = 0.002;
pub fn is_blank_image(bytes: &[u8]) -> Result<bool> {
let img = ImageReader::new(Cursor::new(bytes))
.with_guessed_format()?
.decode()?;
let rgb = img.to_rgb8();
let (width, height) = rgb.dimensions();
if width == 0 || height == 0 {
return Ok(true);
}
let step_x = (width / SAMPLE_GRID_SIZE).max(1);
let step_y = (height / SAMPLE_GRID_SIZE).max(1);
let mut total = 0u64;
let mut dark = 0u64;
let mut sum = 0f32;
for y in (0..height).step_by(step_y as usize) {
for x in (0..width).step_by(step_x as usize) {
let pixel = rgb.get_pixel(x, y);
let [r, g, b] = pixel.0;
let luma = (LUMA_R * r as f32 + LUMA_G * g as f32 + LUMA_B * b as f32) / 255.0;
sum += luma;
if luma < DARK_PIXEL_THRESHOLD {
dark += 1;
}
total += 1;
}
}
if total == 0 {
return Ok(true);
}
let mean = sum / total as f32;
let dark_ratio = dark as f32 / total as f32;
Ok(mean > MEAN_BRIGHTNESS_MIN && dark_ratio < DARK_RATIO_MAX)
}