Skip to main content

embedded_png/
colors.rs

1use crate::ParsedPng;
2use crate::types::PixelType;
3use core::marker::PhantomData;
4use embedded_graphics_core::pixelcolor::{BinaryColor, Gray2, Gray4, Gray8, Rgb888};
5use embedded_graphics_core::prelude::PixelColor;
6
7// TODO options for alpha channel
8// Mix with (known background) // replace transparent with known background (and mix properly with alpha)
9// IgnoreAlpha                 // return the color without transparency or alpha
10// DontDraw                    // do not draw transparent pixels (sample alpha channel at 127)
11// Enable                      // return the color containing alpha channel
12/*
13enum AlphaHandling {
14    UseBackground(C),
15    Ignore,
16    Enable,
17}*/
18
19pub trait AlphaHandler<C>: Clone {}
20pub trait ReturnC {}
21
22#[derive(Clone)]
23pub struct IgnoreAlpha;
24impl<C> AlphaHandler<C> for IgnoreAlpha {}
25impl ReturnC for IgnoreAlpha {}
26
27/// Not available yet in embedded-graphics
28#[derive(Clone)]
29pub struct AlphaColor;
30impl<C> AlphaHandler<C> for AlphaColor {}
31impl ReturnC for AlphaColor {}
32
33#[derive(Clone)]
34pub struct WithBackground<C>(C);
35impl<C: PixelColor> AlphaHandler<C> for WithBackground<C> {}
36impl<C> ReturnC for WithBackground<C> {}
37
38#[derive(Clone)]
39pub struct DontDraw;
40impl<C> AlphaHandler<C> for DontDraw {}
41
42pub struct PixelsIterator<'a, Color, Handler> {
43    pixel_type: PixelType<'a>,
44    palette: Option<&'a [u8]>,
45    scanline: &'a [u8],
46    pos: usize,
47    max_pos: usize, // for bit packed pixels
48    handler: Handler,
49    _phantom: PhantomData<Color>,
50}
51
52#[inline]
53// TranspareNT: get alpha value for transparent colors
54fn tnt(reference: u8, value: u8) -> u8 {
55    if reference == value { 0 } else { 255 }
56}
57
58#[inline]
59// TransparentPalette: get alpha value for transparent palette
60fn tpal(palette: &[u8], value: u8) -> u8 {
61    match palette.get(value as usize) {
62        None => 255,
63        Some(v) => *v,
64    }
65}
66
67#[inline]
68// TranspareNTRgb: get alpha value for transparent colors
69fn tntr(reference: &[u8], value: &[u8]) -> u8 {
70    if reference == value { 0 } else { 255 }
71}
72
73impl<'a, Color, Handler: AlphaHandler<Color>> PixelsIterator<'a, Color, Handler> {
74    pub fn new(png: &ParsedPng<'a, Handler>, scanline: &'a [u8]) -> Self {
75        PixelsIterator {
76            pixel_type: png.pixel_type,
77            palette: png.palette,
78            scanline,
79            pos: 0,
80            max_pos: scanline.len(),
81            handler: png.alpha_handler.clone(),
82            _phantom: PhantomData,
83        }
84    }
85
86    #[inline]
87    fn bits<const N: usize>(&mut self) -> u8 {
88        let s = 8 / N;
89        let byte = self.scanline[self.pos / s];
90        let rshift = self.pos % s;
91        let bits = (byte >> ((s - 1 - rshift) * N)) & (0xFF >> (s - 1) * N);
92        self.pos += 1;
93        bits
94    }
95
96    #[inline]
97    fn bytes<const N: usize>(&mut self) -> [u8; N] {
98        let mut res = [0_u8; N];
99        for (i, item) in res.iter_mut().enumerate().take(N) {
100            *item = self.scanline[self.pos + i];
101        }
102        self.pos += N;
103        res
104    }
105
106    #[inline]
107    fn words<const N: usize>(&mut self) -> [u8; N] {
108        // not supported by embedded-graphics, juste take most significant byte
109        // rough approximation of a color rounding
110        let mut res = [0_u8; N];
111        for (i, item) in res.iter_mut().enumerate().take(N) {
112            *item = self.scanline[self.pos + 2 * i]; // big endian
113        }
114        self.pos += 2 * N;
115        res
116    }
117
118    fn next_opaque(&mut self) -> Color
119    where
120        BinaryColor: Into<Color>,
121        Gray2: Into<Color>,
122        Gray4: Into<Color>,
123        Gray8: Into<Color>,
124        Rgb888: Into<Color>,
125    {
126        match self.pixel_type {
127            PixelType::Grayscale1 => {
128                let bit = self.bits::<1>();
129                if bit != 0 {
130                    BinaryColor::On
131                } else {
132                    BinaryColor::Off
133                }
134                .into() //assert_eq!(scanline, &image[i*5120..i*5120 + 5120], "Incorrect image at {}", i);
135            }
136            PixelType::Grayscale2 => {
137                let bits = self.bits::<2>();
138                Gray2::new(bits >> 6).into()
139            }
140            PixelType::Grayscale4 => {
141                let bits = self.bits::<2>();
142                Gray4::new(bits >> 4).into()
143            }
144            PixelType::Grayscale8 => {
145                let byte = self.bytes::<1>();
146                Gray8::new(byte[0]).into()
147            }
148            PixelType::Grayscale16 => {
149                let byte = self.words::<1>();
150                Gray8::new(byte[0]).into()
151            }
152            PixelType::Palette1(palette) => {
153                let bit = self.bits::<1>();
154                get_rgb_from_palette(palette, bit >> 7).into()
155            }
156            PixelType::Palette2(palette) => {
157                let bits = self.bits::<2>();
158                get_rgb_from_palette(palette, bits >> 6).into()
159            }
160            PixelType::Palette4(palette) => {
161                let bits = self.bits::<4>();
162                get_rgb_from_palette(palette, bits >> 4).into()
163            }
164            PixelType::Palette8(palette) => {
165                let byte = self.bytes::<1>();
166                get_rgb_from_palette(palette, byte[0]).into()
167            }
168            PixelType::Rgb8 => {
169                let bytes = self.bytes::<3>();
170                Rgb888::new(bytes[0], bytes[1], bytes[2]).into()
171            }
172            PixelType::Rgb16 => {
173                let bytes = self.words::<3>();
174                Rgb888::new(bytes[0], bytes[1], bytes[2]).into()
175            }
176            _ => unreachable!(),
177        }
178    }
179
180    // TODO, is this better than next_keep_alpha.1
181    fn next_skip_alpha(&mut self) -> Color
182    where
183        BinaryColor: Into<Color>,
184        Gray2: Into<Color>,
185        Gray4: Into<Color>,
186        Gray8: Into<Color>,
187        Rgb888: Into<Color>,
188    {
189        match self.pixel_type {
190            PixelType::Grayscale1Transparent(_) => {
191                let bit = self.bits::<1>();
192                if bit != 0 {
193                    BinaryColor::On
194                } else {
195                    BinaryColor::Off
196                }
197                .into()
198            }
199            PixelType::Grayscale2Transparent(_) => {
200                let bits = self.bits::<2>();
201                Gray2::new(bits >> 6).into()
202            }
203            PixelType::Grayscale4Transparent(_) => {
204                let bits = self.bits::<2>();
205                Gray4::new(bits >> 4).into()
206            }
207            PixelType::Grayscale8Transparent(_) => {
208                let byte = self.bytes::<1>();
209                Gray8::new(byte[0]).into()
210            }
211            PixelType::Grayscale16Transparent(_) => {
212                let byte = self.words::<1>();
213                Gray8::new(byte[0]).into()
214            }
215            PixelType::Palette1Transparent(palette, _) => {
216                let bit = self.bits::<1>();
217                get_rgb_from_palette(palette, bit >> 7).into()
218            }
219            PixelType::Palette2Transparent(palette, _) => {
220                let bits = self.bits::<2>();
221                get_rgb_from_palette(palette, bits >> 6).into()
222            }
223            PixelType::Palette4Transparent(palette, _) => {
224                let bits = self.bits::<4>();
225                get_rgb_from_palette(palette, bits >> 4).into()
226            }
227            PixelType::Palette8Transparent(palette, _) => {
228                let byte = self.bytes::<1>();
229                get_rgb_from_palette(palette, byte[0]).into()
230            }
231            PixelType::Rgb8Transparent(_) => {
232                let bytes = self.bytes::<3>();
233                Rgb888::new(bytes[0], bytes[1], bytes[2]).into()
234            }
235            PixelType::Rgb16Transparent(_) => {
236                let bytes = self.words::<3>();
237                Rgb888::new(bytes[0], bytes[1], bytes[2]).into()
238            }
239            PixelType::GrayscaleAlpha8 => {
240                let bytes = self.bytes::<2>();
241                Gray8::new(bytes[0]).into()
242            }
243            PixelType::GrayscaleAlpha16 => {
244                let byte = self.words::<2>();
245                Gray8::new(byte[0]).into()
246            }
247            PixelType::RgbAlpha8 => {
248                let bytes = self.bytes::<4>();
249                Rgb888::new(bytes[0], bytes[1], bytes[2]).into()
250            }
251            PixelType::RgbAlpha16 => {
252                let bytes = self.words::<4>();
253                Rgb888::new(bytes[0], bytes[1], bytes[2]).into()
254            }
255            _ => self.next_opaque(),
256        }
257    }
258
259    fn next_keep_alpha(&mut self) -> (u8, Color)
260    where
261        BinaryColor: Into<Color>,
262        Gray2: Into<Color>,
263        Gray4: Into<Color>,
264        Gray8: Into<Color>,
265        Rgb888: Into<Color>,
266    {
267        match self.pixel_type {
268            PixelType::Grayscale1Transparent(t) => {
269                let bit = self.bits::<1>();
270                (
271                    tnt(t, bit),
272                    if bit != 0 {
273                        BinaryColor::On
274                    } else {
275                        BinaryColor::Off
276                    }
277                    .into(),
278                )
279            }
280            PixelType::Grayscale2Transparent(t) => {
281                let bits = self.bits::<2>();
282                (tnt(t, bits), Gray2::new(bits >> 6).into())
283            }
284            PixelType::Grayscale4Transparent(t) => {
285                let bits = self.bits::<2>();
286                (tnt(t, bits), Gray4::new(bits >> 4).into())
287            }
288            PixelType::Grayscale8Transparent(t) => {
289                let byte = self.bytes::<1>();
290                (tnt(t, byte[0]), Gray8::new(byte[0]).into())
291            }
292            PixelType::Grayscale16Transparent(t) => {
293                let byte = self.words::<1>();
294                (tnt((t >> 8) as u8, byte[0]), Gray8::new(byte[0]).into())
295            }
296            PixelType::Palette1Transparent(palette, p) => {
297                let bit = self.bits::<1>();
298                (tpal(p, bit), get_rgb_from_palette(palette, bit >> 7).into())
299            }
300            PixelType::Palette2Transparent(palette, p) => {
301                let bits = self.bits::<2>();
302                (
303                    tpal(p, bits),
304                    get_rgb_from_palette(palette, bits >> 6).into(),
305                )
306            }
307            PixelType::Palette4Transparent(palette, p) => {
308                let bits = self.bits::<4>();
309                (
310                    tpal(p, bits),
311                    get_rgb_from_palette(palette, bits >> 4).into(),
312                )
313            }
314            PixelType::Palette8Transparent(palette, p) => {
315                let byte = self.bytes::<1>();
316                (
317                    tpal(p, byte[0]),
318                    get_rgb_from_palette(palette, byte[0]).into(),
319                )
320            }
321            PixelType::Rgb8Transparent(t) => {
322                let bytes = self.bytes::<3>();
323                (
324                    tntr(&t, &bytes),
325                    Rgb888::new(bytes[0], bytes[1], bytes[2]).into(),
326                )
327            }
328            PixelType::Rgb16Transparent(t) => {
329                let bytes = self.words::<3>();
330                (
331                    tntr(&t, &bytes),
332                    Rgb888::new(bytes[0], bytes[1], bytes[2]).into(),
333                )
334            }
335            PixelType::GrayscaleAlpha8 => {
336                let bytes = self.bytes::<2>();
337                (bytes[1], Gray8::new(bytes[0]).into())
338            }
339            PixelType::GrayscaleAlpha16 => {
340                let bytes = self.words::<2>();
341                (bytes[1], Gray8::new(bytes[0]).into())
342            }
343            PixelType::RgbAlpha8 => {
344                let bytes = self.bytes::<4>();
345                (bytes[3], Rgb888::new(bytes[0], bytes[1], bytes[2]).into())
346            }
347            PixelType::RgbAlpha16 => {
348                let bytes = self.words::<4>();
349                (bytes[3], Rgb888::new(bytes[0], bytes[1], bytes[2]).into())
350            }
351            _ => (0xFF, self.next_opaque()),
352        }
353    }
354
355    fn next_alpha_color(&mut self) -> Color
356    where
357        BinaryColor: Into<Color>,
358        Gray2: Into<Color>,
359        Gray4: Into<Color>,
360        Gray8: Into<Color>,
361        Rgb888: Into<Color>,
362        //Argb8888: Into<Color>
363    {
364        match self.pixel_type {
365            PixelType::Grayscale1Transparent(t) => {
366                let bit = self.bits::<1>();
367                todo!()
368            }
369            PixelType::Grayscale2Transparent(t) => {
370                let bits = self.bits::<2>();
371                todo!()
372            }
373            PixelType::Grayscale4Transparent(t) => {
374                let bits = self.bits::<2>();
375                todo!()
376            }
377            PixelType::Grayscale8Transparent(t) => {
378                let byte = self.bytes::<1>();
379                todo!()
380            }
381            PixelType::Grayscale16Transparent(t) => {
382                let byte = self.words::<1>();
383                todo!()
384            }
385            PixelType::Palette1Transparent(palette, p) => {
386                let bit = self.bits::<1>();
387                todo!()
388            }
389            PixelType::Palette2Transparent(palette, p) => {
390                let bits = self.bits::<2>();
391                todo!()
392            }
393            PixelType::Palette4Transparent(palette, p) => {
394                let bits = self.bits::<4>();
395                todo!()
396            }
397            PixelType::Palette8Transparent(palette, p) => {
398                let byte = self.bytes::<1>();
399                todo!()
400            }
401            PixelType::Rgb8Transparent(t) => {
402                let bytes = self.bytes::<3>();
403                //Argb8888::new(bytes[0], bytes[1], bytes[2], tntr(&t, &bytes)).into()
404                todo!()
405            }
406            PixelType::Rgb16Transparent(t) => {
407                let bytes = self.words::<3>();
408                //Argb8888::new(bytes[0], bytes[1], bytes[2], tntr(&t, &bytes)).into()
409                todo!()
410            }
411            PixelType::GrayscaleAlpha8 => {
412                let bytes = self.bytes::<2>();
413                todo!()
414            }
415            PixelType::GrayscaleAlpha16 => {
416                let bytes = self.words::<2>();
417                todo!()
418            }
419            PixelType::RgbAlpha8 => {
420                let bytes = self.bytes::<4>();
421                //Argb8888::new(bytes[0], bytes[1], bytes[2], bytes[3]).into()
422                todo!()
423            }
424            PixelType::RgbAlpha16 => {
425                let bytes = self.words::<4>();
426                //Argb8888::new(bytes[0], bytes[1], bytes[2], bytes[3]).into()
427                todo!()
428            }
429            _ => self.next_opaque(),
430        }
431    }
432}
433
434fn get_rgb_from_palette(palette: &[u8], idx: u8) -> Rgb888 {
435    let idx = (idx as usize) * 3;
436    if idx + 2 >= palette.len() {
437        // this is an error according to PNG reference, but we prefer displaying something
438        Rgb888::new(0, 0, 0)
439    } else {
440        let r = palette[idx];
441        let g = palette[idx + 1];
442        let b = palette[idx + 2];
443        Rgb888::new(r, g, b)
444    }
445}
446
447impl<'a, C> Iterator for PixelsIterator<'a, C, IgnoreAlpha>
448where
449    BinaryColor: Into<C>,
450    Gray2: Into<C>,
451    Gray4: Into<C>,
452    Gray8: Into<C>,
453    Rgb888: Into<C>,
454{
455    type Item = C;
456
457    fn next(&mut self) -> Option<Self::Item> {
458        if self.pos >= self.max_pos {
459            return None;
460        }
461        Some(self.next_skip_alpha())
462    }
463}
464
465impl<'a, C> Iterator for PixelsIterator<'a, C, AlphaColor>
466where
467    BinaryColor: Into<C>,
468    Gray2: Into<C>,
469    Gray4: Into<C>,
470    Gray8: Into<C>,
471    Rgb888: Into<C>,
472    //      Argb8888: Into<C>,
473{
474    type Item = C;
475
476    fn next(&mut self) -> Option<Self::Item> {
477        if self.pos >= self.max_pos {
478            return None;
479        }
480        Some(self.next_alpha_color())
481    }
482}
483
484impl<'a, C> Iterator for PixelsIterator<'a, C, WithBackground<C>>
485where
486    BinaryColor: Into<C>,
487    Gray2: Into<C>,
488    Gray4: Into<C>,
489    Gray8: Into<C>,
490    Rgb888: Into<C>,
491    C: PixelColor,
492{
493    type Item = C;
494
495    fn next(&mut self) -> Option<Self::Item> {
496        if self.pos >= self.max_pos {
497            return None;
498        }
499        let (alpha, color) = self.next_keep_alpha();
500        todo!()
501    }
502}
503
504impl<'a, C> Iterator for PixelsIterator<'a, C, DontDraw>
505where
506    BinaryColor: Into<C>,
507    Gray2: Into<C>,
508    Gray4: Into<C>,
509    Gray8: Into<C>,
510    Rgb888: Into<C>,
511{
512    type Item = (u8, C);
513
514    fn next(&mut self) -> Option<Self::Item> {
515        if self.pos >= self.max_pos {
516            return None;
517        }
518        Some(self.next_keep_alpha())
519    }
520}
521
522#[cfg(test)]
523mod tests {
524    use super::*;
525
526    #[test]
527    fn bits1() {
528        let scanline = [0b1010_1100, 0b1010_1100];
529        let mut it = PixelsIterator {
530            pixel_type: PixelType::Grayscale1,
531            palette: None,
532            scanline: &scanline,
533            pos: 0,
534            max_pos: 0,
535            handler: IgnoreAlpha,
536            _phantom: PhantomData::<Rgb888>,
537        };
538        assert_eq!(it.bits::<1>(), 1);
539        assert_eq!(it.bits::<1>(), 0);
540        assert_eq!(it.bits::<1>(), 1);
541        assert_eq!(it.bits::<1>(), 0);
542        assert_eq!(it.bits::<1>(), 1);
543        assert_eq!(it.bits::<1>(), 1);
544        assert_eq!(it.bits::<1>(), 0);
545        assert_eq!(it.bits::<1>(), 0);
546        assert_eq!(it.bits::<1>(), 1);
547        assert_eq!(it.bits::<1>(), 0);
548    }
549    #[test]
550    fn bits2() {
551        let scanline = [0b1010_1100, 0b1010_1100];
552        let mut it = PixelsIterator {
553            pixel_type: PixelType::Grayscale1,
554            palette: None,
555            scanline: &scanline,
556            pos: 0,
557            max_pos: 0,
558            handler: IgnoreAlpha,
559            _phantom: PhantomData::<Rgb888>,
560        };
561        assert_eq!(it.bits::<2>(), 0b10);
562        assert_eq!(it.bits::<2>(), 0b10);
563        assert_eq!(it.bits::<2>(), 0b11);
564        assert_eq!(it.bits::<2>(), 0b00);
565        assert_eq!(it.bits::<2>(), 0b10);
566        assert_eq!(it.bits::<2>(), 0b10);
567        assert_eq!(it.bits::<2>(), 0b11);
568        assert_eq!(it.bits::<2>(), 0b00);
569    }
570    #[test]
571    fn bits4() {
572        let scanline = [0b1010_1100, 0b1010_1100];
573        let mut it = PixelsIterator {
574            pixel_type: PixelType::Grayscale1,
575            palette: None,
576            scanline: &scanline,
577            pos: 0,
578            max_pos: 0,
579            handler: IgnoreAlpha,
580            _phantom: PhantomData::<Rgb888>,
581        };
582        assert_eq!(it.bits::<4>(), 0b1010);
583        assert_eq!(it.bits::<4>(), 0b1100);
584        assert_eq!(it.bits::<4>(), 0b1010);
585        assert_eq!(it.bits::<4>(), 0b1100);
586    }
587    #[test]
588    fn bytes1() {
589        let scanline = [0xAA, 0xBB, 0xCC, 0xDD];
590        let mut it = PixelsIterator {
591            pixel_type: PixelType::Grayscale1,
592            palette: None,
593            scanline: &scanline,
594            pos: 0,
595            max_pos: 0,
596            handler: IgnoreAlpha,
597            _phantom: PhantomData::<Rgb888>,
598        };
599        assert_eq!(it.bytes::<1>(), [0xAA]);
600        assert_eq!(it.bytes::<1>(), [0xBB]);
601        assert_eq!(it.bytes::<1>(), [0xCC]);
602        assert_eq!(it.bytes::<1>(), [0xDD]);
603    }
604    #[test]
605    fn bytes2() {
606        let scanline = [0xAA, 0xBB, 0xCC, 0xDD];
607        let mut it = PixelsIterator {
608            pixel_type: PixelType::Grayscale1,
609            palette: None,
610            scanline: &scanline,
611            pos: 0,
612            max_pos: 0,
613            handler: IgnoreAlpha,
614            _phantom: PhantomData::<Rgb888>,
615        };
616        assert_eq!(it.bytes::<2>(), [0xAA, 0xBB]);
617        assert_eq!(it.bytes::<2>(), [0xCC, 0xDD]);
618    }
619}