From ac4df9e8ed08def646e8d846db69ff9c19e32037 Mon Sep 17 00:00:00 2001 From: gered Date: Mon, 20 Mar 2023 17:47:18 -0400 Subject: [PATCH] merge functionality of PixelDecoder and ScanlineBuffer together --- ggdt/src/graphics/bitmap/png.rs | 104 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/ggdt/src/graphics/bitmap/png.rs b/ggdt/src/graphics/bitmap/png.rs index 8d830bf..c6d3ee2 100644 --- a/ggdt/src/graphics/bitmap/png.rs +++ b/ggdt/src/graphics/bitmap/png.rs @@ -166,55 +166,12 @@ impl Filter { } } -trait PixelConversion { - fn read_png_pixel(&mut self, reader: &mut T, palette: &Option) -> Result; -} - -struct PixelDecoder { - pub format: ColorFormat, -} - -impl PixelConversion for PixelDecoder { - fn read_png_pixel(&mut self, reader: &mut T, _palette: &Option) -> Result { - match self.format { - ColorFormat::IndexedColor => { - Ok(reader.read_u8()?) - } - _ => return Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))), - } - } -} - -impl PixelConversion for PixelDecoder { - fn read_png_pixel(&mut self, reader: &mut T, palette: &Option) -> Result { - match self.format { - ColorFormat::IndexedColor => { - let color = reader.read_u8()?; - if let Some(palette) = palette { - Ok(palette[color]) - } else { - return Err(PngError::BadFile(String::from("No palette to map indexed-color format pixels to RGBA format destination"))); - } - } - ColorFormat::RGB => { - let r = reader.read_u8()?; - let g = reader.read_u8()?; - let b = reader.read_u8()?; - Ok(to_rgb32(r, g, b)) - } - ColorFormat::RGBA => { - let r = reader.read_u8()?; - let g = reader.read_u8()?; - let b = reader.read_u8()?; - let a = reader.read_u8()?; - Ok(to_argb32(a, r, g, b)) - } - _ => return Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))), - } - } +trait ScanlinePixelConverter { + fn read_pixel(&mut self, x: usize, palette: &Option) -> Result; } struct ScanlineBuffer { + format: ColorFormat, stride: usize, bpp: usize, y: usize, @@ -233,6 +190,7 @@ impl ScanlineBuffer { }; let stride = ihdr.width as usize * bpp; Ok(ScanlineBuffer { + format: ihdr.format, stride, bpp, y: 0, @@ -275,7 +233,7 @@ impl ScanlineBuffer { } } - pub fn read_line(&mut self, reader: &mut T) -> Result<&[u8], PngError> { + pub fn read_line(&mut self, reader: &mut T) -> Result<(), PngError> { if self.y >= self.height { return Err(PngError::IOError(io::Error::from(io::ErrorKind::UnexpectedEof))); } else if self.y >= 1 { @@ -291,17 +249,60 @@ impl ScanlineBuffer { self.current[x] = decoded; } - Ok(&self.current) + Ok(()) } } +impl ScanlinePixelConverter for ScanlineBuffer { + fn read_pixel(&mut self, x: usize, _palette: &Option) -> Result { + let offset = x * self.bpp; + match self.format { + ColorFormat::IndexedColor => { + Ok(self.current[offset]) + } + _ => return Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))), + } + } +} + +impl ScanlinePixelConverter for ScanlineBuffer { + fn read_pixel(&mut self, x: usize, palette: &Option) -> Result { + let offset = x * self.bpp; + match self.format { + ColorFormat::IndexedColor => { + let color = self.current[offset]; + if let Some(palette) = palette { + Ok(palette[color]) + } else { + return Err(PngError::BadFile(String::from("No palette to map indexed-color format pixels to RGBA format destination"))); + } + } + ColorFormat::RGB => { + let r = self.current[offset]; + let g = self.current[offset + 1]; + let b = self.current[offset + 2]; + Ok(to_rgb32(r, g, b)) + } + ColorFormat::RGBA => { + let r = self.current[offset]; + let g = self.current[offset + 1]; + let b = self.current[offset + 2]; + let a = self.current[offset + 3]; + Ok(to_argb32(a, r, g, b)) + } + _ => return Err(PngError::BadFile(format!("Unsupported color format for this PixelReader: {:?}", self.format))), + } + } +} + + fn load_png_bytes( reader: &mut Reader ) -> Result<(Bitmap, Option), PngError> where Reader: ReadBytesExt + Seek, PixelType: Pixel, - PixelDecoder: PixelConversion + ScanlineBuffer: ScanlinePixelConverter { let header: [u8; 8] = reader.read_bytes()?; if header != PNG_HEADER { @@ -380,16 +381,15 @@ where compressed_data.append(&mut read_chunk_data(reader, &chunk_header)?); } - let mut pixel_decoder = PixelDecoder { format: ihdr.format }; let mut scanline_buffer = ScanlineBuffer::new(&ihdr)?; let mut output = Bitmap::internal_new(ihdr.width, ihdr.height).unwrap(); let mut deflater = flate2::read::ZlibDecoder::<&[u8]>::new(&compressed_data); for y in 0..ihdr.height as usize { - let mut line = scanline_buffer.read_line(&mut deflater)?; + scanline_buffer.read_line(&mut deflater)?; for x in 0..ihdr.width as usize { - let pixel = pixel_decoder.read_png_pixel(&mut line, &palette)?; + let pixel = scanline_buffer.read_pixel(x, &palette)?; // TODO: we can make this a bit more efficient ... unsafe { output.set_pixel_unchecked(x as i32, y as i32, pixel); } }