use crate::qr::QrCode; use image::{ImageBuffer, Luma}; /// 将单个模块填充到图像缓冲区(module_size × module_size 像素块) fn fill_module( img: &mut ImageBuffer, Vec>, x: u32, y: u32, module_size: u32, is_dark: bool, ) { let px_val = if is_dark { 0u8 } else { 255u8 }; let x0 = x * module_size; let y0 = y * module_size; for dy in 0..module_size { for dx in 0..module_size { img.put_pixel(x0 + dx, y0 + dy, Luma([px_val])); } } } pub fn render_png(qr: &QrCode, module_size: u8) -> Result, image::ImageError> { let matrix_size = qr.size() as u32; let margin = qr.margin as u32; let total_size = matrix_size + 2 * margin; let img_size = total_size * module_size as u32; let mut img = ImageBuffer::new(img_size, img_size); for y in 0..total_size { for x in 0..total_size { // 直接比较坐标与 margin 边界,避免 saturating_sub 在边界处回绕到 0 let is_dark = if x >= margin && x < margin + matrix_size && y >= margin && y < margin + matrix_size { let mx = (x - margin) as usize; let my = (y - margin) as usize; qr.modules()[my][mx] } else { false // 白边 (quiet zone) }; fill_module(&mut img, x, y, module_size as u32, is_dark); } } let mut buf = Vec::new(); img.write_to(&mut std::io::Cursor::new(&mut buf), image::ImageFormat::Png)?; Ok(buf) }