#![cfg_attr(not(feature = "std"), allow(dead_code))]
#[cfg(feature = "yuv-444-packed")]
pub(crate) fn copy_alpha_packed_u8x4_at_3(packed: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(packed.len() >= width * 4, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
rgba_out[n * 4 + 3] = packed[n * 4 + 3];
}
}
#[cfg(feature = "yuv-444-packed")]
pub(crate) fn copy_alpha_packed_u16x4_to_u8_at_0<const BE: bool>(
packed: &[u16],
rgba_out: &mut [u8],
width: usize,
) {
debug_assert!(packed.len() >= width * 4, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let raw = if BE {
u16::from_be(packed[n * 4])
} else {
u16::from_le(packed[n * 4])
};
rgba_out[n * 4 + 3] = (raw >> 8) as u8;
}
}
#[cfg(feature = "yuv-444-packed")]
pub(crate) fn copy_alpha_packed_u16x4_at_0<const BE: bool>(
packed: &[u16],
rgba_out: &mut [u16],
width: usize,
) {
debug_assert!(packed.len() >= width * 4, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let raw = if BE {
u16::from_be(packed[n * 4])
} else {
u16::from_le(packed[n * 4])
};
rgba_out[n * 4 + 3] = raw;
}
}
#[allow(dead_code)] pub(crate) fn copy_alpha_packed_u16x4_to_u8_at_3<const BE: bool>(
packed: &[u16],
rgba_out: &mut [u8],
width: usize,
) {
debug_assert!(packed.len() >= width * 4, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let raw = if BE {
u16::from_be(packed[n * 4 + 3])
} else {
u16::from_le(packed[n * 4 + 3])
};
rgba_out[n * 4 + 3] = (raw >> 8) as u8;
}
}
#[allow(dead_code)] pub(crate) fn copy_alpha_packed_u16x4_at_3<const BE: bool>(
packed: &[u16],
rgba_u16_out: &mut [u16],
width: usize,
) {
debug_assert!(packed.len() >= width * 4, "packed too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for n in 0..width {
let raw = if BE {
u16::from_be(packed[n * 4 + 3])
} else {
u16::from_le(packed[n * 4 + 3])
};
rgba_u16_out[n * 4 + 3] = raw;
}
}
#[cfg(any(feature = "gbr", feature = "yuva"))]
pub(crate) fn copy_alpha_plane_u8(alpha: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(alpha.len() >= width, "alpha plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
rgba_out[n * 4 + 3] = alpha[n];
}
}
#[cfg(any(feature = "gbr", feature = "yuva"))]
pub(crate) fn copy_alpha_plane_u16_to_u8<const BITS: u32, const BE: bool>(
alpha: &[u16],
rgba_out: &mut [u8],
width: usize,
) {
const {
assert!(BITS >= 8 && BITS <= 16, "BITS must be in [8, 16]");
}
debug_assert!(alpha.len() >= width, "alpha plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
let mask: u16 = ((1u32 << BITS) - 1) as u16;
let shift = BITS - 8;
for n in 0..width {
let raw = if BE {
u16::from_be(alpha[n])
} else {
u16::from_le(alpha[n])
};
rgba_out[n * 4 + 3] = ((raw & mask) >> shift) as u8;
}
}
#[cfg(any(feature = "gbr", feature = "yuva"))]
pub(crate) fn copy_alpha_plane_u16<const BITS: u32, const BE: bool>(
alpha: &[u16],
rgba_out: &mut [u16],
width: usize,
) {
const {
assert!(BITS > 0 && BITS <= 16, "BITS must be in [1, 16]");
}
debug_assert!(alpha.len() >= width, "alpha plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
let mask: u16 = ((1u32 << BITS) - 1) as u16;
for n in 0..width {
let raw = if BE {
u16::from_be(alpha[n])
} else {
u16::from_le(alpha[n])
};
rgba_out[n * 4 + 3] = raw & mask;
}
}
#[cfg(feature = "gray")]
pub(crate) fn copy_alpha_ya_u8(packed: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(packed.len() >= width * 2, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
rgba_out[n * 4 + 3] = packed[n * 2 + 1];
}
}
#[cfg(feature = "gray")]
pub(crate) fn copy_alpha_ya_u16_to_u8<const BE: bool>(
packed: &[u16],
rgba_out: &mut [u8],
width: usize,
) {
debug_assert!(packed.len() >= width * 2, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let raw = if BE {
u16::from_be(packed[n * 2 + 1])
} else {
u16::from_le(packed[n * 2 + 1])
};
rgba_out[n * 4 + 3] = (raw >> 8) as u8;
}
}
#[cfg(feature = "gray")]
pub(crate) fn copy_alpha_ya_u16<const BE: bool>(
packed: &[u16],
rgba_out: &mut [u16],
width: usize,
) {
debug_assert!(packed.len() >= width * 2, "packed too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let raw = if BE {
u16::from_be(packed[n * 2 + 1])
} else {
u16::from_le(packed[n * 2 + 1])
};
rgba_out[n * 4 + 3] = raw;
}
}
#[allow(dead_code)]
pub(crate) fn copy_alpha_plane_f32_to_u8<const BE: bool>(
alpha: &[f32],
rgba_out: &mut [u8],
width: usize,
) {
debug_assert!(alpha.len() >= width, "alpha plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let bits = alpha[n].to_bits();
let host_bits = if BE {
u32::from_be(bits)
} else {
u32::from_le(bits)
};
let v = f32::from_bits(host_bits);
rgba_out[n * 4 + 3] = (v.clamp(0.0, 1.0) * 255.0 + 0.5) as u8;
}
}
#[allow(dead_code)]
pub(crate) fn copy_alpha_plane_f32_to_u16<const BE: bool>(
alpha: &[f32],
rgba_out: &mut [u16],
width: usize,
) {
debug_assert!(alpha.len() >= width, "alpha plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let bits = alpha[n].to_bits();
let host_bits = if BE {
u32::from_be(bits)
} else {
u32::from_le(bits)
};
let v = f32::from_bits(host_bits);
rgba_out[n * 4 + 3] = (v.clamp(0.0, 1.0) * 65535.0 + 0.5) as u16;
}
}
#[allow(dead_code)]
pub(crate) fn copy_alpha_plane_f32<const BE: bool>(
alpha: &[f32],
rgba_out: &mut [f32],
width: usize,
) {
debug_assert!(alpha.len() >= width, "alpha plane too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for n in 0..width {
let bits = alpha[n].to_bits();
let host_bits = if BE {
u32::from_be(bits)
} else {
u32::from_le(bits)
};
rgba_out[n * 4 + 3] = f32::from_bits(host_bits);
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
fn as_le_u16(host: &[u16]) -> std::vec::Vec<u16> {
host
.iter()
.map(|v| u16::from_ne_bytes(v.to_le_bytes()))
.collect()
}
fn as_be_u16(host: &[u16]) -> std::vec::Vec<u16> {
host
.iter()
.map(|v| u16::from_ne_bytes(v.to_be_bytes()))
.collect()
}
fn as_le_f32(host: &[f32]) -> std::vec::Vec<f32> {
host
.iter()
.map(|v| f32::from_bits(u32::from_ne_bytes(v.to_bits().to_le_bytes())))
.collect()
}
fn as_be_f32(host: &[f32]) -> std::vec::Vec<f32> {
host
.iter()
.map(|v| f32::from_bits(u32::from_ne_bytes(v.to_bits().to_be_bytes())))
.collect()
}
fn ref_copy_alpha_packed_u16x4_to_u8_at_0(
intended: &[u16],
fill: u8,
width: usize,
) -> std::vec::Vec<u8> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = (intended[n * 4] >> 8) as u8;
}
out
}
fn ref_copy_alpha_packed_u16x4_at_0(
intended: &[u16],
fill: u16,
width: usize,
) -> std::vec::Vec<u16> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = intended[n * 4];
}
out
}
fn ref_copy_alpha_plane_u16_to_u8<const BITS: u32>(
intended: &[u16],
fill: u8,
width: usize,
) -> std::vec::Vec<u8> {
let mask: u16 = ((1u32 << BITS) - 1) as u16;
let shift = BITS - 8;
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = ((intended[n] & mask) >> shift) as u8;
}
out
}
fn ref_copy_alpha_plane_u16<const BITS: u32>(
intended: &[u16],
fill: u16,
width: usize,
) -> std::vec::Vec<u16> {
let mask: u16 = ((1u32 << BITS) - 1) as u16;
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = intended[n] & mask;
}
out
}
fn ref_copy_alpha_ya_u16_to_u8(intended: &[u16], fill: u8, width: usize) -> std::vec::Vec<u8> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = (intended[n * 2 + 1] >> 8) as u8;
}
out
}
fn ref_copy_alpha_ya_u16(intended: &[u16], fill: u16, width: usize) -> std::vec::Vec<u16> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = intended[n * 2 + 1];
}
out
}
fn ref_copy_alpha_packed_u16x4_to_u8_at_3(
intended: &[u16],
fill: u8,
width: usize,
) -> std::vec::Vec<u8> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = (intended[n * 4 + 3] >> 8) as u8;
}
out
}
fn ref_copy_alpha_packed_u16x4_at_3(
intended: &[u16],
fill: u16,
width: usize,
) -> std::vec::Vec<u16> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = intended[n * 4 + 3];
}
out
}
fn ref_copy_alpha_plane_f32_to_u8(intended: &[f32], fill: u8, width: usize) -> std::vec::Vec<u8> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = (intended[n].clamp(0.0, 1.0) * 255.0 + 0.5) as u8;
}
out
}
fn ref_copy_alpha_plane_f32_to_u16(
intended: &[f32],
fill: u16,
width: usize,
) -> std::vec::Vec<u16> {
let mut out = std::vec![fill; width * 4];
for n in 0..width {
out[n * 4 + 3] = (intended[n].clamp(0.0, 1.0) * 65535.0 + 0.5) as u16;
}
out
}
#[test]
fn copy_alpha_packed_u8x4_at_3_overwrites_only_alpha_slots() {
let packed = [10, 20, 30, 99, 11, 21, 31, 88, 12, 22, 32, 77];
let mut rgba = std::vec![1u8; 12];
copy_alpha_packed_u8x4_at_3(&packed, &mut rgba, 3);
assert_eq!(rgba, std::vec![1, 1, 1, 99, 1, 1, 1, 88, 1, 1, 1, 77]);
}
#[test]
fn copy_alpha_packed_u16x4_to_u8_at_0_depth_converts_correctly() {
let packed = as_le_u16(&[0x1234, 100, 200, 300, 0xABCD, 101, 201, 301]);
let mut rgba = std::vec![1u8; 8];
copy_alpha_packed_u16x4_to_u8_at_0::<false>(&packed, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0x12, 1, 1, 1, 0xAB]);
}
#[test]
fn copy_alpha_packed_u16x4_at_0_preserves_native_u16() {
let packed = as_le_u16(&[0x1234, 100, 200, 300, 0xABCD, 101, 201, 301]);
let mut rgba = std::vec![1u16; 8];
copy_alpha_packed_u16x4_at_0::<false>(&packed, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0x1234, 1, 1, 1, 0xABCD]);
}
#[test]
fn copy_alpha_packed_u16x4_to_u8_at_0_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![0x1234, 100, 200, 300, 0xABCD, 101, 201, 301];
let packed_le = as_le_u16(&intended);
let packed_be = as_be_u16(&intended);
let mut rgba_le = std::vec![1u8; 8];
let mut rgba_be = std::vec![1u8; 8];
copy_alpha_packed_u16x4_to_u8_at_0::<false>(&packed_le, &mut rgba_le, 2);
copy_alpha_packed_u16x4_to_u8_at_0::<true>(&packed_be, &mut rgba_be, 2);
let expected = ref_copy_alpha_packed_u16x4_to_u8_at_0(&intended, 1, 2);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_packed_u16x4_at_0_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![0x1234, 100, 200, 300, 0xABCD, 101, 201, 301];
let packed_le = as_le_u16(&intended);
let packed_be = as_be_u16(&intended);
let mut rgba_le = std::vec![7u16; 8];
let mut rgba_be = std::vec![7u16; 8];
copy_alpha_packed_u16x4_at_0::<false>(&packed_le, &mut rgba_le, 2);
copy_alpha_packed_u16x4_at_0::<true>(&packed_be, &mut rgba_be, 2);
let expected = ref_copy_alpha_packed_u16x4_at_0(&intended, 7, 2);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_plane_u8_scatters_into_rgba_alpha_slot() {
let alpha = std::vec![50u8, 60, 70, 80];
let mut rgba = std::vec![1u8; 16];
copy_alpha_plane_u8(&alpha, &mut rgba, 4);
assert_eq!(
rgba,
std::vec![1, 1, 1, 50, 1, 1, 1, 60, 1, 1, 1, 70, 1, 1, 1, 80]
);
}
#[test]
fn copy_alpha_plane_u16_to_u8_depth_converts_at_each_bits_value() {
let alpha = as_le_u16(&[0x3FF, 0x1FF]);
let mut rgba = std::vec![1u8; 8];
copy_alpha_plane_u16_to_u8::<10, false>(&alpha, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0xFF, 1, 1, 1, 0x7F]);
let alpha = as_le_u16(&[0xFFF, 0x800]);
let mut rgba = std::vec![1u8; 8];
copy_alpha_plane_u16_to_u8::<12, false>(&alpha, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0xFF, 1, 1, 1, 0x80]);
let alpha = as_le_u16(&[0xFFFF, 0x8000]);
let mut rgba = std::vec![1u8; 8];
copy_alpha_plane_u16_to_u8::<16, false>(&alpha, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0xFF, 1, 1, 1, 0x80]);
}
#[test]
fn copy_alpha_plane_u16_preserves_native_u16_within_bits_range() {
let alpha = as_le_u16(&[0x3FF, 0x1FF, 0x000]);
let mut rgba = std::vec![1u16; 12];
copy_alpha_plane_u16::<10, false>(&alpha, &mut rgba, 3);
assert_eq!(
rgba,
std::vec![1, 1, 1, 0x3FF, 1, 1, 1, 0x1FF, 1, 1, 1, 0x000]
);
}
#[test]
fn copy_alpha_plane_u16_masks_overrange_to_bits_range() {
let alpha = as_le_u16(&[0xFFFF, 0x0500, 0x07FF]);
let mut rgba = std::vec![1u16; 12];
copy_alpha_plane_u16::<10, false>(&alpha, &mut rgba, 3);
assert_eq!(
rgba,
std::vec![1, 1, 1, 0x3FF, 1, 1, 1, 0x100, 1, 1, 1, 0x3FF]
);
}
#[test]
fn copy_alpha_plane_u16_to_u8_masks_overrange_then_shifts() {
let alpha = as_le_u16(&[0x0500, 0xFFFF, 0x03FF]);
let mut rgba = std::vec![1u8; 12];
copy_alpha_plane_u16_to_u8::<10, false>(&alpha, &mut rgba, 3);
assert_eq!(rgba, std::vec![1, 1, 1, 64, 1, 1, 1, 0xFF, 1, 1, 1, 0xFF]);
}
#[test]
fn copy_alpha_plane_u16_to_u8_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![0x3FF, 0x1FF, 0x0500, 0xFFFF, 0x07FF, 0x0123];
let alpha_le = as_le_u16(&intended);
let alpha_be = as_be_u16(&intended);
let mut rgba_le = std::vec![1u8; 24];
let mut rgba_be = std::vec![1u8; 24];
copy_alpha_plane_u16_to_u8::<10, false>(&alpha_le, &mut rgba_le, 6);
copy_alpha_plane_u16_to_u8::<10, true>(&alpha_be, &mut rgba_be, 6);
let expected = ref_copy_alpha_plane_u16_to_u8::<10>(&intended, 1, 6);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_plane_u16_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![0xFFFF, 0x0500, 0x07FF, 0x0123, 0x3FF, 0x000];
let alpha_le = as_le_u16(&intended);
let alpha_be = as_be_u16(&intended);
let mut rgba_le = std::vec![7u16; 24];
let mut rgba_be = std::vec![7u16; 24];
copy_alpha_plane_u16::<10, false>(&alpha_le, &mut rgba_le, 6);
copy_alpha_plane_u16::<10, true>(&alpha_be, &mut rgba_be, 6);
let expected = ref_copy_alpha_plane_u16::<10>(&intended, 7, 6);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_ya_u8_extracts_alpha_from_odd_byte_slots() {
let packed = std::vec![10u8, 99, 20, 88, 30, 77];
let mut rgba = std::vec![1u8; 12];
copy_alpha_ya_u8(&packed, &mut rgba, 3);
assert_eq!(rgba, std::vec![1, 1, 1, 99, 1, 1, 1, 88, 1, 1, 1, 77]);
}
#[test]
fn copy_alpha_ya_u16_to_u8_depth_converts_via_high_byte() {
let packed = as_le_u16(&[0x1234, 0xABCD, 0x5678, 0xFF00]);
let mut rgba = std::vec![1u8; 8];
copy_alpha_ya_u16_to_u8::<false>(&packed, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0xAB, 1, 1, 1, 0xFF]);
}
#[test]
fn copy_alpha_ya_u16_preserves_native_u16() {
let packed = as_le_u16(&[0x1234, 0xABCD, 0x5678, 0x9ABC]);
let mut rgba = std::vec![1u16; 8];
copy_alpha_ya_u16::<false>(&packed, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0xABCD, 1, 1, 1, 0x9ABC]);
}
#[test]
fn copy_alpha_ya_u16_to_u8_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![0x1234, 0xABCD, 0x5678, 0xFF00, 0x0001, 0x00FF];
let packed_le = as_le_u16(&intended);
let packed_be = as_be_u16(&intended);
let mut rgba_le = std::vec![1u8; 12];
let mut rgba_be = std::vec![1u8; 12];
copy_alpha_ya_u16_to_u8::<false>(&packed_le, &mut rgba_le, 3);
copy_alpha_ya_u16_to_u8::<true>(&packed_be, &mut rgba_be, 3);
let expected = ref_copy_alpha_ya_u16_to_u8(&intended, 1, 3);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_ya_u16_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![0x1234, 0xABCD, 0x5678, 0x9ABC, 0x0001, 0x00FF];
let packed_le = as_le_u16(&intended);
let packed_be = as_be_u16(&intended);
let mut rgba_le = std::vec![7u16; 12];
let mut rgba_be = std::vec![7u16; 12];
copy_alpha_ya_u16::<false>(&packed_le, &mut rgba_le, 3);
copy_alpha_ya_u16::<true>(&packed_be, &mut rgba_be, 3);
let expected = ref_copy_alpha_ya_u16(&intended, 7, 3);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_plane_f32_to_u8_clamps_and_scales() {
let alpha = as_le_f32(&[0.0f32, 0.5, 1.0, 1.5, -0.1]);
let mut rgba = vec![1u8; 20];
copy_alpha_plane_f32_to_u8::<false>(&alpha, &mut rgba, 5);
assert_eq!(rgba[3], 0, "alpha[0]=0.0 → 0");
assert_eq!(rgba[7], 128, "alpha[1]=0.5 → 128");
assert_eq!(rgba[11], 255, "alpha[2]=1.0 → 255");
assert_eq!(rgba[15], 255, "alpha[3]=1.5 → clamped to 255");
assert_eq!(rgba[19], 0, "alpha[4]=-0.1 → clamped to 0");
assert_eq!(rgba[0], 1);
assert_eq!(rgba[1], 1);
assert_eq!(rgba[2], 1);
}
#[test]
fn copy_alpha_plane_f32_to_u16_clamps_and_scales() {
let alpha = as_le_f32(&[0.0f32, 0.5, 1.0, 1.5, -0.1]);
let mut rgba = vec![1u16; 20];
copy_alpha_plane_f32_to_u16::<false>(&alpha, &mut rgba, 5);
assert_eq!(rgba[3], 0, "alpha[0]=0.0 → 0");
assert_eq!(rgba[7], 32768, "alpha[1]=0.5 → 32768");
assert_eq!(rgba[11], 65535, "alpha[2]=1.0 → 65535");
assert_eq!(rgba[15], 65535, "alpha[3]=1.5 → clamped to 65535");
assert_eq!(rgba[19], 0, "alpha[4]=-0.1 → clamped to 0");
assert_eq!(rgba[0], 1);
assert_eq!(rgba[1], 1);
assert_eq!(rgba[2], 1);
}
#[test]
fn copy_alpha_plane_f32_lossless_passthrough() {
let alpha = as_le_f32(&[2.5f32, f32::NAN, f32::INFINITY, -1.0]);
let mut rgba = vec![0.0f32; 16];
copy_alpha_plane_f32::<false>(&alpha, &mut rgba, 4);
assert_eq!(rgba[3], 2.5, "HDR 2.5 preserved");
assert!(rgba[7].is_nan(), "NaN preserved");
assert!(rgba[11].is_infinite() && rgba[11] > 0.0, "+Inf preserved");
assert_eq!(rgba[15], -1.0, "negative preserved");
assert_eq!(rgba[0], 0.0);
assert_eq!(rgba[1], 0.0);
assert_eq!(rgba[2], 0.0);
}
#[test]
fn copy_alpha_plane_f32_to_u8_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<f32> = std::vec![0.0f32, 0.25, 0.5, 0.75, 1.0, 1.5, -0.1, 0.123];
let alpha_le = as_le_f32(&intended);
let alpha_be = as_be_f32(&intended);
let mut rgba_le = std::vec![1u8; 32];
let mut rgba_be = std::vec![1u8; 32];
copy_alpha_plane_f32_to_u8::<false>(&alpha_le, &mut rgba_le, 8);
copy_alpha_plane_f32_to_u8::<true>(&alpha_be, &mut rgba_be, 8);
let expected = ref_copy_alpha_plane_f32_to_u8(&intended, 1, 8);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_plane_f32_to_u16_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<f32> = std::vec![0.0f32, 0.25, 0.5, 0.75, 1.0, 1.5, -0.1, 0.123];
let alpha_le = as_le_f32(&intended);
let alpha_be = as_be_f32(&intended);
let mut rgba_le = std::vec![7u16; 32];
let mut rgba_be = std::vec![7u16; 32];
copy_alpha_plane_f32_to_u16::<false>(&alpha_le, &mut rgba_le, 8);
copy_alpha_plane_f32_to_u16::<true>(&alpha_be, &mut rgba_be, 8);
let expected = ref_copy_alpha_plane_f32_to_u16(&intended, 7, 8);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_plane_f32_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<f32> =
std::vec![0.0f32, 0.25, 0.5, 0.75, 1.0, 2.5, -1.0, f32::INFINITY];
let alpha_le = as_le_f32(&intended);
let alpha_be = as_be_f32(&intended);
let mut rgba_le = std::vec![0.0f32; 32];
let mut rgba_be = std::vec![0.0f32; 32];
copy_alpha_plane_f32::<false>(&alpha_le, &mut rgba_le, 8);
copy_alpha_plane_f32::<true>(&alpha_be, &mut rgba_be, 8);
let bits_le: std::vec::Vec<u32> = rgba_le.iter().map(|v| v.to_bits()).collect();
let bits_be: std::vec::Vec<u32> = rgba_be.iter().map(|v| v.to_bits()).collect();
let mut expected_bits = std::vec![0u32; 32];
for (n, v) in intended.iter().enumerate() {
expected_bits[n * 4 + 3] = v.to_bits();
}
assert_eq!(
bits_le, expected_bits,
"LE path must match scalar reference"
);
assert_eq!(
bits_be, expected_bits,
"BE path must match scalar reference"
);
assert_eq!(bits_le, bits_be, "BE and LE outputs must agree bit-for-bit");
}
#[test]
fn copy_alpha_packed_u16x4_to_u8_at_3_narrows_correctly() {
let packed = as_le_u16(&[100, 200, 300, 0xABFF, 101, 201, 301, 0x1234]);
let mut rgba = std::vec![1u8; 8];
copy_alpha_packed_u16x4_to_u8_at_3::<false>(&packed, &mut rgba, 2);
assert_eq!(rgba, std::vec![1, 1, 1, 0xAB, 1, 1, 1, 0x12]);
}
#[test]
fn copy_alpha_packed_u16x4_at_3_copies_verbatim() {
let packed = as_le_u16(&[100, 200, 300, 0xABFF, 101, 201, 301, 0x1234]);
let mut rgba_u16 = std::vec![1u16; 8];
copy_alpha_packed_u16x4_at_3::<false>(&packed, &mut rgba_u16, 2);
assert_eq!(rgba_u16, std::vec![1, 1, 1, 0xABFF, 1, 1, 1, 0x1234]);
}
#[test]
fn copy_alpha_packed_u16x4_to_u8_at_3_touches_only_alpha_slot() {
let packed = as_le_u16(&[0, 0, 0, 0xFFFF]);
let mut rgba = std::vec![42u8; 4];
copy_alpha_packed_u16x4_to_u8_at_3::<false>(&packed, &mut rgba, 1);
assert_eq!(rgba[..3], [42, 42, 42]);
assert_eq!(rgba[3], 0xFF);
}
#[test]
fn copy_alpha_packed_u16x4_at_3_touches_only_alpha_slot() {
let packed = as_le_u16(&[0, 0, 0, 0xBEEF]);
let mut rgba_u16 = std::vec![99u16; 4];
copy_alpha_packed_u16x4_at_3::<false>(&packed, &mut rgba_u16, 1);
assert_eq!(rgba_u16[..3], [99, 99, 99]);
assert_eq!(rgba_u16[3], 0xBEEF);
}
#[test]
fn copy_alpha_packed_u16x4_to_u8_at_3_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![100, 200, 300, 0xABFF, 101, 201, 301, 0x1234];
let packed_le = as_le_u16(&intended);
let packed_be = as_be_u16(&intended);
let mut rgba_le = std::vec![1u8; 8];
let mut rgba_be = std::vec![1u8; 8];
copy_alpha_packed_u16x4_to_u8_at_3::<false>(&packed_le, &mut rgba_le, 2);
copy_alpha_packed_u16x4_to_u8_at_3::<true>(&packed_be, &mut rgba_be, 2);
let expected = ref_copy_alpha_packed_u16x4_to_u8_at_3(&intended, 1, 2);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
#[test]
fn copy_alpha_packed_u16x4_at_3_be_parity_with_swapped_buffer() {
let intended: std::vec::Vec<u16> = std::vec![100, 200, 300, 0xABFF, 101, 201, 301, 0x1234];
let packed_le = as_le_u16(&intended);
let packed_be = as_be_u16(&intended);
let mut rgba_le = std::vec![7u16; 8];
let mut rgba_be = std::vec![7u16; 8];
copy_alpha_packed_u16x4_at_3::<false>(&packed_le, &mut rgba_le, 2);
copy_alpha_packed_u16x4_at_3::<true>(&packed_be, &mut rgba_be, 2);
let expected = ref_copy_alpha_packed_u16x4_at_3(&intended, 7, 2);
assert_eq!(rgba_le, expected, "LE path must match scalar reference");
assert_eq!(rgba_be, expected, "BE path must match scalar reference");
assert_eq!(rgba_le, rgba_be, "BE and LE outputs must agree");
}
}