From b9aa3cf28fac3f3b4125fd819640cd183ed6b08f Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Wed, 8 May 2024 09:48:19 -0500 Subject: [PATCH] Tests for prev_pixel and backbuffer Gotta check that the previous pixel is recorded and the backbuffer is filled. There are errors in the decoder that revolve around this. --- src/main.rs | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/src/main.rs b/src/main.rs index c7f1c56..65440bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -84,7 +84,16 @@ where run_len: 0, } } + + pub(crate) fn peek_prev_pixel(&self) -> &PixelRGBA { + &self.prev_pixel + } + + pub(crate) fn peek_backbuffer(&self, idx: usize) -> &PixelRGBA { + &self.back_buffer[idx] + } } + mod codec_utils { use super::PixelRGBA; pub(crate) fn hash(pixel: PixelRGBA) -> u8 { @@ -456,4 +465,89 @@ mod test { let result: Vec = decoder.collect(); assert_eq!(result, expected); } + + #[test] + fn decoder_prev_pixel_verify() { + let compressed = [ + QOI_OP_RGB, 0x10, 0x10, 0x10, + QOI_OP_RGBA, 0x20, 0x20, 0x20, 0x20, + (QOI_OP_INDEX | 1), + (QOI_OP_DIFF | 0b0011_1111), + (QOI_OP_LUMA | 0b0011_111), 0b0011_1111, + (QOI_OP_RUN | 2), + QOI_OP_RGBA, 0xFF, 0xFF, 0xFF, 0xFF, + ]; + + let expected = [ + PixelRGBA::new(0, 0, 0, 0xFF), // init + PixelRGBA::new(0x10, 0x10, 0x10, 0xFF), // RGB + PixelRGBA::new(0x20, 0x20, 0x20, 0xFF), // RGBA + PixelRGBA::new(0, 0, 0, 0), // INDEX -- this doubles as a small test for the backbuffer operation + PixelRGBA::new(0x1, 0x1, 0x1, 0x0), // DIFF + PixelRGBA::new(0x27, 0x20, 0x27, 0x0), // LUMA + PixelRGBA::new(0x27, 0x20, 0x27, 0x0), // RUN 1 + PixelRGBA::new(0x27, 0x20, 0x27, 0x0), // RUN 2 + PixelRGBA::new(0x27, 0x20, 0x27, 0x0), // RUN 3 + // final OP_RGBA is just to flush out the OP_RUN prev_pixel value + ]; + + let mut decoder = Decoder::new(compressed.into_iter()); + + let mut result = Vec::::new(); + loop { + if let Some(_) = decoder.next() { + result.push(*decoder.peek_prev_pixel()); + } else { + break; + } + } + assert_eq!(result, expected); + } + + #[test] + fn decoder_backbuffer_verify() { + let compressed = [ + QOI_OP_RGB, 0x10, 0x10, 0x10, + QOI_OP_RGBA, 0x20, 0x20, 0x20, 0x20, + (QOI_OP_INDEX | 1), + (QOI_OP_DIFF | 0b0011_1111), + (QOI_OP_LUMA | 0b0011_111), 0b0011_1111, + (QOI_OP_RUN | 2), + QOI_OP_RGBA, 0xFF, 0xFF, 0xFF, 0xFF, + ]; + // these are the indices where we're expecting each pixel to land. + // Each pixel gets put into this backbuffer as it's en/de-coded. + // For RGB and RGBA, it'll simply assign a value into the index. + // For INDEX, the write can be skipped, and the expected index will be + // the same as the one in the op code. By definition, it has to be. + // OP_DIFF & OP_LUMA need to consider the value in the backbuffer, as + // they'll be using it to compute the new pixel. + // + let indices = [ + 31, // Pix (16, 16, 16, 255) + 0, // Pix (32, 32, 32, 32) + 1, // Pix (0, 0, 0, 0) + 3, // current state: Pix (1, 1, 1, 0) + 38, // current state: Pix(39, 32, 39, 0) + 38, // run x1 + 38, // run x2 + 38, // run x3 + ]; + let mut decoder = Decoder::new(compressed.into_iter()); + let mut iters = 0; + loop { + if let Some(pixel) = decoder.next() { + // pixel has been decompressed, so it should be in the backbuffer by this point + + // query it out: + let stored_px = decoder.peek_backbuffer(indices[iters]); + + // and compare it to the value returned from iteration + assert_eq!(&pixel, stored_px); + } else { + break; + } + iters += 1; + } + } }