launchkey_sdk/launchkey/
bitmap.rs

1use image::DynamicImage;
2
3/// Represents a 128x64 monochrome bitmap for Launchkey MK4 displays
4#[derive(Debug, Clone, PartialEq, Eq)]
5pub struct LaunchkeyBitmap([u8; 1216]);
6
7impl LaunchkeyBitmap {
8    /// Creates a new bitmap from a 1216-byte array, where each byte encodes pixels in a specific format.
9    pub fn new(data: [u8; 1216]) -> Self {
10        Self(data)
11    }
12
13    /// Converts a full image to a Launchkey-compatible 128x64 monochrome bitmap using a brightness threshold.
14    pub fn from_image(img: DynamicImage, threshold: u8) -> Result<Self, String> {
15        const DISPLAY_WIDTH: u32 = 128;
16        const DISPLAY_HEIGHT: u32 = 64;
17        const BYTES_PER_ROW: u32 = 19;
18
19        let img = img.resize_exact(DISPLAY_WIDTH, DISPLAY_HEIGHT, image::imageops::Nearest);
20        let img = img.to_luma8();
21
22        let mut data = [0u8; 1216];
23
24        for y in 0..DISPLAY_HEIGHT {
25            for x in 0..DISPLAY_WIDTH {
26                let pixel = img.get_pixel(x, y)[0];
27                if pixel > threshold {
28                    let byte_index = ((y * BYTES_PER_ROW) + (x / 7)) as usize;
29                    let bit_offset = 6 - (x % 7); // Leftmost pixel = highest bit (bit 7)
30                    data[byte_index] |= 1 << bit_offset;
31                }
32            }
33        }
34
35        Ok(Self(data))
36    }
37}
38
39impl TryFrom<&[u8]> for LaunchkeyBitmap {
40    type Error = String;
41
42    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
43        if value.len() != 1216 {
44            Err(format!("Invalid length: {} (must be 1216)", value.len()))
45        } else {
46            let mut buffer = [0u8; 1216];
47            buffer.copy_from_slice(value);
48            Ok(Self(buffer))
49        }
50    }
51}
52
53impl From<LaunchkeyBitmap> for [u8; 1216] {
54    fn from(val: LaunchkeyBitmap) -> Self {
55        val.0
56    }
57}
58
59impl AsRef<[u8; 1216]> for LaunchkeyBitmap {
60    fn as_ref(&self) -> &[u8; 1216] {
61        &self.0
62    }
63}