use super::*;
fn as_le_u16(intended: &[u16]) -> std::vec::Vec<u16> {
let bytes: std::vec::Vec<u8> = intended.iter().flat_map(|v| v.to_le_bytes()).collect();
bytes
.chunks_exact(2)
.map(|b| u16::from_ne_bytes([b[0], b[1]]))
.collect()
}
fn as_be_u16(intended: &[u16]) -> std::vec::Vec<u16> {
let bytes: std::vec::Vec<u8> = intended.iter().flat_map(|v| v.to_be_bytes()).collect();
bytes
.chunks_exact(2)
.map(|b| u16::from_ne_bytes([b[0], b[1]]))
.collect()
}
#[test]
fn gray8_to_rgb_broadcasts() {
let y = [0u8, 128, 255];
let mut out = [0u8; 9];
gray8_to_rgb_row(&y, &mut out, 3, true);
assert_eq!(&out[0..3], &[0, 0, 0]);
assert_eq!(&out[3..6], &[128, 128, 128]);
assert_eq!(&out[6..9], &[255, 255, 255]);
}
#[test]
fn gray8_to_rgba_broadcasts_opaque() {
let y = [100u8, 200];
let mut out = [0u8; 8];
gray8_to_rgba_row(&y, &mut out, 2, true);
assert_eq!(&out[0..4], &[100, 100, 100, 0xFF]);
assert_eq!(&out[4..8], &[200, 200, 200, 0xFF]);
}
#[test]
fn gray8_to_hsv_h0_s0_v_y() {
let y = [0u8, 128, 255];
let mut h = [0xFFu8; 3];
let mut s = [0xFFu8; 3];
let mut v = [0u8; 3];
gray8_to_hsv_row(&y, &mut h, &mut s, &mut v, 3, true);
assert_eq!(h, [0, 0, 0]);
assert_eq!(s, [0, 0, 0]);
assert_eq!(v, [0, 128, 255]);
}
#[test]
fn gray8_limited_range_black() {
let y = [16u8];
let mut out = [0u8; 3];
gray8_to_rgb_row(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray8_limited_range_white() {
let y = [235u8];
let mut out = [0u8; 3];
gray8_to_rgb_row(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[255, 255, 255]);
}
#[test]
fn gray8_limited_range_midpoint() {
let y = [125u8]; let mut out = [0u8; 3];
gray8_to_rgb_row(&y, &mut out, 1, false);
assert!(
out[0] >= 126 && out[0] <= 128,
"expected ~127 got {}",
out[0]
);
assert_eq!(out[0], out[1]);
assert_eq!(out[0], out[2]);
}
#[test]
fn gray8_limited_range_rgba() {
let y = [16u8, 235];
let mut out = [0u8; 8];
gray8_to_rgba_row(&y, &mut out, 2, false);
assert_eq!(&out[0..4], &[0, 0, 0, 0xFF]);
assert_eq!(&out[4..8], &[255, 255, 255, 0xFF]);
}
#[test]
fn gray8_limited_range_hsv() {
let y = [16u8, 235];
let mut h = [0xFFu8; 2];
let mut s = [0xFFu8; 2];
let mut v = [0u8; 2];
gray8_to_hsv_row(&y, &mut h, &mut s, &mut v, 2, false);
assert_eq!(h, [0, 0]);
assert_eq!(s, [0, 0]);
assert_eq!(v, [0, 255]);
}
#[test]
fn gray10_limited_range_black() {
let y = as_le_u16(&[64u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<10, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray10_limited_range_white() {
let y = as_le_u16(&[940u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<10, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[255, 255, 255]);
}
#[test]
fn gray10_limited_range_midpoint() {
let y = as_le_u16(&[500u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<10, false>(&y, &mut out, 1, false);
assert!(
out[0] >= 126 && out[0] <= 128,
"expected ~127 got {}",
out[0]
);
}
#[test]
fn gray10_full_range_pass_through() {
let y = as_le_u16(&[512u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<10, false>(&y, &mut out, 1, true);
assert_eq!(&out[0..3], &[128, 128, 128]);
}
#[test]
fn gray12_limited_range_black() {
let y = as_le_u16(&[256u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<12, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray12_limited_range_white() {
let y = as_le_u16(&[3760u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<12, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[255, 255, 255]);
}
#[test]
fn gray14_limited_range_black() {
let y = as_le_u16(&[1024u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<14, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray14_limited_range_white() {
let y = as_le_u16(&[15040u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<14, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[255, 255, 255]);
}
#[test]
fn gray16_limited_range_black() {
let y = as_le_u16(&[4096u16]);
let mut out = std::vec![0u8; 3];
gray16_to_rgb_row::<false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray16_limited_range_white() {
let y = as_le_u16(&[60160u16]);
let mut out = std::vec![0u8; 3];
gray16_to_rgb_row::<false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[255, 255, 255]);
}
#[test]
fn gray16_limited_range_midpoint() {
let y = as_le_u16(&[32000u16]);
let mut out = std::vec![0u8; 3];
gray16_to_rgb_row::<false>(&y, &mut out, 1, false);
assert!(
out[0] >= 126 && out[0] <= 128,
"expected ~127 got {}",
out[0]
);
}
#[test]
fn gray16_full_range_pass_through() {
let y = as_le_u16(&[0x8000u16]);
let mut out = std::vec![0u8; 3];
gray16_to_rgb_row::<false>(&y, &mut out, 1, true);
assert_eq!(&out[0..3], &[128, 128, 128]);
}
#[test]
fn gray16_to_rgb_u16_limited_range_black() {
let y = as_le_u16(&[4096u16]); let mut out = std::vec![0u16; 3];
gray16_to_rgb_u16_row::<false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray16_to_rgb_u16_limited_range_white() {
let y = as_le_u16(&[60160u16]); let mut out = std::vec![0u16; 3];
gray16_to_rgb_u16_row::<false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[65535, 65535, 65535]);
}
#[test]
fn gray16_to_rgb_u16_limited_range_over_white_clamps() {
let y = as_le_u16(&[65535u16]);
let mut out = std::vec![0u16; 3];
gray16_to_rgb_u16_row::<false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[65535, 65535, 65535]);
}
#[test]
fn gray16_to_rgba_u16_limited_range_black_and_white() {
let y = as_le_u16(&[4096u16, 60160u16]);
let mut out = std::vec![0u16; 8];
gray16_to_rgba_u16_row::<false>(&y, &mut out, 2, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
assert_eq!(out[3], 0xFFFF);
assert_eq!(&out[4..7], &[65535, 65535, 65535]);
assert_eq!(out[7], 0xFFFF);
}
#[test]
fn gray_n_to_rgb_10bit_downshifts() {
let y = as_le_u16(&[0, 512, 1023]);
let mut out = std::vec![0u8; 9];
gray_n_to_rgb_row::<10, false>(&y, &mut out, 3, true);
assert_eq!(&out[0..3], &[0, 0, 0]);
assert_eq!(&out[3..6], &[128, 128, 128]);
assert_eq!(&out[6..9], &[255, 255, 255]);
}
#[test]
fn gray_n_to_rgb_u16_10bit_masks() {
let y = as_le_u16(&[0xFFFF, 512, 0]);
let mut out = std::vec![0u16; 9];
gray_n_to_rgb_u16_row::<10, false>(&y, &mut out, 3, true);
assert_eq!(&out[0..3], &[1023, 1023, 1023]);
assert_eq!(&out[3..6], &[512, 512, 512]);
assert_eq!(&out[6..9], &[0, 0, 0]);
}
#[test]
fn gray_n_to_hsv_h0_s0() {
let y = as_le_u16(&[512u16]); let mut h = std::vec![0xFFu8; 1];
let mut s = std::vec![0xFFu8; 1];
let mut v = std::vec![0u8; 1];
gray_n_to_hsv_row::<10, false>(&y, &mut h, &mut s, &mut v, 1, true);
assert_eq!(h[0], 0);
assert_eq!(s[0], 0);
assert_eq!(v[0], 128);
}
#[test]
fn gray16_to_rgb_downshifts_8() {
let y = as_le_u16(&[0, 0x8000, 0xFFFF]);
let mut out = std::vec![0u8; 9];
gray16_to_rgb_row::<false>(&y, &mut out, 3, true);
assert_eq!(&out[0..3], &[0, 0, 0]);
assert_eq!(&out[3..6], &[0x80, 0x80, 0x80]);
assert_eq!(&out[6..9], &[0xFF, 0xFF, 0xFF]);
}
#[test]
fn gray16_to_luma_u16_identity() {
let y = as_le_u16(&[0, 1000, 65535]);
let mut out = std::vec![0u16; 3];
gray16_to_luma_u16_row::<false>(&y, &mut out, 3);
assert_eq!(out.as_slice(), &[0, 1000, 65535]);
}
#[test]
fn gray16_to_rgba_u16_opaque() {
let y = as_le_u16(&[12345u16]);
let mut out = std::vec![0u16; 4];
gray16_to_rgba_u16_row::<false>(&y, &mut out, 1, true);
assert_eq!(&out[0..4], &[12345, 12345, 12345, 0xFFFF]);
}
#[test]
fn gray_n_to_luma_u16_10bit_masks() {
let y: std::vec::Vec<u16> = std::vec![0xFFFF]; let mut out = std::vec![0u16; 1];
gray_n_to_luma_u16_row::<10, false>(&y, &mut out, 1);
assert_eq!(out[0], 1023);
}
#[test]
fn gray9_limited_range_black() {
let y = as_le_u16(&[32u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<9, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[0, 0, 0]);
}
#[test]
fn gray9_limited_range_white() {
let y = as_le_u16(&[470u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<9, false>(&y, &mut out, 1, false);
assert_eq!(&out[0..3], &[255, 255, 255]);
}
#[test]
fn gray9_full_range_pass_through() {
let y = as_le_u16(&[256u16]);
let mut out = std::vec![0u8; 3];
gray_n_to_rgb_row::<9, false>(&y, &mut out, 1, true);
assert_eq!(&out[0..3], &[128, 128, 128]);
}
#[test]
fn gray10_be_parity_rgb() {
let intended: std::vec::Vec<u16> = std::vec![512u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u8; 3];
let mut out_be = std::vec![0u8; 3];
gray_n_to_rgb_row::<10, false>(&le_in, &mut out_le, 1, true);
gray_n_to_rgb_row::<10, true>(&be_in, &mut out_be, 1, true);
assert_eq!(out_le, out_be, "BE and LE gray10 rgb outputs must match");
assert_eq!(&out_le[..], &[128, 128, 128]);
}
#[test]
fn gray10_be_parity_rgba() {
let intended: std::vec::Vec<u16> = std::vec![768u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u8; 4];
let mut out_be = std::vec![0u8; 4];
gray_n_to_rgba_row::<10, false>(&le_in, &mut out_le, 1, true);
gray_n_to_rgba_row::<10, true>(&be_in, &mut out_be, 1, true);
assert_eq!(out_le, out_be, "BE and LE gray10 rgba outputs must match");
assert_eq!(&out_le[..], &[192, 192, 192, 0xFF]);
}
#[test]
fn gray10_be_parity_luma() {
let intended: std::vec::Vec<u16> = std::vec![256u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u8; 1];
let mut out_be = std::vec![0u8; 1];
gray_n_to_luma_row::<10, false>(&le_in, &mut out_le, 1);
gray_n_to_luma_row::<10, true>(&be_in, &mut out_be, 1);
assert_eq!(out_le, out_be, "BE and LE gray10 luma outputs must match");
assert_eq!(out_le[0], 64);
}
#[test]
fn gray10_be_parity_luma_u16() {
let intended: std::vec::Vec<u16> = std::vec![512u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u16; 1];
let mut out_be = std::vec![0u16; 1];
gray_n_to_luma_u16_row::<10, false>(&le_in, &mut out_le, 1);
gray_n_to_luma_u16_row::<10, true>(&be_in, &mut out_be, 1);
assert_eq!(
out_le, out_be,
"BE and LE gray10 luma_u16 outputs must match"
);
assert_eq!(out_le[0], 512);
}
#[test]
fn gray16_be_parity_rgb() {
let intended: std::vec::Vec<u16> = std::vec![0x8000u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u8; 3];
let mut out_be = std::vec![0u8; 3];
gray16_to_rgb_row::<false>(&le_in, &mut out_le, 1, true);
gray16_to_rgb_row::<true>(&be_in, &mut out_be, 1, true);
assert_eq!(out_le, out_be, "BE and LE gray16 rgb outputs must match");
assert_eq!(&out_le[..], &[128, 128, 128]);
}
#[test]
fn gray16_be_parity_rgba() {
let intended: std::vec::Vec<u16> = std::vec![0xC000u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u8; 4];
let mut out_be = std::vec![0u8; 4];
gray16_to_rgba_row::<false>(&le_in, &mut out_le, 1, true);
gray16_to_rgba_row::<true>(&be_in, &mut out_be, 1, true);
assert_eq!(out_le, out_be, "BE and LE gray16 rgba outputs must match");
assert_eq!(&out_le[..], &[192, 192, 192, 0xFF]);
}
#[test]
fn gray16_be_parity_luma() {
let intended: std::vec::Vec<u16> = std::vec![0x4000u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u8; 1];
let mut out_be = std::vec![0u8; 1];
gray16_to_luma_row::<false>(&le_in, &mut out_le, 1);
gray16_to_luma_row::<true>(&be_in, &mut out_be, 1);
assert_eq!(out_le, out_be, "BE and LE gray16 luma outputs must match");
assert_eq!(out_le[0], 64);
}
#[test]
fn gray16_be_parity_luma_u16() {
let intended: std::vec::Vec<u16> = std::vec![0x1234u16];
let le_in = as_le_u16(&intended);
let be_in = as_be_u16(&intended);
let mut out_le = std::vec![0u16; 1];
let mut out_be = std::vec![0u16; 1];
gray16_to_luma_u16_row::<false>(&le_in, &mut out_le, 1);
gray16_to_luma_u16_row::<true>(&be_in, &mut out_be, 1);
assert_eq!(
out_le, out_be,
"BE and LE gray16 luma_u16 outputs must match"
);
assert_eq!(out_le[0], 0x1234);
}