From 7225591e7dd55f08e097b263635aa3bd72643543 Mon Sep 17 00:00:00 2001 From: Sofia Date: Fri, 12 Sep 2025 13:09:52 +0300 Subject: [PATCH] Tweak qoi-parsing --- images/hi.qoi | Bin 0 -> 744 bytes images/hi.xcf | Bin 0 -> 4394 bytes images/large.qoi | Bin 0 -> 1698 bytes images/large.xcf | Bin 0 -> 9065 bytes images/sheep.qoi | Bin 0 -> 852 bytes images/sheep.xcf | Bin 0 -> 3602 bytes src/qoi.rs | 134 +++++++++++++++++++++++++---------------------- 7 files changed, 71 insertions(+), 63 deletions(-) create mode 100644 images/hi.qoi create mode 100644 images/hi.xcf create mode 100644 images/large.qoi create mode 100644 images/large.xcf create mode 100644 images/sheep.qoi create mode 100644 images/sheep.xcf diff --git a/images/hi.qoi b/images/hi.qoi new file mode 100644 index 0000000000000000000000000000000000000000..21ac898ae98ae1ee0628d2658418da2f321a74f3 GIT binary patch literal 744 zcmaiy%MHRX42Fx?#T)p}60Cs42{8e)C4HrBQn+wr0A@f)_;*^72-H?`oiF}l=i&3| zcqocu2iq3=w|?Pb=*7{zc&Fy67C&>#SF&sqzL8mFLt)An*Dvu%rD(tUoE>|rk~p}O z`m=tSt(D_8sLkKs? z(FSgW4UIC_iXXUEpR<*?(Rt66_$4m&h_gP3wwvl9|1V=t@v37Sdx%d3ek_iy?mcQS iMhl@ne9m~vG!907==-DwS`vo%Q!F;I{=M`yzRd>!v14EW literal 0 HcmV?d00001 diff --git a/images/hi.xcf b/images/hi.xcf new file mode 100644 index 0000000000000000000000000000000000000000..0de368f91afd952e447afa268e9e0cab34b4124f GIT binary patch literal 4394 zcmeHJ&2HO95T+&D`m^k$O#`$jiY?nhPFhlw(!_}%$&Q`IFwh`|sbAy{QN4KbA1#E!tz!CZ^9G+5^( zC#8Zia#=)}YYb@!He=5;LmEL~U@zbV=8Z8yU+qJF4+GDjgHb^DJlAB_(a2RyW>e)y zk12HQdqJewdN@fx9)WaA$hJcxeV|7=z6a%s-rXKMHhD{fka=#e(NeVrp|0T#U@yJK z%j2iY!^U>M+RY~R;V`<9ZV^{^XixrT%uMwF4^rJ_QFus$7rNuyRPH|{@as0g^x`Q` zpfrw|1J-S=eZQkU>a^OV)$ZKe>a_1KIQMzLEavL=RebQkzoo7f4dwoWujj1Dt-oV~ zg^Z6V6!9p6q`rhxhv4Qoe|0)R?r*i5tvUAJFKmA}^de8)!;AC+Y7~-vvG2q-JC-Mq z*@*p22barj-pSR@C-L!|-;kt2zSQn@H0{EyOivJEzvRr*fTt&7$>Uw7#1E*+#y#1` z+=fHXm&quwd-5=f{7$p!hN?dB-cS{~VRK^Bgv-^G``zZm&(zI$<@oBvTE$aHyQi4{ z&VO+MJ;^+|f`bD;GStVuZ!<&3 z3)w!KT19)Lw9dVvXD4GhPR`}r!{|0oyCpVSVU&IsgbeNgK*CYm)r}vlz#F;zt5`_h zN~^%};~N8gig^1Mc)|x72;XC)ms1Q(`dGkK0TTh=6>v?!YXYtdcmpu5myHqtTpQQ= zBE`U@&k@HkfPW_7><>h?Cs5%i|C#XIa|a|O{Idb0{5NOGV+R-#jPgGTm!x+~zs3cr zn^GNkg;QNx1)j;}_=Z%Bi-LSpD$JD&(t7GInLkV3fUS%Ayj+Rv(u$x*c^THv{Lhw) zu%|Wde}l(!o?PSpQD5aYdAS-_Q$5Z_n|X2t@>hhMt*7=V-{!a$mvgujS9oq?zHUK6 zeM#8cT3iCTAZ@_AGVrx{mGit@1buW6C1=>L%2Tjyo_fl>QP4jXkQc7z?wut{av7Ug}>tKDy~2_D{;PRr{(!o pJ6+Y+ReV~xS*7Qz_PUB^_g?&-h`su}-aFl!ud6ugegDT^{4a-ac9sAD literal 0 HcmV?d00001 diff --git a/images/large.qoi b/images/large.qoi new file mode 100644 index 0000000000000000000000000000000000000000..9ebd755351575fd3971d38cce6d7cfb71be7614a GIT binary patch literal 1698 zcmXTS&rD-rVE6#S%nYG_U)3K}`}_CrN7GSiGzdmh0r45(s3|bpz`zr=zpqA<&uH=? SKKYEQM5}a;0&64?U<3f1F}A$` literal 0 HcmV?d00001 diff --git a/images/large.xcf b/images/large.xcf new file mode 100644 index 0000000000000000000000000000000000000000..8fd96d9d594c6c07c7eacf0fe5378ec6a9b345ff GIT binary patch literal 9065 zcmeHMTW=Fb6dtb~Uz3oKs~avG2S@_MH!gwT1QDPJsR+tNr4?0WoQ<=pZ?YF^`eI)C zULIPh{SW|zAmADYga8I$(xoXkAw>9B;Gr^9FO}-ms#S9^7MwhKvuPC_ zYs37;cDBqrckeym%!m@TtHrXlRBqZE3lYSX(fAgC6_mI`IU?L zm0b3aYwtJhvRx}y-baVp_$OAa>}+BA#e;6C#6Pn)4k!K4f;YZ!VAdx%KIlK-fu433 zq}G=6ncM;LpC4NO!B*X=r*ASM9>LjQ?)`OZS?^$O!M2Y5t+nxP*4?S({Z2^hxUXDY z`^dTMg_Z37XVkmExA%8k+1+sOLOMNz(lQ%OYtwG8rW&+uYpdQ!nJ=1^)zp^bG*&X1 zS}R@Ls6V&TNNbsGnGC`!lUgfew)OPH#?xvey)B*QDY$9SZ~w<$gdDuPcJ*!hY8M-a z+7Yy*^**?xLv5v-A^1pCaL>&=AEE+TY4g>4D7f2jO6ePoM#U}_8Ibwird`TjUCQkl zqPrK<9kUXJ-|oE(OK#e~Fpo<|Oi;Ec}!$AA~rd56S2 z#`Kdj7>@v-2GC#VZ}h{i-x)prw);89)tXL!ABd+pfNPIIAv-Rx!s#r^YPFkYRXYJI zvI_RntYn(6*Y?s;wbrYk)T8Mbvdvy}9IcMWKZ|=_bDng@_B*-h|fu6YGz?gk0bVj!a!s(rsIe- zVkzU8XV#5kJdJ3JA_|9q2cRz|7BJU|y@8|`$=5)$rw_?VwSy31cSen8z)PSG1QAbR zWR)=PHsp?jkRi==hByZ8+!e<`$TJH?@Rrnn_W$F#kKpuK)x7GaF}qU(T`Ic;4}0B% z?kd<_9Kk$ucNnzpOcS67@TL|*N11?EMF1hhLL5FnD$;U9WYNuZ56`xs4<0?Zm|Cuvx9n3wH(PN3cqQ`MHAHdrZ^^wPWvZk`G>#^?SSpoTF$pD`@ zkCo9sHjtJ0g^7FOyf>ykjst35Khw^!&Yb~OWxMlS&o^+&@?IXzeen5G;IW4of}HL> zrWAit9#{LClE)N2i@tz%@yA6c7Lk2h_iatz`mgylCXt`Uz)vE7O#t%?_!O}B_FTYTuVKut o-;483q$c~e(0Q+Ki=BSq@9_>r;{#&H1^mCL?E?RGRB%E31w1LEp8x;= literal 0 HcmV?d00001 diff --git a/images/sheep.qoi b/images/sheep.qoi new file mode 100644 index 0000000000000000000000000000000000000000..cc4ea456ebc9a5924231188d345d6a812bfd557a GIT binary patch literal 852 zcmb7>!D@ss5QZ&%1EH@lmz?L?x9F|sLQkbnV4tkW5~PU8Qba^ViipS}ihW3Uy16}d o?yUS_wss>iP~|{JbHdiZ$9!(^_E)Kq`IwFX$;m}X1(p4H8s9%HudVp{CcfkF`K46&!esT zDleRfhvL5Yl&>{S)e-pIV_qmLQ+|0xDQ|BJyt09SZ>|wAaP%WjQ^UyJwxw2dqt53P z%yTx<3p-NB&>dbkDh;g-o32@_wKWF|gMCa7)KOzf&=-fu@3C!Gv}(uJ4ost_*H1cz zRMVT9^n`pA(EzMD@s-x04UM4Dqy>6??zt!xvZW=`~Co3Ya z85Oe%E=BRx>DST|aj!IAh#X5OM!`|*yrH(VqVQE$ugOPLNO@m(+Q*vxQf*mHO(;F# z@hfCuda=thY>iXB1?#+$-`Z7nc5`_?_h?ti@8*>&`o6IBx^Ae=o5b)J{*7kTorX}# z!uvCx|I_G%T)w()YudWHs&%CmA&MNVgI08zr{L{>OvtQkBAt)vpU3otn7$a( zQ!#xBI?Wd~`YS+jX|AX8#G~+#i8lv;&#?E0B!!7XI{7EC)RB9{9NHiHxw~ZTeX79x+1F+xEeEMaFqO zt`zvX@O9zq1AZ<6zCPgR65#6tzOL`%m#{iD~QHl7qQ;5r7dbQ7iE39iuRTyXUzxVrF|2+RZN)|K34VTEIhieaSs*xND>!i(?2L@J%I-}By(5U2fnzC83T1EM zHtTV+i)cV_?hws|HL&U;+62%$f{61-(Kxml(`H!8rIAQ-Y{~Br`%{R_@7(E0!X literal 0 HcmV?d00001 diff --git a/src/qoi.rs b/src/qoi.rs index 0d82689..bb776c6 100644 --- a/src/qoi.rs +++ b/src/qoi.rs @@ -14,7 +14,7 @@ use crate::{ }; // 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; #[derive(Debug, uDebug)] @@ -57,30 +57,31 @@ pub fn draw_image( display.set_window( position, Position { - x: position.x + width, - y: position.y + height, + x: position.x + width - 1, + y: position.y + height - 1, }, ); - let qoi_iter = QoiIterator::from(iter, serial); - let mut prev_pixels = [0u8; 64]; + 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)); - } - if let Some(remainder) = chunks.into_remainder() { - for pixel in remainder { - let [c1, c2] = pixel.as_color().bytes; - display.write(Writeable::Data(&[c1, c2])); - } + // 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)); + // display.delay.delay_ms(100); + // } + 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, @@ -104,12 +105,15 @@ struct QoiIterator<'a> { last_pixel: Rgb565, last_alpha: u8, 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, @@ -119,6 +123,8 @@ impl<'a> QoiIterator<'a> { last_pixel: Rgb565(0, 0, 0), last_alpha: 255, repeat: 0, + expected_colors: expected, + parsed_colors: 0, } } } @@ -127,6 +133,11 @@ impl<'a> Iterator for QoiIterator<'a> { type Item = Rgb565; fn next(&mut self) -> Option { + if self.parsed_colors >= self.expected_colors { + return None; + } + self.parsed_colors += 1; + if self.repeat > 0 { self.repeat -= 1; return Some(self.last_pixel); @@ -137,19 +148,19 @@ impl<'a> Iterator for QoiIterator<'a> { 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(); + // ufmt::uwriteln!(self.serial, "RGBA: {} {} {} {}", red, green, blue, alpha).unwrap(); (Rgb565(*red, *green, *blue), *alpha) } 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(); + // ufmt::uwriteln!(self.serial, "RGB: {} {} {}", red, green, blue).unwrap(); (Rgb565(*red, *green, *blue), self.last_alpha) } else { let tag = (0b11000000 & byte) >> 6; let data = 0b00111111 & byte; - ufmt::uwriteln!(self.serial, "Tag: {}", tag).unwrap(); + // ufmt::uwriteln!(self.serial, "Tag: {}", tag).unwrap(); if tag == 0 { ( @@ -160,14 +171,14 @@ impl<'a> Iterator for QoiIterator<'a> { 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(); + // 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, @@ -183,36 +194,33 @@ impl<'a> Iterator for QoiIterator<'a> { let db_dg = (0b00001111 & second) as i8 - 8; let dr = dr_dg + dg; let db = db_dg + dg; - ufmt::uwriteln!( - self.serial, - "Last: {} {} {}", - self.last_pixel.0 as i8, - self.last_pixel.1 as i8, - self.last_pixel.2 as i8 - ) - .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(); + + 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).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, + (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, ), self.last_alpha, ) } else if tag == 3 { // QOI_OP_RUN 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) } else { (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) % 64) as usize; - ufmt::uwriteln!( - self.serial, - "Color: {} {} {} {}, Hash: {}", - color.0, - color.1, - color.2, - alpha, - hash - ) - .unwrap(); + // ufmt::uwriteln!( + // self.serial, + // "Color: {} {} {} {}, Hash: {}", + // color.0, + // color.1, + // color.2, + // alpha, + // hash + // ) + // .unwrap(); self.prev_pixels[hash] = color; Some(color) } else {