From 79109cc40b4bb54695d809bab7552bce6b693de3 Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Mon, 6 May 2024 15:35:06 -0500 Subject: [PATCH] Proper operation decoding The op codes are now being recognized properly. I just gotta decode them the right way. I fixed an error where I was bitwise-or -ing the values instead of bitwise-and -ing them. Small brain up in here. --- src/main.rs | 114 ++++++++++++++++++++++++++-------------------------- 1 file changed, 58 insertions(+), 56 deletions(-) diff --git a/src/main.rs b/src/main.rs index 8217c73..9038217 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,6 +26,7 @@ const QOI_OP_INDEX: u8 = 0b0000_0000; const QOI_OP_DIFF: u8 = 0b0100_0000; const QOI_OP_LUMA: u8 = 0b1000_0000; const QOI_OP_RUN: u8 = 0b1100_0000; +const QOI_OP_SMALL_MASK: u8 = 0b1100_0000; // mask for the small op codes struct Decoder> { // QOI codec state information @@ -108,63 +109,64 @@ where self.run_len -= 1; return Some(self.prev_pixel); } else { + // Two kinds of patterns to match: + // 1. Whole byte tag -- RGB and RGBA + // 2. Partial byte tag -- 2 front bits of Index, Diff, Luma, and Run let byte = self.bytes.next()?; - match byte { - QOI_OP_RGB => { - return Some(PixelRGBA { - r: self.bytes.next()?, - g: self.bytes.next()?, - b: self.bytes.next()?, - a: self.prev_pixel.a, - }); - } - QOI_OP_RGBA => { - return Some(PixelRGBA { - r: self.bytes.next()?, - g: self.bytes.next()?, - b: self.bytes.next()?, - a: self.bytes.next()?, - }); - } - QOI_OP_INDEX => { - let idx = (byte | 0b0011_1111) as usize; - return Some(self.back_buffer[idx]); - } - QOI_OP_DIFF => { - let dr = ((byte | 0b0011_0000) >> 4) - 2; - let dg = ((byte | 0b0000_1100) >> 2) - 2; - let db = (byte | 0b0000_0011) - 2; - return Some(PixelRGBA { - r: self.prev_pixel.r + dr, - g: self.prev_pixel.g + dg, - b: self.prev_pixel.b + db, - a: self.prev_pixel.a, - }); - } - QOI_OP_LUMA => { - let dg = (byte | 0b0011_1111) - 32; - let packed = self.bytes.next()?; - let drdg = ((packed | 0b1111_0000) >> 4) - 8; - let dbdg = (packed | 0b0000_1111) - 8; - let dr = drdg + dg; - let db = dbdg + dg; - return Some(PixelRGBA { - r: self.prev_pixel.r + dr, - g: self.prev_pixel.g + dg, - b: self.prev_pixel.b + db, - a: self.prev_pixel.a, - }); - } - QOI_OP_RUN => { - self.run_len = byte | 0b0011_1111; - // storage bias of -1, so a +1 should be on the end here. - // However, I'm immediately popping off the first occurrence - // and returning a PixelRGBA, so the count is also immediatly - // dropped by 1 - return Some(self.prev_pixel); - } - _ => { - panic!("bad op code") + if byte == QOI_OP_RGB { + return Some(PixelRGBA { + r: self.bytes.next()?, + g: self.bytes.next()?, + b: self.bytes.next()?, + a: self.prev_pixel.a, + }); + }else if byte == QOI_OP_RGBA { + return Some(PixelRGBA { + r: self.bytes.next()?, + g: self.bytes.next()?, + b: self.bytes.next()?, + a: self.bytes.next()?, + }); + } else { + match byte & QOI_OP_SMALL_MASK { + QOI_OP_INDEX => { + let idx = (byte & !QOI_OP_SMALL_MASK) as usize; + return Some(self.back_buffer[idx]); + }, + QOI_OP_DIFF => { + let dr = ((byte & 0b0011_0000) >> 4) - 2; + let dg = ((byte & 0b0000_1100) >> 2) - 2; + let db = (byte & 0b0000_0011) - 2; + return Some(PixelRGBA { + r: self.prev_pixel.r + dr, + g: self.prev_pixel.g + dg, + b: self.prev_pixel.b + db, + a: self.prev_pixel.a, + }); + }, + QOI_OP_LUMA => { + let dg = (byte & !QOI_OP_SMALL_MASK) - 32; + let packed = self.bytes.next()?; + let drdg = ((packed & 0b1111_0000) >> 4) - 8; + let dbdg = (packed & 0b0000_1111) - 8; + let dr = drdg + dg; + let db = dbdg + dg; + return Some(PixelRGBA { + r: self.prev_pixel.r + dr, + g: self.prev_pixel.g + dg, + b: self.prev_pixel.b + db, + a: self.prev_pixel.a, + }); + }, + QOI_OP_RUN => { + self.run_len = byte & !QOI_OP_SMALL_MASK; + // storage bias of -1, so a +1 should be on the end here. + // However, I'm immediately popping off the first occurrence + // and returning a PixelRGBA, so the count is also immediatly + // dropped by 1 + return Some(self.prev_pixel); + }, + _ => panic!("bad op code{}", byte) } } }