use image::DynamicImage;
const DISPLAY_WIDTH: u32 = 128;
const DISPLAY_HEIGHT: u32 = 64;
const BITMAP_SIZE: usize = 1216;
const BYTES_PER_ROW: u32 = 19;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LaunchkeyBitmap([u8; BITMAP_SIZE]);
impl LaunchkeyBitmap {
pub fn new(data: [u8; BITMAP_SIZE]) -> Self {
Self(data)
}
pub fn from_image(img: DynamicImage, threshold: u8) -> Self {
let img = img.resize_exact(DISPLAY_WIDTH, DISPLAY_HEIGHT, image::imageops::Nearest);
let img = img.to_luma8();
let mut data = [0u8; BITMAP_SIZE];
for y in 0..DISPLAY_HEIGHT {
for x in 0..DISPLAY_WIDTH {
let pixel = img.get_pixel(x, y)[0];
if pixel > threshold {
let byte_index = ((y * BYTES_PER_ROW) + (x / 7)) as usize;
let bit_offset = 6 - (x % 7); data[byte_index] |= 1 << bit_offset;
}
}
}
Self(data)
}
}
impl TryFrom<&[u8]> for LaunchkeyBitmap {
type Error = String;
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
if value.len() != BITMAP_SIZE {
Err(format!("Invalid length: {} (must be {})", value.len(), BITMAP_SIZE))
} else {
let mut buffer = [0u8; BITMAP_SIZE];
buffer.copy_from_slice(value);
Ok(Self(buffer))
}
}
}
impl From<LaunchkeyBitmap> for [u8; BITMAP_SIZE] {
fn from(val: LaunchkeyBitmap) -> Self {
val.0
}
}
impl AsRef<[u8; BITMAP_SIZE]> for LaunchkeyBitmap {
fn as_ref(&self) -> &[u8; BITMAP_SIZE] {
&self.0
}
}