embedded_png/
colors.rs

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