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:
114
src/main.rs
114
src/main.rs
@@ -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")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user