pub fn split16_pack(counts: &[u16], rgb: &mut [u8]) {
assert_eq!(rgb.len(), counts.len() * 3, "rgb buffer must be counts.len() * 3");
for (c, px) in counts.iter().zip(rgb.chunks_exact_mut(3)) {
px[0] = (c >> 8) as u8;
px[1] = (c & 0xff) as u8;
px[2] = 0;
}
}
pub fn split16_unpack(rgb: &[u8], counts: &mut [u16]) {
assert_eq!(rgb.len(), counts.len() * 3, "rgb buffer must be counts.len() * 3");
for (c, px) in counts.iter_mut().zip(rgb.chunks_exact(3)) {
*c = ((px[0] as u16) << 8) | px[1] as u16;
}
}
pub fn split16_pack_vec(counts: &[u16]) -> Vec<u8> {
let mut rgb = vec![0u8; counts.len() * 3];
split16_pack(counts, &mut rgb);
rgb
}
pub fn split16_unpack_vec(rgb: &[u8]) -> Vec<u16> {
let mut counts = vec![0u16; rgb.len() / 3];
split16_unpack(&rgb[..counts.len() * 3], &mut counts);
counts
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn exhaustive_u16_roundtrip() {
let counts: Vec<u16> = (0..=u16::MAX).collect();
let rgb = split16_pack_vec(&counts);
for (i, px) in rgb.chunks_exact(3).enumerate() {
assert_eq!(px[2], 0, "B channel must be zero at {i}");
}
let back = split16_unpack_vec(&rgb);
assert_eq!(back, counts);
}
#[test]
fn known_packing() {
let rgb = split16_pack_vec(&[1000, 65535, 0]);
assert_eq!(&rgb[0..3], &[0x03, 0xE8, 0x00]);
assert_eq!(&rgb[3..6], &[0xFF, 0xFF, 0x00]);
assert_eq!(&rgb[6..9], &[0x00, 0x00, 0x00]);
}
}