1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
//! Static 5×5 greyscale and black-and-white images.

use tiny_led_matrix::{Render, MAX_BRIGHTNESS};

/// A 5×5 image supporting the full range of brightnesses for each LED.
///
/// Uses 25 bytes of storage.
#[derive(Copy, Clone, Debug)]
pub struct GreyscaleImage (
    [[u8; 5]; 5]
);


impl GreyscaleImage {

    /// Constructs a GreyscaleImage from an array of brightnesses.
    ///
    /// The data should be an array of 5 rows (top first), each of which is an
    /// array of 5 brightness values (left first).
    ///
    /// # Example
    ///
    /// ```
    /// const GREY_HEART: GreyscaleImage = GreyscaleImage::new(&[
    ///     [0, 9, 0, 9, 0],
    ///     [9, 5, 9, 5, 9],
    ///     [9, 5, 5, 5, 9],
    ///     [0, 9, 5, 9, 0],
    ///     [0, 0, 9, 0, 0],
    /// ]);
    /// ```
    pub const fn new(data: &[[u8; 5]; 5]) -> GreyscaleImage {
        GreyscaleImage(*data)
    }

    pub const fn blank() -> GreyscaleImage {
        GreyscaleImage([[0; 5]; 5])
    }

}

impl Render for GreyscaleImage {

    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        self.0[y][x]
    }
}

impl Render for &GreyscaleImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        GreyscaleImage::brightness_at(self, x, y)
    }
}


/// A 5×5 image supporting only two levels of brightness (on and off).
///
/// Uses 5 bytes of storage.
///
/// For display, each pixel is treated as having brightness either 0 or
/// MAX_BRIGHTNESS.
#[derive(Copy, Clone, Debug)]
pub struct BitImage (
    [u8; 5]
);

impl BitImage {

    /// Constructs a BitImage from an array of brightnesses.
    ///
    /// The data should be an array of 5 rows (top first), each of which is an
    /// array of 5 values (left first). Each value should be either 0 or 1.
    ///
    /// # Example
    ///
    /// ```
    /// const HEART: BitImage = BitImage::new(&[
    ///     [0, 1, 0, 1, 0],
    ///     [1, 0, 1, 0, 1],
    ///     [1, 0, 0, 0, 1],
    ///     [0, 1, 0, 1, 0],
    ///     [0, 0, 1, 0, 0],
    /// ]);
    /// ```
    pub const fn new(im: &[[u8; 5]; 5]) -> BitImage {
        // FIXME: can we reject values other than 0 or 1?
        const fn row_byte(row: [u8; 5]) -> u8 {
            row[0] | row[1]<<1 | row[2]<<2 | row[3]<<3 | row[4]<<4
        };
        BitImage([
            row_byte(im[0]),
            row_byte(im[1]),
            row_byte(im[2]),
            row_byte(im[3]),
            row_byte(im[4]),
        ])
    }

    /// Returns a new blank BitImage.
    ///
    /// All pixel values are 0.
    pub const fn blank() -> BitImage {
        BitImage([0; 5])
    }

}

impl Render for BitImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        let rowdata = self.0[y];
        if rowdata & (1<<x) != 0 {MAX_BRIGHTNESS as u8} else {0}
    }
}

impl Render for &BitImage {
    fn brightness_at(&self, x: usize, y: usize) -> u8 {
        BitImage::brightness_at(self, x, y)
    }
}