From 7a7b710ca481457f3438adba15fd6c3fa2b3c258 Mon Sep 17 00:00:00 2001 From: Jaby Date: Sun, 16 Feb 2025 15:27:07 +0100 Subject: [PATCH] Support direct color PNG images --- src/Tools/tim_tool/src/logic/tim.rs | 40 +++++++++++++++++++---------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/Tools/tim_tool/src/logic/tim.rs b/src/Tools/tim_tool/src/logic/tim.rs index bfa96882..cfdb26c3 100644 --- a/src/Tools/tim_tool/src/logic/tim.rs +++ b/src/Tools/tim_tool/src/logic/tim.rs @@ -9,30 +9,35 @@ pub struct TIMInfo { impl TIMInfo { pub fn from_image(path: &PathBuf) -> Result { - fn make_color(iter: &mut dyn std::iter::Iterator) -> Option { + fn make_color(iter: &mut dyn std::iter::Iterator, load_alpha: bool) -> Option { Some(Rgba8Pixel::new( *iter.next()?, *iter.next()?, *iter.next()?, - 0xFF)) + if load_alpha {*iter.next()?} else {0xFF})) } let mut reader = png::Decoder::new(File::open(path)?).read_info().or_else(|error| {Err(Error::from_error(error))})?; let info = reader.info().clone(); - let mut buffer = vec![0; reader.output_buffer_size()]; - let frame_info = reader.next_frame(&mut buffer).or_else(|error| {Err(Error::from_error(error))})?; - let bit_depth = frame_info.bit_depth; - let mut image_data = SharedPixelBuffer::new(frame_info.width, frame_info.height); - + let mut buffer = vec![0; reader.output_buffer_size()]; + let frame_info = reader.next_frame(&mut buffer).or_else(|error| {Err(Error::from_error(error))})?; + let bytes_per_pixel = info.bytes_per_pixel(); + let bit_depth = frame_info.bit_depth; + let mut image_data = SharedPixelBuffer::new(frame_info.width, frame_info.height); + let mut dst_pixels = image_data.make_mut_slice(); + + if bytes_per_pixel != 3 && bytes_per_pixel != 4 { + return Err(Error::from_text(format!("Image has {} bytes per pixel, but only 3 and 4 bytes per pixel are supported", bytes_per_pixel))); + } + if info.color_type == png::ColorType::Indexed { let palette = info.palette.ok_or(Error::from_str("Found indexed PNG without palette"))?; let mut palette_colors = Vec::new(); let mut iter = palette.iter(); - while let Some(color) = make_color(&mut iter) { + while let Some(color) = make_color(&mut iter, false) { palette_colors.push(color); } - - let mut dst_pixels = image_data.make_mut_slice(); + for byte in buffer.into_iter() { match bit_depth { png::BitDepth::Four => { @@ -44,15 +49,24 @@ impl TIMInfo { dst_pixels[0] = palette_colors[byte as usize]; dst_pixels = &mut dst_pixels[1..]; }, - _ => {return Err(Error::from_str("Only 4 and 8bit color depth are supported"));} + _ => {return Err(Error::from_str("Only 4 and 8bit color depth are supported for indexed color images"));} } } - Ok(TIMInfo{image_data, palette: Some(palette_colors)}) } else { - Err(Error::not_implemented("Support for non indexed images")) + let mut byte_iter = buffer.iter(); + while let Some(color) = make_color(&mut byte_iter, bytes_per_pixel == 4) { + match bit_depth { + png::BitDepth::Eight => { + dst_pixels[0] = color; + dst_pixels = &mut dst_pixels[1..]; + } + _ => {return Err(Error::from_str("Only 8bit color depth are supported for direct color images"));} + } + } + Ok(TIMInfo{image_data, palette: None}) } }