use core::slice::Iter; use atmega_hal::{ Atmega, Usart, pac::USART0, port::{PB3, PB5, PD0, PD1, Pin, PinOps, mode}, }; use embedded_hal::delay::DelayNs; use ufmt::derive::uDebug; use crate::{ CoreClock, display::{Color, Display, Position, Rgb565, Writeable}, }; // https://qoiformat.org/qoi-specification.pdf const image: &[u8; 1253] = include_bytes!("../images/hi.qoi"); #[derive(Debug, uDebug)] pub enum QoiErr { InvalidMagicNumber, UnexpectedEOF, } pub fn draw_image( serial: &mut Usart, Pin, CoreClock>, display: &mut Display, position: Position, ) -> Result<(), QoiErr> { let mut iter = image.iter(); if let (Some(113), Some(111), Some(105), Some(102)) = (iter.next(), iter.next(), iter.next(), iter.next()) { fn next<'a>(iter: &mut Iter<'a, u8>) -> Result<&'a u8, QoiErr> { iter.next().ok_or(QoiErr::UnexpectedEOF) } let width = u32::from_be_bytes([ *next(&mut iter)?, *next(&mut iter)?, *next(&mut iter)?, *next(&mut iter)?, ]) as u16; let height = u32::from_be_bytes([ *next(&mut iter)?, *next(&mut iter)?, *next(&mut iter)?, *next(&mut iter)?, ]) as u16; let channels = *next(&mut iter)?; let colorspace = *next(&mut iter)?; ufmt::uwriteln!(serial, "Successfully read QOI header").unwrap(); display.set_window( position, Position { x: position.x + width - 1, y: position.y + height - 1, }, ); let qoi_iter = QoiIterator::from(iter, serial, width * height); // let mut chunks = qoi_iter.array_chunks::(); // while let Some(array) = chunks.next() { // let mut colors = [0u8; BUFFER_SIZE * 2]; // for (i, pixel) in array.iter().enumerate() { // let [c1, c2] = pixel.as_color().bytes; // colors[i * 2] = c1; // colors[i * 2 + 1] = c2; // } // display.write(Writeable::Data(&colors)); // } let mut counter = 0u32; for pixel in qoi_iter { let [c1, c2] = pixel.as_color().bytes; display.write(Writeable::Data(&[c1, c2])); counter += 1; } ufmt::uwriteln!(serial, "Counter: {}", counter).unwrap(); // display.draw_rect( // position, // Position { // x: position.x + 100, // y: position.y + 100, // }, // Rgb565::green().as_color(), // ); Ok(()) } else { Err(QoiErr::InvalidMagicNumber) } } struct QoiIterator<'a> { inner: Iter<'a, u8>, serial: &'a mut Usart, Pin, CoreClock>, prev_pixels: [Rgb565; 64], last_pixel: Rgb565, repeat: u8, expected_colors: u16, parsed_colors: u16, } impl<'a> QoiIterator<'a> { fn from( bytes: Iter<'a, u8>, serial: &'a mut Usart, Pin, CoreClock>, expected: u16, ) -> Self { QoiIterator { inner: bytes, serial, prev_pixels: [Rgb565(0, 255, 0); 64], last_pixel: Rgb565(0, 0, 0), repeat: 0, expected_colors: expected, parsed_colors: 0, } } } impl<'a> Iterator for QoiIterator<'a> { type Item = Rgb565; fn next(&mut self) -> Option { if self.parsed_colors >= self.expected_colors { ufmt::uwriteln!(self.serial, "Reached expected").unwrap(); return None; } self.parsed_colors += 1; if self.repeat > 0 { self.repeat -= 1; return Some(self.last_pixel); } if let Some(byte) = self.inner.next() { let color = if *byte == 0xff { let red = self.inner.next().unwrap(); let green = self.inner.next().unwrap(); let blue = self.inner.next().unwrap(); let _alpha = self.inner.next().unwrap(); // ufmt::uwriteln!(self.serial, "RGBA: {} {} {} {}", red, green, blue, alpha).unwrap(); Rgb565(*red, *green, *blue) } else if *byte == 0b11111110 { let red = self.inner.next().unwrap(); let green = self.inner.next().unwrap(); let blue = self.inner.next().unwrap(); // ufmt::uwriteln!(self.serial, "RGB: {} {} {}", red, green, blue).unwrap(); Rgb565(*red, *green, *blue) } else { let tag = (0b11000000 & byte) >> 6; let data = 0b00111111 & byte; // ufmt::uwriteln!(self.serial, "Tag: {}", tag).unwrap(); if tag == 0 { self.prev_pixels[data as usize] } else if tag == 1 { let dr = ((0b110000 & data) >> 4) as i8 - 2; let dg = ((0b001100 & data) >> 2) as i8 - 2; let db = (0b000011 & data) as i8 - 2; // ufmt::uwriteln!( // self.serial, // "Diffs: {} {} {}", // ((0b110000 & data) >> 4), // ((0b001100 & data) >> 2), // (0b000011 & data) // ) // .unwrap(); Rgb565( (self.last_pixel.0 as i8).wrapping_add(dr) as u8, (self.last_pixel.1 as i8).wrapping_add(dg) as u8, (self.last_pixel.2 as i8).wrapping_add(db) as u8, ) } else if tag == 2 { let second = self.inner.next().unwrap(); let dg = data as i8 - 32; let dr_dg = ((0b11110000 & second) >> 4) as i8 - 8; let db_dg = (0b00001111 & second) as i8 - 8; let dr = dr_dg + dg; let db = db_dg + dg; let a = self.last_pixel.0 as i8; let b = self.last_pixel.1 as i8; let c = self.last_pixel.2 as i8; // ufmt::uwriteln!(self.serial, "Hello there! {} {} {}", a, b, c).unwrap(); // ufmt::uwriteln!(self.serial, "Values: {} {} {}", dr_dg, dg, db_dg).unwrap(); // ufmt::uwriteln!(self.serial, "Diffs: {} {} {}", dr, dg, db).unwrap(); // ufmt::uwriteln!( // self.serial, // "Res: {} {} {}", // self.last_pixel.0 as i8 + dr, // self.last_pixel.1 as i8 + dg, // self.last_pixel.2 as i8 + db // ) // .unwrap(); Rgb565( (self.last_pixel.0 as i8 + dr) as u8, (self.last_pixel.1 as i8 + dg) as u8, (self.last_pixel.2 as i8 + db) as u8, ) } else if tag == 3 { // QOI_OP_RUN self.repeat = data; // ufmt::uwriteln!(self.serial, "Repeat: {}", self.repeat).unwrap(); self.last_pixel } else { Rgb565::green() } }; self.last_pixel = color; let hash = ((color.0 as u32 * 3 + color.1 as u32 * 5 + color.2 as u32 * 7 + 255 as u32 * 11) % 64) as usize; // ufmt::uwriteln!( // self.serial, // "Color: {} {} {} {}, Hash: {}", // color.0, // color.1, // color.2, // alpha, // hash // ) // .unwrap(); self.prev_pixels[hash] = color; Some(color) } else { ufmt::uwriteln!(self.serial, "End reached").unwrap(); None } } }