Tweak qoi-parsing

This commit is contained in:
Sofia 2025-09-12 13:09:52 +03:00
parent d22be14de0
commit 7225591e7d
7 changed files with 71 additions and 63 deletions

BIN
images/hi.qoi Normal file

Binary file not shown.

BIN
images/hi.xcf Normal file

Binary file not shown.

BIN
images/large.qoi Normal file

Binary file not shown.

BIN
images/large.xcf Normal file

Binary file not shown.

BIN
images/sheep.qoi Normal file

Binary file not shown.

BIN
images/sheep.xcf Normal file

Binary file not shown.

View File

@ -14,7 +14,7 @@ use crate::{
}; };
// https://qoiformat.org/qoi-specification.pdf // https://qoiformat.org/qoi-specification.pdf
const image: &[u8; 288] = include_bytes!("../images/Image.qoi"); const image: &[u8; 852] = include_bytes!("../images/sheep.qoi");
const BUFFER_SIZE: usize = 64; const BUFFER_SIZE: usize = 64;
#[derive(Debug, uDebug)] #[derive(Debug, uDebug)]
@ -57,30 +57,31 @@ pub fn draw_image<T: DelayNs, DCPin: PinOps, RSTPin: PinOps>(
display.set_window( display.set_window(
position, position,
Position { Position {
x: position.x + width, x: position.x + width - 1,
y: position.y + height, y: position.y + height - 1,
}, },
); );
let qoi_iter = QoiIterator::from(iter, serial); let qoi_iter = QoiIterator::from(iter, serial, width * height);
let mut prev_pixels = [0u8; 64];
let mut chunks = qoi_iter.array_chunks::<BUFFER_SIZE>(); // let mut chunks = qoi_iter.array_chunks::<BUFFER_SIZE>();
while let Some(array) = chunks.next() { // while let Some(array) = chunks.next() {
let mut colors = [0u8; BUFFER_SIZE * 2]; // let mut colors = [0u8; BUFFER_SIZE * 2];
for (i, pixel) in array.iter().enumerate() { // for (i, pixel) in array.iter().enumerate() {
let [c1, c2] = pixel.as_color().bytes; // let [c1, c2] = pixel.as_color().bytes;
colors[i * 2] = c1; // colors[i * 2] = c1;
colors[i * 2 + 1] = c2; // colors[i * 2 + 1] = c2;
} // }
display.write(Writeable::Data(&colors)); // display.write(Writeable::Data(&colors));
} // display.delay.delay_ms(100);
if let Some(remainder) = chunks.into_remainder() { // }
for pixel in remainder { let mut counter = 0u32;
let [c1, c2] = pixel.as_color().bytes; for pixel in qoi_iter {
display.write(Writeable::Data(&[c1, c2])); let [c1, c2] = pixel.as_color().bytes;
} display.write(Writeable::Data(&[c1, c2]));
counter += 1;
} }
ufmt::uwriteln!(serial, "Counter: {}", counter).unwrap();
// display.draw_rect( // display.draw_rect(
// position, // position,
@ -104,12 +105,15 @@ struct QoiIterator<'a> {
last_pixel: Rgb565, last_pixel: Rgb565,
last_alpha: u8, last_alpha: u8,
repeat: u8, repeat: u8,
expected_colors: u16,
parsed_colors: u16,
} }
impl<'a> QoiIterator<'a> { impl<'a> QoiIterator<'a> {
fn from( fn from(
bytes: Iter<'a, u8>, bytes: Iter<'a, u8>,
serial: &'a mut Usart<USART0, Pin<mode::Input, PD0>, Pin<mode::Output, PD1>, CoreClock>, serial: &'a mut Usart<USART0, Pin<mode::Input, PD0>, Pin<mode::Output, PD1>, CoreClock>,
expected: u16,
) -> Self { ) -> Self {
QoiIterator { QoiIterator {
inner: bytes, inner: bytes,
@ -119,6 +123,8 @@ impl<'a> QoiIterator<'a> {
last_pixel: Rgb565(0, 0, 0), last_pixel: Rgb565(0, 0, 0),
last_alpha: 255, last_alpha: 255,
repeat: 0, repeat: 0,
expected_colors: expected,
parsed_colors: 0,
} }
} }
} }
@ -127,6 +133,11 @@ impl<'a> Iterator for QoiIterator<'a> {
type Item = Rgb565; type Item = Rgb565;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.parsed_colors >= self.expected_colors {
return None;
}
self.parsed_colors += 1;
if self.repeat > 0 { if self.repeat > 0 {
self.repeat -= 1; self.repeat -= 1;
return Some(self.last_pixel); return Some(self.last_pixel);
@ -137,19 +148,19 @@ impl<'a> Iterator for QoiIterator<'a> {
let green = self.inner.next().unwrap(); let green = self.inner.next().unwrap();
let blue = self.inner.next().unwrap(); let blue = self.inner.next().unwrap();
let alpha = self.inner.next().unwrap(); let alpha = self.inner.next().unwrap();
ufmt::uwriteln!(self.serial, "RGBA: {} {} {} {}", red, green, blue, alpha).unwrap(); // ufmt::uwriteln!(self.serial, "RGBA: {} {} {} {}", red, green, blue, alpha).unwrap();
(Rgb565(*red, *green, *blue), *alpha) (Rgb565(*red, *green, *blue), *alpha)
} else if *byte == 0b11111110 { } else if *byte == 0b11111110 {
let red = self.inner.next().unwrap(); let red = self.inner.next().unwrap();
let green = self.inner.next().unwrap(); let green = self.inner.next().unwrap();
let blue = self.inner.next().unwrap(); let blue = self.inner.next().unwrap();
ufmt::uwriteln!(self.serial, "RGB: {} {} {}", red, green, blue).unwrap(); // ufmt::uwriteln!(self.serial, "RGB: {} {} {}", red, green, blue).unwrap();
(Rgb565(*red, *green, *blue), self.last_alpha) (Rgb565(*red, *green, *blue), self.last_alpha)
} else { } else {
let tag = (0b11000000 & byte) >> 6; let tag = (0b11000000 & byte) >> 6;
let data = 0b00111111 & byte; let data = 0b00111111 & byte;
ufmt::uwriteln!(self.serial, "Tag: {}", tag).unwrap(); // ufmt::uwriteln!(self.serial, "Tag: {}", tag).unwrap();
if tag == 0 { if tag == 0 {
( (
@ -160,14 +171,14 @@ impl<'a> Iterator for QoiIterator<'a> {
let dr = ((0b110000 & data) >> 4) as i8 - 2; let dr = ((0b110000 & data) >> 4) as i8 - 2;
let dg = ((0b001100 & data) >> 2) as i8 - 2; let dg = ((0b001100 & data) >> 2) as i8 - 2;
let db = (0b000011 & data) as i8 - 2; let db = (0b000011 & data) as i8 - 2;
ufmt::uwriteln!( // ufmt::uwriteln!(
self.serial, // self.serial,
"Diffs: {} {} {}", // "Diffs: {} {} {}",
((0b110000 & data) >> 4), // ((0b110000 & data) >> 4),
((0b001100 & data) >> 2), // ((0b001100 & data) >> 2),
(0b000011 & data) // (0b000011 & data)
) // )
.unwrap(); // .unwrap();
( (
Rgb565( Rgb565(
(self.last_pixel.0 as i8).wrapping_add(dr) as u8, (self.last_pixel.0 as i8).wrapping_add(dr) as u8,
@ -183,36 +194,33 @@ impl<'a> Iterator for QoiIterator<'a> {
let db_dg = (0b00001111 & second) as i8 - 8; let db_dg = (0b00001111 & second) as i8 - 8;
let dr = dr_dg + dg; let dr = dr_dg + dg;
let db = db_dg + dg; let db = db_dg + dg;
ufmt::uwriteln!(
self.serial, let a = self.last_pixel.0 as i8;
"Last: {} {} {}", let b = self.last_pixel.1 as i8;
self.last_pixel.0 as i8, let c = self.last_pixel.2 as i8;
self.last_pixel.1 as i8, // ufmt::uwriteln!(self.serial, "Hello there! {} {} {}", a, b, c).unwrap();
self.last_pixel.2 as i8 // ufmt::uwriteln!(self.serial, "Values: {} {} {}", dr_dg, dg, db_dg).unwrap();
) // ufmt::uwriteln!(self.serial, "Diffs: {} {} {}", dr, dg, db).unwrap();
.unwrap(); // ufmt::uwriteln!(
ufmt::uwriteln!(self.serial, "Values: {} {} {}", dr_dg, dg, db_dg).unwrap(); // self.serial,
ufmt::uwriteln!(self.serial, "Diffs: {} {} {}", dr, dg, db).unwrap(); // "Res: {} {} {}",
ufmt::uwriteln!( // self.last_pixel.0 as i8 + dr,
self.serial, // self.last_pixel.1 as i8 + dg,
"Res: {} {} {}", // self.last_pixel.2 as i8 + db
self.last_pixel.0 as i8 + dr, // )
self.last_pixel.1 as i8 + dg, // .unwrap();
self.last_pixel.2 as i8 + db
)
.unwrap();
( (
Rgb565( Rgb565(
(self.last_pixel.0 as i8).wrapping_add(dr) as u8, (self.last_pixel.0 as i8 + dr) as u8,
(self.last_pixel.1 as i8).wrapping_add(dg) as u8, (self.last_pixel.1 as i8 + dg) as u8,
(self.last_pixel.2 as i8).wrapping_add(db) as u8, (self.last_pixel.2 as i8 + db) as u8,
), ),
self.last_alpha, self.last_alpha,
) )
} else if tag == 3 { } else if tag == 3 {
// QOI_OP_RUN // QOI_OP_RUN
self.repeat = data; self.repeat = data;
ufmt::uwriteln!(self.serial, "Repeat: {}", self.repeat).unwrap(); // ufmt::uwriteln!(self.serial, "Repeat: {}", self.repeat).unwrap();
(self.last_pixel, self.last_alpha) (self.last_pixel, self.last_alpha)
} else { } else {
(Rgb565::green(), 255) (Rgb565::green(), 255)
@ -224,16 +232,16 @@ impl<'a> Iterator for QoiIterator<'a> {
((color.0 as u32 * 3 + color.1 as u32 * 5 + color.2 as u32 * 7 + alpha as u32 * 11) ((color.0 as u32 * 3 + color.1 as u32 * 5 + color.2 as u32 * 7 + alpha as u32 * 11)
% 64) as usize; % 64) as usize;
ufmt::uwriteln!( // ufmt::uwriteln!(
self.serial, // self.serial,
"Color: {} {} {} {}, Hash: {}", // "Color: {} {} {} {}, Hash: {}",
color.0, // color.0,
color.1, // color.1,
color.2, // color.2,
alpha, // alpha,
hash // hash
) // )
.unwrap(); // .unwrap();
self.prev_pixels[hash] = color; self.prev_pixels[hash] = color;
Some(color) Some(color)
} else { } else {