From 04f83a55d2da4e4a7d6cbc01477a2be0099d55ed Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Mon, 13 Oct 2025 10:05:31 -0500 Subject: [PATCH] Add "full" image decode test to decoder.rs This is a full QOI file decode routine, although the image it contains is just one single blue pixel. I've added this because I finally found the bug I've been hunting: I'm using `tests/codec.rs` to load reference files and decode them, but this is resulting in data size errors. There are 32 extra bytes coming out of the decoder -- too much for the WIDTH x HEIGHT number of pixels, and it happens to every image. The cause is the 8-byte end marker. It is not properly detected by the decoder and is instead used as additional data (probably QOI_OP_INDEX). Since the decoder emits *pixels*, each of which are 4 bytes, we have 32 bytes of garbage data coming out of the decoder. Bug found! Now to make the test pass... --- src/decoder.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/decoder.rs b/src/decoder.rs index 292769d..ad4ba28 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -666,4 +666,38 @@ mod test { expected ); } + + /// Try decoding an image consisting of a single pixel. + #[test] + fn decode_1_pixel_image() { + let input: [u8; 26] = [ + 0x71, 0x6f, 0x69, 0x66, // 'qoif' magic bytes + 0x00, 0x00, 0x00, 0x01, // u32 width + 0x00, 0x00, 0x00, 0x01, // u32 height + 0x03, // u8 channels (3 for RGB mode) + 0x00, // u8 colorspace (0 for sRGB w/ linear alpha) + // One single blue pixel, QOI_OP_RGB + 0xFE, 0x00, 0x00, 0xFF, + // footer + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 + ]; + + let mut decoder = Decoder::try_new(input.into_iter()) + .expect("Failed to initialize decoder from byte array"); + + // Check the metadata + assert_eq!(decoder.width, 1); + assert_eq!(decoder.height, 1); + assert_eq!(decoder.channels, 3); + assert_eq!(decoder.colorspace, 0); + + // Grab the one single pixel and check that it's solid blue. + let pixel = decoder.next().expect("Couldn't get pixel from decoder"); + assert_eq!(pixel, PixelRGBA::new(0, 0, 255, 255)); + + // Assert that there are no more pixels. + let pixel = decoder.next(); + assert!(pixel.is_none()); + } } \ No newline at end of file