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.
This commit is contained in:
2024-05-06 15:35:06 -05:00
parent aa18ba5992
commit 79109cc40b

View File

@@ -26,6 +26,7 @@ const QOI_OP_INDEX: u8 = 0b0000_0000;
const QOI_OP_DIFF: u8 = 0b0100_0000; const QOI_OP_DIFF: u8 = 0b0100_0000;
const QOI_OP_LUMA: u8 = 0b1000_0000; const QOI_OP_LUMA: u8 = 0b1000_0000;
const QOI_OP_RUN: u8 = 0b1100_0000; const QOI_OP_RUN: u8 = 0b1100_0000;
const QOI_OP_SMALL_MASK: u8 = 0b1100_0000; // mask for the small op codes
struct Decoder<I: Iterator<Item = u8>> { struct Decoder<I: Iterator<Item = u8>> {
// QOI codec state information // QOI codec state information
@@ -108,63 +109,64 @@ where
self.run_len -= 1; self.run_len -= 1;
return Some(self.prev_pixel); return Some(self.prev_pixel);
} else { } 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()?; let byte = self.bytes.next()?;
match byte { if byte == QOI_OP_RGB {
QOI_OP_RGB => { return Some(PixelRGBA {
return Some(PixelRGBA { r: self.bytes.next()?,
r: self.bytes.next()?, g: self.bytes.next()?,
g: self.bytes.next()?, b: self.bytes.next()?,
b: self.bytes.next()?, a: self.prev_pixel.a,
a: self.prev_pixel.a, });
}); }else if byte == QOI_OP_RGBA {
} return Some(PixelRGBA {
QOI_OP_RGBA => { r: self.bytes.next()?,
return Some(PixelRGBA { g: self.bytes.next()?,
r: self.bytes.next()?, b: self.bytes.next()?,
g: self.bytes.next()?, a: self.bytes.next()?,
b: self.bytes.next()?, });
a: self.bytes.next()?, } else {
}); match byte & QOI_OP_SMALL_MASK {
} QOI_OP_INDEX => {
QOI_OP_INDEX => { let idx = (byte & !QOI_OP_SMALL_MASK) as usize;
let idx = (byte | 0b0011_1111) as usize; return Some(self.back_buffer[idx]);
return Some(self.back_buffer[idx]); },
} QOI_OP_DIFF => {
QOI_OP_DIFF => { let dr = ((byte & 0b0011_0000) >> 4) - 2;
let dr = ((byte | 0b0011_0000) >> 4) - 2; let dg = ((byte & 0b0000_1100) >> 2) - 2;
let dg = ((byte | 0b0000_1100) >> 2) - 2; let db = (byte & 0b0000_0011) - 2;
let db = (byte | 0b0000_0011) - 2; return Some(PixelRGBA {
return Some(PixelRGBA { r: self.prev_pixel.r + dr,
r: self.prev_pixel.r + dr, g: self.prev_pixel.g + dg,
g: self.prev_pixel.g + dg, b: self.prev_pixel.b + db,
b: self.prev_pixel.b + db, a: self.prev_pixel.a,
a: self.prev_pixel.a, });
}); },
} QOI_OP_LUMA => {
QOI_OP_LUMA => { let dg = (byte & !QOI_OP_SMALL_MASK) - 32;
let dg = (byte | 0b0011_1111) - 32; let packed = self.bytes.next()?;
let packed = self.bytes.next()?; let drdg = ((packed & 0b1111_0000) >> 4) - 8;
let drdg = ((packed | 0b1111_0000) >> 4) - 8; let dbdg = (packed & 0b0000_1111) - 8;
let dbdg = (packed | 0b0000_1111) - 8; let dr = drdg + dg;
let dr = drdg + dg; let db = dbdg + dg;
let db = dbdg + dg; return Some(PixelRGBA {
return Some(PixelRGBA { r: self.prev_pixel.r + dr,
r: self.prev_pixel.r + dr, g: self.prev_pixel.g + dg,
g: self.prev_pixel.g + dg, b: self.prev_pixel.b + db,
b: self.prev_pixel.b + db, a: self.prev_pixel.a,
a: self.prev_pixel.a, });
}); },
} QOI_OP_RUN => {
QOI_OP_RUN => { self.run_len = byte & !QOI_OP_SMALL_MASK;
self.run_len = byte | 0b0011_1111; // storage bias of -1, so a +1 should be on the end here.
// storage bias of -1, so a +1 should be on the end here. // However, I'm immediately popping off the first occurrence
// However, I'm immediately popping off the first occurrence // and returning a PixelRGBA, so the count is also immediatly
// and returning a PixelRGBA, so the count is also immediatly // dropped by 1
// dropped by 1 return Some(self.prev_pixel);
return Some(self.prev_pixel); },
} _ => panic!("bad op code{}", byte)
_ => {
panic!("bad op code")
} }
} }
} }