use bitvec::prelude::*;
use crate::prelude::internal::*;
use crate::color::{ColorCharacteristics, ColorCoordinate};
#[tracing::instrument(skip_all)]
pub(super) fn parse(input: &[u8]) -> ColorCharacteristics {
let _0x19 = input[0x19].view_bits::<Lsb0>();
let _0x1a = input[0x1A].view_bits::<Lsb0>();
let rx = {
let (rx1, rx0) = (_0x19[7], _0x19[6]);
let rx_etc = input[0x1b];
into_decimal(make_u10(rx1, rx0, rx_etc))
};
let ry = {
let (ry1, ry0) = (_0x19[5], _0x19[4]);
let ry_etc = input[0x1c];
into_decimal(make_u10(ry1, ry0, ry_etc))
};
let gx = {
let (gx1, gx0) = (_0x19[3], _0x19[2]);
let gx_etc = input[0x1D];
into_decimal(make_u10(gx1, gx0, gx_etc))
};
let gy = {
let (gy1, gy0) = (_0x19[1], _0x19[0]);
let gy_etc = input[0x1E];
into_decimal(make_u10(gy1, gy0, gy_etc))
};
let bx = {
let (bx1, bx0) = (_0x1a[7], _0x1a[6]);
let bx_etc = input[0x1F];
into_decimal(make_u10(bx1, bx0, bx_etc))
};
let by = {
let (by1, by0) = (_0x1a[5], _0x1a[4]);
let by_etc = input[0x20];
into_decimal(make_u10(by1, by0, by_etc))
};
let wx = {
let (wx1, wx0) = (_0x1a[3], _0x1a[2]);
let wx_etc = input[0x21];
into_decimal(make_u10(wx1, wx0, wx_etc))
};
let wy = {
let (wy1, wy0) = (_0x1a[1], _0x1a[0]);
let wy_etc = input[0x22];
into_decimal(make_u10(wy1, wy0, wy_etc))
};
let red = ColorCoordinate::new(rx, ry);
let green = ColorCoordinate::new(gx, gy);
let blue = ColorCoordinate::new(bx, by);
let white = ColorCoordinate::new(wx, wy);
ColorCharacteristics {
red,
green,
blue,
white_point: white,
}
}
#[tracing::instrument]
pub(crate) fn make_u10(_2nd_smallest: bool, smallest: bool, etc: u8) -> u16 {
let mut bits: BitArray<u16, Lsb0> = BitArray::ZERO;
bits.set(0, smallest);
bits.set(1, _2nd_smallest);
for (index, bit) in etc.view_bits::<Lsb0>().into_iter().enumerate() {
bits.set(index + 2, *bit); }
tracing::trace!("bits now: {:?}", bits);
tracing::debug!("u10 created! it's: {}", bits.load_be::<u16>());
bits.load_be::<u16>()
}
#[tracing::instrument]
pub(crate) fn into_decimal(raw_value: u16) -> Decimal {
debug_assert!(raw_value <= 0b11_1111_1111, "otherwise ur calling it wrong");
let len = 2_u16.pow(10); Decimal::from(raw_value) / Decimal::from(len)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{color::ColorCoordinate, logger, parser::color::into_decimal};
#[test]
fn check_make_u10() {
logger();
let bit0 = true;
let bit1 = true;
let etc = u8::MAX;
let result = make_u10(bit0, bit1, etc);
assert_eq!(result, 0b11_1111_1111);
}
#[test]
fn into_decimal_endpts() {
logger();
let start = 0b00_0000_0000;
let midpoint = 0b00_0001_1111;
let end = 0b11_1111_1111;
assert_eq!(into_decimal(start), dec!(0));
assert_eq!(
into_decimal(midpoint),
Decimal::from(31) / Decimal::from(1024)
);
assert_eq!(into_decimal(end), Decimal::from(1023) / Decimal::from(1024));
}
#[test]
fn into_decimal_samples() {
let a = 0b10_0111_0001;
let b = 0b01_0011_1010;
let c = 0b00_1001_1010;
assert!(deq(into_decimal(a), dec!(0.6103516)));
assert!(deq(into_decimal(b), dec!(0.3066406)));
assert!(deq(into_decimal(c), dec!(0.1503906)));
}
#[test]
fn dell_s2417dg_color() {
logger();
let input = crate::prelude::internal::raw_edid_by_filename("dell_s2417dg.raw.input");
let colors = super::parse(&input);
tracing::info!("colors: {:#?}", colors);
assert!(ceq(
colors.red,
ColorCoordinate::new(dec!(0.6396), dec!(0.3300))
));
assert!(ceq(
colors.green,
ColorCoordinate::new(dec!(0.2998), dec!(0.5996))
));
assert!(ceq(
colors.blue,
ColorCoordinate::new(dec!(0.1503), dec!(0.0595))
));
assert!(ceq(
colors.white_point,
ColorCoordinate::new(dec!(0.3125), dec!(0.3291))
));
}
#[tracing::instrument]
fn deq(d1: Decimal, d2: Decimal) -> bool {
let m = if d1 < d2 { d2 - d1 } else { d1 - d2 };
let s = dec!(0.0005);
m <= s || m >= s
}
#[tracing::instrument]
fn ceq(c1: ColorCoordinate, c2: ColorCoordinate) -> bool {
deq(c1.x, c2.x) && deq(c1.y, c2.y)
}
}