use super::*;
fn solid_frame_le16(width: u32, height: u32, pixel: u16) -> std::vec::Vec<u8> {
let px = pixel.to_le_bytes();
let n = width as usize * height as usize;
let mut buf = std::vec::Vec::with_capacity(n * 2);
for _ in 0..n {
buf.extend_from_slice(&px);
}
buf
}
fn random_legacy_frame(width: u32, height: u32, seed: u32, mask: u16) -> std::vec::Vec<u8> {
let n = width as usize * height as usize;
let mut buf = std::vec![0u8; n * 2];
let mut state = seed;
for chunk in buf.chunks_mut(2) {
state = state.wrapping_mul(1_664_525).wrapping_add(1_013_904_223);
let word = ((state >> 8) as u16) & mask;
chunk.copy_from_slice(&word.to_le_bytes());
}
buf
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_simd_matches_scalar() {
let w = 1921usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xDEAD_BEEF, 0xFFFF);
let src = Rgb565Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut rgba_simd = std::vec![0u8; w * h * 4];
let mut rgba_scalar = std::vec![0u8; w * h * 4];
let mut rgb_u16_simd = std::vec![0u16; w * h * 3];
let mut rgb_u16_scalar = std::vec![0u16; w * h * 3];
let mut rgba_u16_simd = std::vec![0u16; w * h * 4];
let mut rgba_u16_scalar = std::vec![0u16; w * h * 4];
let mut luma_simd = std::vec![0u8; w * h];
let mut luma_scalar = std::vec![0u8; w * h];
let mut s = MixedSinker::<Rgb565>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap()
.with_rgba(&mut rgba_simd)
.unwrap()
.with_rgb_u16(&mut rgb_u16_simd)
.unwrap()
.with_rgba_u16(&mut rgba_u16_simd)
.unwrap()
.with_luma(&mut luma_simd)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let mut s2 = MixedSinker::<Rgb565>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_rgba(&mut rgba_scalar)
.unwrap()
.with_rgb_u16(&mut rgb_u16_scalar)
.unwrap()
.with_rgba_u16(&mut rgba_u16_scalar)
.unwrap()
.with_luma(&mut luma_scalar)
.unwrap();
s2.set_simd(false);
rgb565_to(&src, true, ColorMatrix::Bt709, &mut s2).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "RGB565 rgb output diverges");
assert_eq!(rgba_simd, rgba_scalar, "RGB565 rgba output diverges");
assert_eq!(
rgb_u16_simd, rgb_u16_scalar,
"RGB565 rgb_u16 output diverges"
);
assert_eq!(
rgba_u16_simd, rgba_u16_scalar,
"RGB565 rgba_u16 output diverges"
);
assert_eq!(luma_simd, luma_scalar, "RGB565 luma output diverges");
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr565_simd_matches_scalar() {
let w = 1921usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xCAFE_BABE, 0xFFFF);
let src = Bgr565Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut rgba_simd = std::vec![0u8; w * h * 4];
let mut rgba_scalar = std::vec![0u8; w * h * 4];
let mut rgb_u16_simd = std::vec![0u16; w * h * 3];
let mut rgb_u16_scalar = std::vec![0u16; w * h * 3];
let mut s = MixedSinker::<Bgr565>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap()
.with_rgba(&mut rgba_simd)
.unwrap()
.with_rgb_u16(&mut rgb_u16_simd)
.unwrap();
bgr565_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let mut s2 = MixedSinker::<Bgr565>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_rgba(&mut rgba_scalar)
.unwrap()
.with_rgb_u16(&mut rgb_u16_scalar)
.unwrap();
s2.set_simd(false);
bgr565_to(&src, true, ColorMatrix::Bt709, &mut s2).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "BGR565 rgb output diverges");
assert_eq!(rgba_simd, rgba_scalar, "BGR565 rgba output diverges");
assert_eq!(
rgb_u16_simd, rgb_u16_scalar,
"BGR565 rgb_u16 output diverges"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_simd_matches_scalar() {
let w = 1921usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xABCD_1234, 0x7FFF);
let src = Rgb555Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut rgba_simd = std::vec![0u8; w * h * 4];
let mut rgba_scalar = std::vec![0u8; w * h * 4];
let mut rgb_u16_simd = std::vec![0u16; w * h * 3];
let mut rgb_u16_scalar = std::vec![0u16; w * h * 3];
let mut s = MixedSinker::<Rgb555>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap()
.with_rgba(&mut rgba_simd)
.unwrap()
.with_rgb_u16(&mut rgb_u16_simd)
.unwrap();
rgb555_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let mut s2 = MixedSinker::<Rgb555>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_rgba(&mut rgba_scalar)
.unwrap()
.with_rgb_u16(&mut rgb_u16_scalar)
.unwrap();
s2.set_simd(false);
rgb555_to(&src, true, ColorMatrix::Bt709, &mut s2).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "RGB555 rgb output diverges");
assert_eq!(rgba_simd, rgba_scalar, "RGB555 rgba output diverges");
assert_eq!(
rgb_u16_simd, rgb_u16_scalar,
"RGB555 rgb_u16 output diverges"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr555_simd_matches_scalar() {
let w = 1921usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0x1357_2468, 0x7FFF);
let src = Bgr555Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut rgba_simd = std::vec![0u8; w * h * 4];
let mut rgba_scalar = std::vec![0u8; w * h * 4];
let mut s = MixedSinker::<Bgr555>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap()
.with_rgba(&mut rgba_simd)
.unwrap();
bgr555_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let mut s2 = MixedSinker::<Bgr555>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_rgba(&mut rgba_scalar)
.unwrap();
s2.set_simd(false);
bgr555_to(&src, true, ColorMatrix::Bt709, &mut s2).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "BGR555 rgb output diverges");
assert_eq!(rgba_simd, rgba_scalar, "BGR555 rgba output diverges");
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_simd_matches_scalar() {
let w = 1921usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xFEDC_BA98, 0x0FFF);
let src = Rgb444Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut rgba_simd = std::vec![0u8; w * h * 4];
let mut rgba_scalar = std::vec![0u8; w * h * 4];
let mut rgb_u16_simd = std::vec![0u16; w * h * 3];
let mut rgb_u16_scalar = std::vec![0u16; w * h * 3];
let mut s = MixedSinker::<Rgb444>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap()
.with_rgba(&mut rgba_simd)
.unwrap()
.with_rgb_u16(&mut rgb_u16_simd)
.unwrap();
rgb444_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let mut s2 = MixedSinker::<Rgb444>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_rgba(&mut rgba_scalar)
.unwrap()
.with_rgb_u16(&mut rgb_u16_scalar)
.unwrap();
s2.set_simd(false);
rgb444_to(&src, true, ColorMatrix::Bt709, &mut s2).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "RGB444 rgb output diverges");
assert_eq!(rgba_simd, rgba_scalar, "RGB444 rgba output diverges");
assert_eq!(
rgb_u16_simd, rgb_u16_scalar,
"RGB444 rgb_u16 output diverges"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr444_simd_matches_scalar() {
let w = 1921usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0x0123_4567, 0x0FFF);
let src = Bgr444Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut rgb_simd = std::vec![0u8; w * h * 3];
let mut rgb_scalar = std::vec![0u8; w * h * 3];
let mut rgba_simd = std::vec![0u8; w * h * 4];
let mut rgba_scalar = std::vec![0u8; w * h * 4];
let mut s = MixedSinker::<Bgr444>::new(w, h)
.with_rgb(&mut rgb_simd)
.unwrap()
.with_rgba(&mut rgba_simd)
.unwrap();
bgr444_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let mut s2 = MixedSinker::<Bgr444>::new(w, h)
.with_rgb(&mut rgb_scalar)
.unwrap()
.with_rgba(&mut rgba_scalar)
.unwrap();
s2.set_simd(false);
bgr444_to(&src, true, ColorMatrix::Bt709, &mut s2).unwrap();
assert_eq!(rgb_simd, rgb_scalar, "BGR444 rgb output diverges");
assert_eq!(rgba_simd, rgba_scalar, "BGR444 rgba output diverges");
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_rgba_forces_alpha_ff() {
let pix = solid_frame_le16(8, 2, 0x07E0);
let src = Rgb565Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_out = std::vec![0u8; 8 * 2 * 4];
let mut sink = MixedSinker::<Rgb565>::new(8, 2)
.with_rgba(&mut rgba_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_out.chunks(4) {
assert_eq!(px[3], 0xFF, "RGB565 RGBA alpha not 0xFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr565_rgba_forces_alpha_ff() {
let pix = solid_frame_le16(8, 2, 0x07E0);
let src = Bgr565Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_out = std::vec![0u8; 8 * 2 * 4];
let mut sink = MixedSinker::<Bgr565>::new(8, 2)
.with_rgba(&mut rgba_out)
.unwrap();
bgr565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_out.chunks(4) {
assert_eq!(px[3], 0xFF, "BGR565 RGBA alpha not 0xFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_rgba_forces_alpha_ff() {
let pix = solid_frame_le16(8, 2, 0x7FFF);
let src = Rgb555Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_out = std::vec![0u8; 8 * 2 * 4];
let mut sink = MixedSinker::<Rgb555>::new(8, 2)
.with_rgba(&mut rgba_out)
.unwrap();
rgb555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_out.chunks(4) {
assert_eq!(px[3], 0xFF, "RGB555 RGBA alpha not 0xFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr555_rgba_forces_alpha_ff() {
let pix = solid_frame_le16(8, 2, 0x7FFF);
let src = Bgr555Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_out = std::vec![0u8; 8 * 2 * 4];
let mut sink = MixedSinker::<Bgr555>::new(8, 2)
.with_rgba(&mut rgba_out)
.unwrap();
bgr555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_out.chunks(4) {
assert_eq!(px[3], 0xFF, "BGR555 RGBA alpha not 0xFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_rgba_forces_alpha_ff() {
let pix = solid_frame_le16(8, 2, 0x0FFF);
let src = Rgb444Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_out = std::vec![0u8; 8 * 2 * 4];
let mut sink = MixedSinker::<Rgb444>::new(8, 2)
.with_rgba(&mut rgba_out)
.unwrap();
rgb444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_out.chunks(4) {
assert_eq!(px[3], 0xFF, "RGB444 RGBA alpha not 0xFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr444_rgba_forces_alpha_ff() {
let pix = solid_frame_le16(8, 2, 0x0FFF);
let src = Bgr444Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_out = std::vec![0u8; 8 * 2 * 4];
let mut sink = MixedSinker::<Bgr444>::new(8, 2)
.with_rgba(&mut rgba_out)
.unwrap();
bgr444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_out.chunks(4) {
assert_eq!(px[3], 0xFF, "BGR444 RGBA alpha not 0xFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_rgba_u16_forces_alpha_ffff() {
let pix = solid_frame_le16(8, 2, 0xF800); let src = Rgb565Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_u16_out = std::vec![0u16; 8 * 2 * 4];
let mut sink = MixedSinker::<Rgb565>::new(8, 2)
.with_rgba_u16(&mut rgba_u16_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_u16_out.chunks(4) {
assert_eq!(px[3], 0xFFFF, "RGB565 RGBA u16 alpha not 0xFFFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_rgba_u16_forces_alpha_ffff() {
let pix = solid_frame_le16(8, 2, 0x7C00); let src = Rgb555Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_u16_out = std::vec![0u16; 8 * 2 * 4];
let mut sink = MixedSinker::<Rgb555>::new(8, 2)
.with_rgba_u16(&mut rgba_u16_out)
.unwrap();
rgb555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_u16_out.chunks(4) {
assert_eq!(px[3], 0xFFFF, "RGB555 RGBA u16 alpha not 0xFFFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_rgba_u16_forces_alpha_ffff() {
let pix = solid_frame_le16(8, 2, 0x0F00); let src = Rgb444Frame::try_new(&pix, 8, 2, 16).unwrap();
let mut rgba_u16_out = std::vec![0u16; 8 * 2 * 4];
let mut sink = MixedSinker::<Rgb444>::new(8, 2)
.with_rgba_u16(&mut rgba_u16_out)
.unwrap();
rgb444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgba_u16_out.chunks(4) {
assert_eq!(px[3], 0xFFFF, "RGB444 RGBA u16 alpha not 0xFFFF");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_u16_native_precision_max() {
let pix = solid_frame_le16(16, 4, 0xFFFF);
let src = Rgb565Frame::try_new(&pix, 16, 4, 32).unwrap();
let mut rgb_u16_out = std::vec![0u16; 16 * 4 * 3];
let mut sink = MixedSinker::<Rgb565>::new(16, 4)
.with_rgb_u16(&mut rgb_u16_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_u16_out.chunks(3) {
assert_eq!(px, [31, 63, 31], "RGB565 u16 max pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_u16_native_precision_max() {
let pix = solid_frame_le16(16, 4, 0x7FFF);
let src = Rgb555Frame::try_new(&pix, 16, 4, 32).unwrap();
let mut rgb_u16_out = std::vec![0u16; 16 * 4 * 3];
let mut sink = MixedSinker::<Rgb555>::new(16, 4)
.with_rgb_u16(&mut rgb_u16_out)
.unwrap();
rgb555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_u16_out.chunks(3) {
assert_eq!(px, [31, 31, 31], "RGB555 u16 max pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_u16_native_precision_max() {
let pix = solid_frame_le16(16, 4, 0x0FFF);
let src = Rgb444Frame::try_new(&pix, 16, 4, 32).unwrap();
let mut rgb_u16_out = std::vec![0u16; 16 * 4 * 3];
let mut sink = MixedSinker::<Rgb444>::new(16, 4)
.with_rgb_u16(&mut rgb_u16_out)
.unwrap();
rgb444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_u16_out.chunks(3) {
assert_eq!(px, [15, 15, 15], "RGB444 u16 max pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_known_pixel_pure_green() {
let pix = solid_frame_le16(16, 1, 0x07E0);
let src = Rgb565Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Rgb565>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [0, 255, 0], "RGB565 pure green pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_known_pixel_pure_red() {
let pix = solid_frame_le16(16, 1, 0xF800);
let src = Rgb565Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Rgb565>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 0, 0], "RGB565 pure red pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_known_pixel_all_zeros() {
let pix = solid_frame_le16(16, 1, 0x0000);
let src = Rgb565Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Rgb565>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [0, 0, 0], "RGB565 all-zeros pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_known_pixel_all_ones_expands_to_255() {
let pix = solid_frame_le16(16, 1, 0xFFFF);
let src = Rgb565Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Rgb565>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 255, 255], "RGB565 all-ones pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_known_pixel_all_ones_expands_to_255() {
let pix = solid_frame_le16(16, 1, 0x7FFF);
let src = Rgb555Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Rgb555>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 255, 255], "RGB555 all-ones pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_known_pixel_all_ones_expands_to_255() {
let pix = solid_frame_le16(16, 1, 0x0FFF);
let src = Rgb444Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Rgb444>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 255, 255], "RGB444 all-ones pixel wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr565_channel_order_r_in_low_bits() {
let pix = solid_frame_le16(16, 1, 0x001F); let src = Bgr565Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Bgr565>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
bgr565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 0, 0], "BGR565 R-channel order wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr555_channel_order_r_in_low_bits() {
let pix = solid_frame_le16(16, 1, 0x001F);
let src = Bgr555Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Bgr555>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
bgr555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 0, 0], "BGR555 R-channel order wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr444_channel_order_r_in_low_bits() {
let pix = solid_frame_le16(16, 1, 0x000F);
let src = Bgr444Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut rgb_out = std::vec![0u8; 16 * 3];
let mut sink = MixedSinker::<Bgr444>::new(16, 1)
.with_rgb(&mut rgb_out)
.unwrap();
bgr444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for px in rgb_out.chunks(3) {
assert_eq!(px, [255, 0, 0], "BGR444 R-channel order wrong");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_luma_u16_matches_luma_u8_zero_extended() {
let w = 64usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xBEEF_FEED, 0xFFFF);
let src = Rgb565Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut luma_u8 = std::vec![0u8; w * h];
let mut luma_u16 = std::vec![0u16; w * h];
let mut s = MixedSinker::<Rgb565>::new(w, h)
.with_luma(&mut luma_u8)
.unwrap()
.with_luma_u16(&mut luma_u16)
.unwrap();
s.set_simd(false);
rgb565_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let expected: std::vec::Vec<u16> = luma_u8.iter().map(|&y| y as u16).collect();
assert_eq!(
luma_u16, expected,
"RGB565 luma_u16 not zero-extended u8 luma"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn bgr565_luma_u16_matches_luma_u8_zero_extended() {
let w = 64usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xF00D_CAFE, 0xFFFF);
let src = Bgr565Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut luma_u8 = std::vec![0u8; w * h];
let mut luma_u16 = std::vec![0u16; w * h];
let mut s = MixedSinker::<Bgr565>::new(w, h)
.with_luma(&mut luma_u8)
.unwrap()
.with_luma_u16(&mut luma_u16)
.unwrap();
s.set_simd(false);
bgr565_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let expected: std::vec::Vec<u16> = luma_u8.iter().map(|&y| y as u16).collect();
assert_eq!(
luma_u16, expected,
"BGR565 luma_u16 not zero-extended u8 luma"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_luma_u16_matches_luma_u8_zero_extended() {
let w = 64usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0xA1B2_C3D4, 0x0FFF);
let src = Rgb444Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut luma_u8 = std::vec![0u8; w * h];
let mut luma_u16 = std::vec![0u16; w * h];
let mut s = MixedSinker::<Rgb444>::new(w, h)
.with_luma(&mut luma_u8)
.unwrap()
.with_luma_u16(&mut luma_u16)
.unwrap();
s.set_simd(false);
rgb444_to(&src, true, ColorMatrix::Bt709, &mut s).unwrap();
let expected: std::vec::Vec<u16> = luma_u8.iter().map(|&y| y as u16).collect();
assert_eq!(
luma_u16, expected,
"RGB444 luma_u16 not zero-extended u8 luma"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_luma_u16_in_u8_range() {
let w = 128usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0x1234_5678, 0xFFFF);
let src = Rgb565Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut luma_u16 = std::vec![0u16; w * h];
let mut sink = MixedSinker::<Rgb565>::new(w, h)
.with_luma_u16(&mut luma_u16)
.unwrap();
sink.set_simd(false);
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
assert!(
luma_u16.iter().all(|&y| y <= 255),
"RGB565 luma_u16 out of [0,255] range"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_luma_u16_in_u8_range() {
let w = 128usize;
let h = 4usize;
let pix = random_legacy_frame(w as u32, h as u32, 0x8765_4321, 0x7FFF);
let src = Rgb555Frame::try_new(&pix, w as u32, h as u32, (w * 2) as u32).unwrap();
let mut luma_u16 = std::vec![0u16; w * h];
let mut sink = MixedSinker::<Rgb555>::new(w, h)
.with_luma_u16(&mut luma_u16)
.unwrap();
sink.set_simd(false);
rgb555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
assert!(
luma_u16.iter().all(|&y| y <= 255),
"RGB555 luma_u16 out of [0,255] range"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_hsv_pure_red_hue_near_zero() {
let pix = solid_frame_le16(16, 1, 0xF800); let src = Rgb565Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut h = std::vec![0u8; 16];
let mut s = std::vec![0u8; 16];
let mut v = std::vec![0u8; 16];
let mut sink = MixedSinker::<Rgb565>::new(16, 1)
.with_hsv(&mut h, &mut s, &mut v)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
for (&hh, (&ss, &vv)) in h.iter().zip(s.iter().zip(v.iter())) {
assert_eq!(hh, 0, "RGB565 red hue not 0");
assert_eq!(ss, 255, "RGB565 red saturation not 255");
assert_eq!(vv, 255, "RGB565 red value not 255");
}
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb555_hsv_pure_blue_hue() {
let pix = solid_frame_le16(16, 1, 0x001F);
let src = Rgb555Frame::try_new(&pix, 16, 1, 32).unwrap();
let mut hh = std::vec![0u8; 16];
let mut ss = std::vec![0u8; 16];
let mut vv = std::vec![0u8; 16];
let mut sink = MixedSinker::<Rgb555>::new(16, 1)
.with_hsv(&mut hh, &mut ss, &mut vv)
.unwrap();
sink.set_simd(false);
rgb555_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
assert!(
ss.iter().all(|&s| s == 255),
"RGB555 blue saturation not 255"
);
assert!(vv.iter().all(|&v| v == 255), "RGB555 blue value not 255");
assert!(
hh.windows(2).all(|w| w[0] == w[1]),
"RGB555 blue hue inconsistent"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb565_width_one_round_trip() {
let pix = solid_frame_le16(1, 1, 0x07E0);
let src = Rgb565Frame::try_new(&pix, 1, 1, 2).unwrap();
let mut rgb_out = std::vec![0u8; 3];
let mut rgba_out = std::vec![0u8; 4];
let mut sink = MixedSinker::<Rgb565>::new(1, 1)
.with_rgb(&mut rgb_out)
.unwrap()
.with_rgba(&mut rgba_out)
.unwrap();
rgb565_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
assert_eq!(
rgb_out.as_slice(),
[0u8, 255, 0],
"RGB565 width=1 RGB wrong"
);
assert_eq!(
rgba_out.as_slice(),
[0u8, 255, 0, 0xFF],
"RGB565 width=1 RGBA wrong"
);
}
#[test]
#[cfg_attr(
miri,
ignore = "SIMD-dispatched row kernels use intrinsics unsupported by Miri"
)]
fn rgb444_width_one_round_trip() {
let pix = solid_frame_le16(1, 1, 0x0F00);
let src = Rgb444Frame::try_new(&pix, 1, 1, 2).unwrap();
let mut rgb_out = std::vec![0u8; 3];
let mut sink = MixedSinker::<Rgb444>::new(1, 1)
.with_rgb(&mut rgb_out)
.unwrap();
rgb444_to(&src, true, ColorMatrix::Bt709, &mut sink).unwrap();
assert_eq!(
rgb_out.as_slice(),
[255u8, 0, 0],
"RGB444 width=1 RGB wrong"
);
}
#[test]
fn rgb565_rgba_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u8; 3]; let result = MixedSinker::<Rgb565>::new(4, 1).with_rgba(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientRgbaBuffer(_))),
"Expected InsufficientRgbaBuffer"
);
}
#[test]
fn rgb565_rgb_u16_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u16; 1]; let result = MixedSinker::<Rgb565>::new(4, 1).with_rgb_u16(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientRgbU16Buffer(_))),
"Expected InsufficientRgbU16Buffer"
);
}
#[test]
fn rgb565_rgba_u16_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u16; 1]; let result = MixedSinker::<Rgb565>::new(4, 1).with_rgba_u16(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientRgbaU16Buffer(_))),
"Expected InsufficientRgbaU16Buffer"
);
}
#[test]
fn rgb565_luma_u16_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u16; 0]; let result = MixedSinker::<Rgb565>::new(4, 1).with_luma_u16(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientLumaU16Buffer(_))),
"Expected InsufficientLumaU16Buffer"
);
}
#[test]
fn bgr565_rgba_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u8; 3];
let result = MixedSinker::<Bgr565>::new(4, 1).with_rgba(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientRgbaBuffer(_))),
"Expected InsufficientRgbaBuffer"
);
}
#[test]
fn rgb555_rgba_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u8; 3];
let result = MixedSinker::<Rgb555>::new(4, 1).with_rgba(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientRgbaBuffer(_))),
"Expected InsufficientRgbaBuffer"
);
}
#[test]
fn bgr444_rgba_buffer_too_short_returns_error() {
let mut too_short = std::vec![0u8; 3];
let result = MixedSinker::<Bgr444>::new(4, 1).with_rgba(&mut too_short);
assert!(
matches!(result, Err(MixedSinkerError::InsufficientRgbaBuffer(_))),
"Expected InsufficientRgbaBuffer"
);
}