launchkey_sdk/launchkey/
bitmap.rs1use image::DynamicImage;
2
3const DISPLAY_WIDTH: u32 = 128;
5
6const DISPLAY_HEIGHT: u32 = 64;
8
9const BITMAP_SIZE: usize = 1216;
11
12const BYTES_PER_ROW: u32 = 19;
14
15#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct LaunchkeyBitmap([u8; BITMAP_SIZE]);
18
19impl LaunchkeyBitmap {
20 pub fn new(data: [u8; BITMAP_SIZE]) -> Self {
22 Self(data)
23 }
24
25 pub fn from_image(img: DynamicImage, threshold: u8) -> Self {
27 let img = img.resize_exact(DISPLAY_WIDTH, DISPLAY_HEIGHT, image::imageops::Nearest);
28 let img = img.to_luma8();
29
30 let mut data = [0u8; BITMAP_SIZE];
31
32 for y in 0..DISPLAY_HEIGHT {
33 for x in 0..DISPLAY_WIDTH {
34 let pixel = img.get_pixel(x, y)[0];
35 if pixel > threshold {
36 let byte_index = ((y * BYTES_PER_ROW) + (x / 7)) as usize;
37 let bit_offset = 6 - (x % 7); data[byte_index] |= 1 << bit_offset;
39 }
40 }
41 }
42
43 Self(data)
44 }
45}
46
47impl TryFrom<&[u8]> for LaunchkeyBitmap {
48 type Error = String;
49
50 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
51 if value.len() != BITMAP_SIZE {
52 Err(format!("Invalid length: {} (must be {})", value.len(), BITMAP_SIZE))
53 } else {
54 let mut buffer = [0u8; BITMAP_SIZE];
55 buffer.copy_from_slice(value);
56 Ok(Self(buffer))
57 }
58 }
59}
60
61impl From<LaunchkeyBitmap> for [u8; BITMAP_SIZE] {
62 fn from(val: LaunchkeyBitmap) -> Self {
63 val.0
64 }
65}
66
67impl AsRef<[u8; BITMAP_SIZE]> for LaunchkeyBitmap {
68 fn as_ref(&self) -> &[u8; BITMAP_SIZE] {
69 &self.0
70 }
71}