use super::*;
use crate::ColorMatrix;
fn as_le_u16(host: &[u16]) -> std::vec::Vec<u16> {
host
.iter()
.map(|v| u16::from_ne_bytes(v.to_le_bytes()))
.collect()
}
#[test]
fn rgb_high_bit_bits10_channel_reorder() {
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[100u16; 1]);
let r = as_le_u16(&[1000u16; 1]);
let mut out = [0u8; 3];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], 250); assert_eq!(out[1], 0); assert_eq!(out[2], 25); }
#[test]
fn rgb_high_bit_bits10_max_value_becomes_0xff() {
let max = (1u16 << 10) - 1; let g = as_le_u16(&[max; 4]);
let b = as_le_u16(&[max; 4]);
let r = as_le_u16(&[max; 4]);
let mut out = [0u8; 12];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, 4);
assert!(out.iter().all(|&v| v == 0xFF), "all pixels must be 0xFF");
}
#[test]
fn rgb_high_bit_bits16_max_value_becomes_0xff() {
let max = u16::MAX;
let g = as_le_u16(&[max; 2]);
let b = as_le_u16(&[max; 2]);
let r = as_le_u16(&[max; 2]);
let mut out = [0u8; 6];
gbr_to_rgb_high_bit_row::<16, false>(&g, &b, &r, &mut out, 2);
assert!(out.iter().all(|&v| v == 0xFF));
}
#[test]
fn rgb_high_bit_bits10_zero_becomes_zero() {
let g = as_le_u16(&[0u16; 2]);
let b = as_le_u16(&[0u16; 2]);
let r = as_le_u16(&[0u16; 2]);
let mut out = [0xFFu8; 6];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, 2);
assert!(out.iter().all(|&v| v == 0));
}
#[test]
fn rgb_high_bit_bits9_downshift_by_1() {
let g = as_le_u16(&[510u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[0u16; 1]);
let mut out = [0u8; 3];
gbr_to_rgb_high_bit_row::<9, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[1], 255); }
#[test]
fn rgb_high_bit_bits12_downshift_by_4() {
let r = as_le_u16(&[4080u16; 1]);
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let mut out = [0u8; 3];
gbr_to_rgb_high_bit_row::<12, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], 255); }
#[test]
fn rgb_high_bit_multiple_pixels_correct_layout() {
let r = as_le_u16(&[400u16, 200u16, 0u16]);
let g = as_le_u16(&[800u16, 0u16, 600u16]);
let b = as_le_u16(&[300u16, 0u16, 200u16]);
let mut out = [0u8; 9];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, 3);
assert_eq!(out[0], 100);
assert_eq!(out[1], 200);
assert_eq!(out[2], 75);
assert_eq!(out[3], 50);
assert_eq!(out[4], 0);
assert_eq!(out[5], 0);
assert_eq!(out[6], 0);
assert_eq!(out[7], 150);
assert_eq!(out[8], 50);
}
#[test]
fn rgb_u16_high_bit_channel_reorder() {
let g = as_le_u16(&[111u16; 1]);
let b = as_le_u16(&[222u16; 1]);
let r = as_le_u16(&[333u16; 1]);
let mut out = [0u16; 3];
gbr_to_rgb_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], 333); assert_eq!(out[1], 111); assert_eq!(out[2], 222); }
#[test]
fn rgb_u16_high_bit_bits10_max_preserved() {
let max = (1u16 << 10) - 1; let g = as_le_u16(&[max; 4]);
let b = as_le_u16(&[max; 4]);
let r = as_le_u16(&[max; 4]);
let mut out = [0u16; 12];
gbr_to_rgb_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 4);
assert!(out.iter().all(|&v| v == max));
}
#[test]
fn rgb_u16_high_bit_bits16_max_preserved() {
let max = u16::MAX;
let g = as_le_u16(&[max; 2]);
let b = as_le_u16(&[max; 2]);
let r = as_le_u16(&[max; 2]);
let mut out = [0u16; 6];
gbr_to_rgb_u16_high_bit_row::<16, false>(&g, &b, &r, &mut out, 2);
assert!(out.iter().all(|&v| v == max));
}
#[test]
fn rgb_u16_high_bit_values_not_shifted() {
let g = as_le_u16(&[1000u16; 1]);
let b = as_le_u16(&[2000u16; 1]);
let r = as_le_u16(&[3000u16; 1]);
let mut out = [0u16; 3];
gbr_to_rgb_u16_high_bit_row::<12, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], 3000); assert_eq!(out[1], 1000); assert_eq!(out[2], 2000); }
#[test]
fn rgba_opaque_high_bit_bits10_alpha_is_0xff() {
let max = (1u16 << 10) - 1;
let g = as_le_u16(&[max; 4]);
let b = as_le_u16(&[max; 4]);
let r = as_le_u16(&[max; 4]);
let mut out = [0u8; 16];
gbr_to_rgba_opaque_high_bit_row::<10, false>(&g, &b, &r, &mut out, 4);
for i in 0..4 {
assert_eq!(out[i * 4 + 3], 0xFF, "alpha must be 0xFF at pixel {i}");
assert_eq!(out[i * 4], 0xFF, "R must be 0xFF at pixel {i}");
}
}
#[test]
fn rgba_opaque_high_bit_bits9_downshift_correct() {
let g = as_le_u16(&[510u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[0u16; 1]);
let mut out = [0u8; 4];
gbr_to_rgba_opaque_high_bit_row::<9, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[1], 255); assert_eq!(out[3], 0xFF); }
#[test]
fn rgba_opaque_u16_high_bit_bits10_alpha_is_1023() {
let g = as_le_u16(&[500u16; 2]);
let b = as_le_u16(&[200u16; 2]);
let r = as_le_u16(&[800u16; 2]);
let mut out = [0u16; 8];
gbr_to_rgba_opaque_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 2);
let opaque = (1u16 << 10) - 1; assert_eq!(out[3], opaque); assert_eq!(out[7], opaque); assert_eq!(out[0], 800); assert_eq!(out[1], 500); assert_eq!(out[2], 200); }
#[test]
fn rgba_opaque_u16_high_bit_bits16_alpha_is_65535() {
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[0u16; 1]);
let mut out = [0u16; 4];
gbr_to_rgba_opaque_u16_high_bit_row::<16, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[3], u16::MAX);
}
#[test]
fn rgba_opaque_u16_high_bit_bits9_alpha_is_511() {
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[0u16; 1]);
let mut out = [0u16; 4];
gbr_to_rgba_opaque_u16_high_bit_row::<9, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[3], (1u16 << 9) - 1); }
#[test]
fn gbra_rgba_high_bit_bits10_source_alpha_downshifted() {
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[0u16; 1]);
let a = as_le_u16(&[512u16; 1]);
let mut out = [0u8; 4];
gbra_to_rgba_high_bit_row::<10, false>(&g, &b, &r, &a, &mut out, 1);
assert_eq!(out[3], 128); }
#[test]
fn gbra_rgba_high_bit_bits10_max_alpha_is_0xff() {
let max = (1u16 << 10) - 1;
let g = as_le_u16(&[max; 2]);
let b = as_le_u16(&[max; 2]);
let r = as_le_u16(&[max; 2]);
let a = as_le_u16(&[max; 2]);
let mut out = [0u8; 8];
gbra_to_rgba_high_bit_row::<10, false>(&g, &b, &r, &a, &mut out, 2);
for i in 0..2 {
assert_eq!(out[i * 4 + 3], 0xFF, "alpha must be 0xFF at pixel {i}");
}
}
#[test]
fn gbra_rgba_high_bit_bits14_channel_reorder_and_shift() {
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[16320u16; 1]);
let a = as_le_u16(&[8192u16; 1]);
let mut out = [0u8; 4];
gbra_to_rgba_high_bit_row::<14, false>(&g, &b, &r, &a, &mut out, 1);
assert_eq!(out[0], 255); assert_eq!(out[1], 0); assert_eq!(out[2], 0); assert_eq!(out[3], 128); }
#[test]
fn gbra_rgba_u16_high_bit_source_alpha_preserved() {
let g = as_le_u16(&[100u16; 1]);
let b = as_le_u16(&[200u16; 1]);
let r = as_le_u16(&[300u16; 1]);
let a = as_le_u16(&[777u16; 1]);
let mut out = [0u16; 4];
gbra_to_rgba_u16_high_bit_row::<10, false>(&g, &b, &r, &a, &mut out, 1);
assert_eq!(out[0], 300); assert_eq!(out[1], 100); assert_eq!(out[2], 200); assert_eq!(out[3], 777); }
#[test]
fn gbra_rgba_u16_high_bit_bits16_all_channels_preserved() {
let g = as_le_u16(&[10000u16; 2]);
let b = as_le_u16(&[20000u16; 2]);
let r = as_le_u16(&[30000u16; 2]);
let a = as_le_u16(&[40000u16; 2]);
let mut out = [0u16; 8];
gbra_to_rgba_u16_high_bit_row::<16, false>(&g, &b, &r, &a, &mut out, 2);
for i in 0..2 {
assert_eq!(out[i * 4], 30000);
assert_eq!(out[i * 4 + 1], 10000);
assert_eq!(out[i * 4 + 2], 20000);
assert_eq!(out[i * 4 + 3], 40000);
}
}
#[test]
fn rgb_high_bit_bits10_parity_with_scaled_8bit() {
let val: u16 = 128u16 << 2;
let g = as_le_u16(&[val; 8]);
let b = as_le_u16(&[val; 8]);
let r = as_le_u16(&[val; 8]);
let mut out = [0u8; 24];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, 8);
assert!(out.iter().all(|&v| v == 128));
}
#[test]
fn rgb_high_bit_bits12_parity_with_scaled_8bit() {
let val: u16 = 200u16 << 4;
let g = as_le_u16(&[val; 4]);
let b = as_le_u16(&[val; 4]);
let r = as_le_u16(&[val; 4]);
let mut out = [0u8; 12];
gbr_to_rgb_high_bit_row::<12, false>(&g, &b, &r, &mut out, 4);
assert!(out.iter().all(|&v| v == 200));
}
#[test]
fn gbr_to_rgb_high_bit_masks_upper_bits_bits10() {
let dirty: u16 = 0x0CFF;
let clean = dirty & 0x03FF;
let expected_u8 = (clean >> 2) as u8;
let g = as_le_u16(&[dirty; 1]);
let b = as_le_u16(&[dirty; 1]);
let r = as_le_u16(&[dirty; 1]);
let mut out = [0u8; 3];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1);
assert_eq!(
out[0], expected_u8,
"R must equal masked-then-shifted value"
);
assert_eq!(
out[1], expected_u8,
"G must equal masked-then-shifted value"
);
assert_eq!(
out[2], expected_u8,
"B must equal masked-then-shifted value"
);
}
#[test]
fn gbr_to_rgb_high_bit_masks_upper_bits_multiple_widths_bits10() {
let dirty: u16 = 0x0500; let clean = dirty & 0x03FF;
let expected_u8 = (clean >> 2) as u8;
for w in [1usize, 7, 8, 16, 17, 32, 33, 64, 128, 130] {
let g = as_le_u16(&std::vec![dirty; w]);
let b = as_le_u16(&std::vec![dirty; w]);
let r = as_le_u16(&std::vec![dirty; w]);
let mut out = std::vec![0u8; w * 3];
gbr_to_rgb_high_bit_row::<10, false>(&g, &b, &r, &mut out, w);
for i in 0..w {
assert_eq!(out[i * 3], expected_u8, "R pixel {i} wrong at width {w}");
assert_eq!(
out[i * 3 + 1],
expected_u8,
"G pixel {i} wrong at width {w}"
);
assert_eq!(
out[i * 3 + 2],
expected_u8,
"B pixel {i} wrong at width {w}"
);
}
}
}
#[test]
fn gbra_to_rgba_high_bit_masks_upper_bits_alpha_bits10() {
let dirty_rgb: u16 = 0x0400; let dirty_alpha: u16 = 0x0A00; let g = as_le_u16(&[dirty_rgb; 1]);
let b = as_le_u16(&[dirty_rgb; 1]);
let r = as_le_u16(&[dirty_rgb; 1]);
let a = as_le_u16(&[dirty_alpha; 1]);
let mut out = [0u8; 4];
gbra_to_rgba_high_bit_row::<10, false>(&g, &b, &r, &a, &mut out, 1);
assert_eq!(out[0], 0, "R (dirty, masked to 0)");
assert_eq!(out[1], 0, "G (dirty, masked to 0)");
assert_eq!(out[2], 0, "B (dirty, masked to 0)");
assert_eq!(out[3], 128, "alpha must be masked then shifted");
}
#[test]
fn gbr_to_rgb_u16_high_bit_masks_upper_bits_bits10() {
let dirty: u16 = 0x0CFF;
let clean = dirty & 0x03FF; let g = as_le_u16(&[dirty; 1]);
let b = as_le_u16(&[dirty; 1]);
let r = as_le_u16(&[dirty; 1]);
let mut out = [0u16; 3];
gbr_to_rgb_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], clean, "R u16 must be masked value");
assert_eq!(out[1], clean, "G u16 must be masked value");
assert_eq!(out[2], clean, "B u16 must be masked value");
}
#[test]
fn gbra_to_rgba_u16_high_bit_masks_upper_bits_bits10() {
let dirty: u16 = 0x0555; let clean = dirty & 0x03FF;
let g = as_le_u16(&[dirty; 1]);
let b = as_le_u16(&[dirty; 1]);
let r = as_le_u16(&[dirty; 1]);
let a = as_le_u16(&[dirty; 1]);
let mut out = [0u16; 4];
gbra_to_rgba_u16_high_bit_row::<10, false>(&g, &b, &r, &a, &mut out, 1);
assert_eq!(out[0], clean, "R u16 must be masked");
assert_eq!(out[1], clean, "G u16 must be masked");
assert_eq!(out[2], clean, "B u16 must be masked");
assert_eq!(out[3], clean, "A u16 must be masked");
}
#[test]
fn gbr_to_rgba_opaque_high_bit_masks_upper_bits_bits10() {
let dirty: u16 = 0x0CFF; let clean = dirty & 0x03FF;
let expected_u8 = (clean >> 2) as u8;
let g = as_le_u16(&[dirty; 1]);
let b = as_le_u16(&[dirty; 1]);
let r = as_le_u16(&[dirty; 1]);
let mut out = [0u8; 4];
gbr_to_rgba_opaque_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], expected_u8, "R must be masked");
assert_eq!(out[1], expected_u8, "G must be masked");
assert_eq!(out[2], expected_u8, "B must be masked");
assert_eq!(out[3], 0xFF, "alpha must be 0xFF");
}
#[test]
fn gbr_to_rgba_opaque_u16_high_bit_masks_upper_bits_bits10() {
let dirty: u16 = 0x0CFF; let clean = dirty & 0x03FF;
let g = as_le_u16(&[dirty; 1]);
let b = as_le_u16(&[dirty; 1]);
let r = as_le_u16(&[dirty; 1]);
let mut out = [0u16; 4];
gbr_to_rgba_opaque_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1);
assert_eq!(out[0], clean, "R u16 must be masked");
assert_eq!(out[1], clean, "G u16 must be masked");
assert_eq!(out[2], clean, "B u16 must be masked");
assert_eq!(out[3], (1u16 << 10) - 1, "alpha must be opaque 1023");
}
#[test]
fn gbr_to_rgb_high_bit_bits16_mask_is_noop() {
let val = u16::MAX;
let g = as_le_u16(&[val; 2]);
let b = as_le_u16(&[val; 2]);
let r = as_le_u16(&[val; 2]);
let mut out = [0u8; 6];
gbr_to_rgb_high_bit_row::<16, false>(&g, &b, &r, &mut out, 2);
assert!(
out.iter().all(|&v| v == 0xFF),
"BITS=16: max sample => 0xFF"
);
}
#[test]
fn gbra_to_rgba_high_bit_cross_path_consistency_bits10() {
let dirty_alpha: u16 = 0x0900;
let clean_alpha = dirty_alpha & 0x03FF; let expected_a_u8 = (clean_alpha >> 2) as u8;
let r = as_le_u16(&[400u16; 1]); let g = as_le_u16(&[200u16; 1]);
let b = as_le_u16(&[100u16; 1]);
let a = as_le_u16(&[dirty_alpha; 1]);
let mut out_direct = [0u8; 4];
gbra_to_rgba_high_bit_row::<10, false>(&g, &b, &r, &a, &mut out_direct, 1);
let a_clean = as_le_u16(&[clean_alpha; 1]);
let mut out_manual = [0u8; 4];
gbra_to_rgba_high_bit_row::<10, false>(&g, &b, &r, &a_clean, &mut out_manual, 1);
assert_eq!(
out_direct, out_manual,
"direct GBRA path must match manually-masked alpha path"
);
assert_eq!(out_direct[3], expected_a_u8, "alpha channel value");
}
#[test]
fn luma_u16_high_bit_bits10_max_white_not_banded() {
let max = (1u16 << 10) - 1; let g = as_le_u16(&[max; 1]);
let b = as_le_u16(&[max; 1]);
let r = as_le_u16(&[max; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, true);
assert!(
out[0] >= 1020,
"max-white luma_u16 must be near 1023 (was {}, old banded path gives 1020)",
out[0]
);
assert!(
out[0] <= 1023,
"max-white luma_u16 must not exceed native max"
);
}
#[test]
fn luma_u16_high_bit_bits12_max_white_not_banded() {
let max = (1u16 << 12) - 1; let g = as_le_u16(&[max; 1]);
let b = as_le_u16(&[max; 1]);
let r = as_le_u16(&[max; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<12, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt601, true);
assert!(
out[0] >= 4090,
"max-white luma_u16 bits12 must be near 4095 (was {})",
out[0]
);
assert!(out[0] <= 4095, "must not exceed native max");
}
#[test]
fn luma_u16_high_bit_bits16_max_white_not_banded() {
let max = u16::MAX;
let g = as_le_u16(&[max; 1]);
let b = as_le_u16(&[max; 1]);
let r = as_le_u16(&[max; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<16, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, true);
assert!(
out[0] >= 65520,
"max-white luma_u16 bits16 must be near 65535 (was {}), old banded gives 65280",
out[0]
);
}
#[test]
fn luma_u16_high_bit_bits10_neutral_gray_midrange() {
let mid = 512u16;
let g = as_le_u16(&[mid; 1]);
let b = as_le_u16(&[mid; 1]);
let r = as_le_u16(&[mid; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, true);
assert!(
out[0] >= 510 && out[0] <= 514,
"neutral gray luma_u16 must be ~512 (was {})",
out[0]
);
}
#[test]
fn luma_u16_high_bit_bits10_zero_gives_zero() {
let g = as_le_u16(&[0u16; 2]);
let b = as_le_u16(&[0u16; 2]);
let r = as_le_u16(&[0u16; 2]);
let mut out = [0xFFFFu16; 2];
gbr_to_luma_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 2, ColorMatrix::Bt709, true);
assert!(out.iter().all(|&v| v == 0), "all-black must give zero luma");
}
#[test]
fn luma_u16_high_bit_bits10_full_range_vs_limited_range() {
let mid = 512u16;
let g = as_le_u16(&[mid; 1]);
let b = as_le_u16(&[mid; 1]);
let r = as_le_u16(&[mid; 1]);
let mut out_full = [0u16; 1];
let mut out_lim = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out_full, 1, ColorMatrix::Bt601, true);
gbr_to_luma_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out_lim, 1, ColorMatrix::Bt601, false);
let y_off = 16u16 << 2; let y_max = 235u16 << 2; assert!(
out_full[0] >= out_lim[0],
"limited-range luma <= full-range luma for mid gray"
);
assert!(
out_lim[0] >= y_off,
"limited-range must be >= 64 (was {})",
out_lim[0]
);
assert!(
out_lim[0] <= y_max,
"limited-range must be <= 940 (was {})",
out_lim[0]
);
}
#[test]
fn luma_u16_high_bit_bits16_limited_range_black_gives_min_offset() {
let g = as_le_u16(&[0u16; 1]);
let b = as_le_u16(&[0u16; 1]);
let r = as_le_u16(&[0u16; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<16, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, false);
let y_off = 16u16 << 8; assert_eq!(
out[0], y_off,
"all-black limited-range must give Y_off={y_off}"
);
}
#[test]
fn luma_u16_high_bit_bits16_limited_range_max_white_maps_to_y_max() {
let g = as_le_u16(&[u16::MAX; 1]);
let b = as_le_u16(&[u16::MAX; 1]);
let r = as_le_u16(&[u16::MAX; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<16, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, false);
let y_max = 235u16 << 8; assert_eq!(
out[0], y_max,
"all-white limited-range must give Y_max={y_max}"
);
}
#[test]
fn luma_u16_high_bit_bits16_limited_range_near_white_keeps_gradation() {
for &v in &[65000u16, 65300, 65500] {
let g = as_le_u16(&[v; 1]);
let b = as_le_u16(&[v; 1]);
let r = as_le_u16(&[v; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<16, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, false);
let expected = 4096 + ((v as u64 * 56064 + 65535 / 2) / 65535) as u16;
let diff = (out[0] as i32 - expected as i32).abs();
assert!(
diff <= 1,
"v={v} expected ≈{expected} got {} (diff {diff})",
out[0]
);
assert!(
out[0] < 60160 || (v >= 65500),
"limited-range must not clamp at v={v} (got {})",
out[0]
);
}
}
#[test]
fn luma_u16_high_bit_bits10_limited_range_endpoints() {
let cases: &[(u16, u16)] = &[(0, 64), (1023, 940)];
for &(input, expected) in cases {
let g = as_le_u16(&[input; 1]);
let b = as_le_u16(&[input; 1]);
let r = as_le_u16(&[input; 1]);
let mut out = [0u16; 1];
gbr_to_luma_u16_high_bit_row::<10, false>(&g, &b, &r, &mut out, 1, ColorMatrix::Bt709, false);
let diff = (out[0] as i32 - expected as i32).abs();
assert!(
diff <= 1,
"BITS=10 input={input} expected ≈{expected} got {}",
out[0]
);
}
}
fn as_be_u16(host: &[u16]) -> std::vec::Vec<u16> {
host
.iter()
.map(|v| u16::from_ne_bytes(v.to_be_bytes()))
.collect()
}
fn rand_plane<const BITS: u32>(seed: u32, n: usize) -> std::vec::Vec<u16> {
let mask = (1u32 << BITS) - 1;
let mut s = seed;
(0..n)
.map(|_| {
s = s.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
(s & mask) as u16
})
.collect()
}
fn ref_gbr_to_rgb_high_bit<const BITS: u32>(
g: &[u16],
b: &[u16],
r: &[u16],
width: usize,
) -> std::vec::Vec<u8> {
let shift = BITS - 8;
let mut out = std::vec![0u8; width * 3];
for x in 0..width {
out[x * 3] = (r[x] >> shift) as u8;
out[x * 3 + 1] = (g[x] >> shift) as u8;
out[x * 3 + 2] = (b[x] >> shift) as u8;
}
out
}
fn ref_gbr_to_rgba_opaque_high_bit<const BITS: u32>(
g: &[u16],
b: &[u16],
r: &[u16],
width: usize,
) -> std::vec::Vec<u8> {
let shift = BITS - 8;
let mut out = std::vec![0u8; width * 4];
for x in 0..width {
out[x * 4] = (r[x] >> shift) as u8;
out[x * 4 + 1] = (g[x] >> shift) as u8;
out[x * 4 + 2] = (b[x] >> shift) as u8;
out[x * 4 + 3] = 0xFF;
}
out
}
fn ref_gbra_to_rgba_high_bit<const BITS: u32>(
g: &[u16],
b: &[u16],
r: &[u16],
a: &[u16],
width: usize,
) -> std::vec::Vec<u8> {
let shift = BITS - 8;
let mut out = std::vec![0u8; width * 4];
for x in 0..width {
out[x * 4] = (r[x] >> shift) as u8;
out[x * 4 + 1] = (g[x] >> shift) as u8;
out[x * 4 + 2] = (b[x] >> shift) as u8;
out[x * 4 + 3] = (a[x] >> shift) as u8;
}
out
}
fn ref_gbr_to_rgb_u16_high_bit<const BITS: u32>(
g: &[u16],
b: &[u16],
r: &[u16],
width: usize,
) -> std::vec::Vec<u16> {
let mask: u16 = ((1u32 << BITS) - 1) as u16;
let mut out = std::vec![0u16; width * 3];
for x in 0..width {
out[x * 3] = r[x] & mask;
out[x * 3 + 1] = g[x] & mask;
out[x * 3 + 2] = b[x] & mask;
}
out
}
fn ref_gbra_to_rgba_u16_high_bit<const BITS: u32>(
g: &[u16],
b: &[u16],
r: &[u16],
a: &[u16],
width: usize,
) -> std::vec::Vec<u16> {
let mask: u16 = ((1u32 << BITS) - 1) as u16;
let mut out = std::vec![0u16; width * 4];
for x in 0..width {
out[x * 4] = r[x] & mask;
out[x * 4 + 1] = g[x] & mask;
out[x * 4 + 2] = b[x] & mask;
out[x * 4 + 3] = a[x] & mask;
}
out
}
#[test]
fn scalar_gbr_to_rgb_high_bit_be_parity_bits10() {
for w in [1usize, 7, 8, 9, 17, 33, 65] {
let g = rand_plane::<10>(0xAAAA, w);
let b = rand_plane::<10>(0xBBBB, w);
let r = rand_plane::<10>(0xCCCC, w);
let g_le = as_le_u16(&g);
let b_le = as_le_u16(&b);
let r_le = as_le_u16(&r);
let g_be = as_be_u16(&g);
let b_be = as_be_u16(&b);
let r_be = as_be_u16(&r);
let mut out_le = std::vec![0u8; w * 3];
let mut out_be = std::vec![0u8; w * 3];
gbr_to_rgb_high_bit_row::<10, false>(&g_le, &b_le, &r_le, &mut out_le, w);
gbr_to_rgb_high_bit_row::<10, true>(&g_be, &b_be, &r_be, &mut out_be, w);
let expected = ref_gbr_to_rgb_high_bit::<10>(&g, &b, &r, w);
assert_eq!(
out_le, expected,
"scalar LE path does not match independent reference (gbr_to_rgb bits10 w={w})"
);
assert_eq!(
out_le, out_be,
"scalar BE/LE mismatch gbr_to_rgb bits10 w={w}"
);
}
}
#[test]
fn scalar_gbr_to_rgb_high_bit_be_parity_bits16() {
for w in [1usize, 7, 8, 9, 17, 33, 65] {
let g = rand_plane::<16>(0xAAAA, w);
let b = rand_plane::<16>(0xBBBB, w);
let r = rand_plane::<16>(0xCCCC, w);
let g_le = as_le_u16(&g);
let b_le = as_le_u16(&b);
let r_le = as_le_u16(&r);
let g_be = as_be_u16(&g);
let b_be = as_be_u16(&b);
let r_be = as_be_u16(&r);
let mut out_le = std::vec![0u8; w * 3];
let mut out_be = std::vec![0u8; w * 3];
gbr_to_rgb_high_bit_row::<16, false>(&g_le, &b_le, &r_le, &mut out_le, w);
gbr_to_rgb_high_bit_row::<16, true>(&g_be, &b_be, &r_be, &mut out_be, w);
let expected = ref_gbr_to_rgb_high_bit::<16>(&g, &b, &r, w);
assert_eq!(
out_le, expected,
"scalar LE path does not match independent reference (gbr_to_rgb bits16 w={w})"
);
assert_eq!(
out_le, out_be,
"scalar BE/LE mismatch gbr_to_rgb bits16 w={w}"
);
}
}
#[test]
fn scalar_gbr_to_rgba_opaque_high_bit_be_parity_bits10() {
for w in [1usize, 7, 8, 9, 17] {
let g = rand_plane::<10>(0xAAAA, w);
let b = rand_plane::<10>(0xBBBB, w);
let r = rand_plane::<10>(0xCCCC, w);
let g_le = as_le_u16(&g);
let b_le = as_le_u16(&b);
let r_le = as_le_u16(&r);
let g_be = as_be_u16(&g);
let b_be = as_be_u16(&b);
let r_be = as_be_u16(&r);
let mut out_le = std::vec![0u8; w * 4];
let mut out_be = std::vec![0u8; w * 4];
gbr_to_rgba_opaque_high_bit_row::<10, false>(&g_le, &b_le, &r_le, &mut out_le, w);
gbr_to_rgba_opaque_high_bit_row::<10, true>(&g_be, &b_be, &r_be, &mut out_be, w);
let expected = ref_gbr_to_rgba_opaque_high_bit::<10>(&g, &b, &r, w);
assert_eq!(
out_le, expected,
"scalar LE path does not match independent reference (gbr_to_rgba_opaque bits10 w={w})"
);
assert_eq!(
out_le, out_be,
"scalar BE/LE mismatch gbr_to_rgba_opaque bits10 w={w}"
);
}
}
#[test]
fn scalar_gbra_to_rgba_high_bit_be_parity_bits10() {
for w in [1usize, 7, 8, 9, 17] {
let g = rand_plane::<10>(0xAAAA, w);
let b = rand_plane::<10>(0xBBBB, w);
let r = rand_plane::<10>(0xCCCC, w);
let a = rand_plane::<10>(0xDDDD, w);
let g_le = as_le_u16(&g);
let b_le = as_le_u16(&b);
let r_le = as_le_u16(&r);
let a_le = as_le_u16(&a);
let g_be = as_be_u16(&g);
let b_be = as_be_u16(&b);
let r_be = as_be_u16(&r);
let a_be = as_be_u16(&a);
let mut out_le = std::vec![0u8; w * 4];
let mut out_be = std::vec![0u8; w * 4];
gbra_to_rgba_high_bit_row::<10, false>(&g_le, &b_le, &r_le, &a_le, &mut out_le, w);
gbra_to_rgba_high_bit_row::<10, true>(&g_be, &b_be, &r_be, &a_be, &mut out_be, w);
let expected = ref_gbra_to_rgba_high_bit::<10>(&g, &b, &r, &a, w);
assert_eq!(
out_le, expected,
"scalar LE path does not match independent reference (gbra_to_rgba bits10 w={w})"
);
assert_eq!(
out_le, out_be,
"scalar BE/LE mismatch gbra_to_rgba bits10 w={w}"
);
}
}
#[test]
fn scalar_gbr_to_rgb_u16_high_bit_be_parity_bits10() {
for w in [1usize, 7, 8, 9, 17] {
let g = rand_plane::<10>(0xAAAA, w);
let b = rand_plane::<10>(0xBBBB, w);
let r = rand_plane::<10>(0xCCCC, w);
let g_le = as_le_u16(&g);
let b_le = as_le_u16(&b);
let r_le = as_le_u16(&r);
let g_be = as_be_u16(&g);
let b_be = as_be_u16(&b);
let r_be = as_be_u16(&r);
let mut out_le = std::vec![0u16; w * 3];
let mut out_be = std::vec![0u16; w * 3];
gbr_to_rgb_u16_high_bit_row::<10, false>(&g_le, &b_le, &r_le, &mut out_le, w);
gbr_to_rgb_u16_high_bit_row::<10, true>(&g_be, &b_be, &r_be, &mut out_be, w);
let expected = ref_gbr_to_rgb_u16_high_bit::<10>(&g, &b, &r, w);
assert_eq!(
out_le, expected,
"scalar LE path does not match independent reference (gbr_to_rgb_u16 bits10 w={w})"
);
assert_eq!(
out_le, out_be,
"scalar BE/LE mismatch gbr_to_rgb_u16 bits10 w={w}"
);
}
}
#[test]
fn scalar_gbra_to_rgba_u16_high_bit_be_parity_bits10() {
for w in [1usize, 7, 8, 9, 17] {
let g = rand_plane::<10>(0xAAAA, w);
let b = rand_plane::<10>(0xBBBB, w);
let r = rand_plane::<10>(0xCCCC, w);
let a = rand_plane::<10>(0xDDDD, w);
let g_le = as_le_u16(&g);
let b_le = as_le_u16(&b);
let r_le = as_le_u16(&r);
let a_le = as_le_u16(&a);
let g_be = as_be_u16(&g);
let b_be = as_be_u16(&b);
let r_be = as_be_u16(&r);
let a_be = as_be_u16(&a);
let mut out_le = std::vec![0u16; w * 4];
let mut out_be = std::vec![0u16; w * 4];
gbra_to_rgba_u16_high_bit_row::<10, false>(&g_le, &b_le, &r_le, &a_le, &mut out_le, w);
gbra_to_rgba_u16_high_bit_row::<10, true>(&g_be, &b_be, &r_be, &a_be, &mut out_be, w);
let expected = ref_gbra_to_rgba_u16_high_bit::<10>(&g, &b, &r, &a, w);
assert_eq!(
out_le, expected,
"scalar LE path does not match independent reference (gbra_to_rgba_u16 bits10 w={w})"
);
assert_eq!(
out_le, out_be,
"scalar BE/LE mismatch gbra_to_rgba_u16 bits10 w={w}"
);
}
}