use crate::pixelcolor::PixelColor;
const RED_MASK: u16 = 0b11111_000000_00000;
const GREEN_MASK: u16 = 0b00000_111111_00000;
const BLUE_MASK: u16 = 0b00000_000000_11111;
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Rgb565(pub u16);
impl Rgb565 {
pub fn r(&self) -> u8 {
((self.0 & RED_MASK) >> 8) as u8
}
pub fn g(&self) -> u8 {
((self.0 & GREEN_MASK) >> 3) as u8
}
pub fn b(&self) -> u8 {
((self.0 & BLUE_MASK) << 3) as u8
}
}
impl PixelColor for Rgb565 {}
impl From<u8> for Rgb565 {
fn from(other: u8) -> Self {
Self::from((other, other, other))
}
}
impl From<u16> for Rgb565 {
fn from(other: u16) -> Self {
Self(other)
}
}
impl From<(u8, u8, u8)> for Rgb565 {
fn from((r, g, b): (u8, u8, u8)) -> Self {
let value =
(((r as u16) << 8) & RED_MASK)
| (((g as u16) << 3) & GREEN_MASK)
| ((b as u16) >> 3 & BLUE_MASK);
Self(value)
}
}
impl From<[u8; 2]> for Rgb565 {
fn from(other: [u8; 2]) -> Self {
Self(u16::from_be_bytes(other))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_u8() {
assert_eq!(Rgb565::from(0u8), Rgb565(0));
assert_eq!(Rgb565::from(0xffu8), Rgb565(0xffff));
assert_eq!(Rgb565::from(0b0000_1111u8), Rgb565(0b00001_000011_00001));
assert_eq!(Rgb565::from(0b1010_1010u8), Rgb565(0b10101_101010_10101));
}
#[test]
fn from_u16() {
assert_eq!(Rgb565::from(0xffu16), Rgb565(0x00ff));
assert_eq!(Rgb565::from(0xffffu16), Rgb565(0xffff));
assert_eq!(Rgb565::from(0xababu16), Rgb565(0xabab));
}
#[test]
fn from_tuple() {
assert_eq!(Rgb565::from((0xff, 0xff, 0xff)), Rgb565(0xffff));
assert_eq!(
Rgb565::from((0xff, 0x0f, 0b0101_0101)),
Rgb565(0b11111_000011_01010)
);
}
#[test]
fn from_be_bytes() {
assert_eq!(Rgb565::from([0xff, 0x00]), Rgb565(0xff00));
assert_eq!(Rgb565::from([0xab, 0xcd]), Rgb565(0xabcd));
}
#[test]
fn accessors() {
let p = Rgb565(0b11001_010101_10010);
assert_eq!(p.r(), 0b11001_000);
assert_eq!(p.g(), 0b010101_00);
assert_eq!(p.b(), 0b10010_000);
}
}