#![allow(dead_code)]
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb565_to_rgb_row(src: &[u8], rgb_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r5 = ((px >> 11) & 0x1F) as u8;
let g6 = ((px >> 5) & 0x3F) as u8;
let b5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g6 << 2) | (g6 >> 4);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 3;
rgb_out[dst] = r;
rgb_out[dst + 1] = g;
rgb_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb565_to_rgba_row(src: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r5 = ((px >> 11) & 0x1F) as u8;
let g6 = ((px >> 5) & 0x3F) as u8;
let b5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g6 << 2) | (g6 >> 4);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 4;
rgba_out[dst] = r;
rgba_out[dst + 1] = g;
rgba_out[dst + 2] = b;
rgba_out[dst + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb565_to_rgb_u16_row(src: &[u8], rgb_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r = (px >> 11) & 0x1F;
let g = (px >> 5) & 0x3F;
let b = px & 0x1F;
let dst = x * 3;
rgb_u16_out[dst] = r;
rgb_u16_out[dst + 1] = g;
rgb_u16_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb565_to_rgba_u16_row(src: &[u8], rgba_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r = (px >> 11) & 0x1F;
let g = (px >> 5) & 0x3F;
let b = px & 0x1F;
let dst = x * 4;
rgba_u16_out[dst] = r;
rgba_u16_out[dst + 1] = g;
rgba_u16_out[dst + 2] = b;
rgba_u16_out[dst + 3] = 0xFFFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr565_to_rgb_row(src: &[u8], rgb_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b5 = ((px >> 11) & 0x1F) as u8;
let g6 = ((px >> 5) & 0x3F) as u8;
let r5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g6 << 2) | (g6 >> 4);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 3;
rgb_out[dst] = r;
rgb_out[dst + 1] = g;
rgb_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr565_to_rgba_row(src: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b5 = ((px >> 11) & 0x1F) as u8;
let g6 = ((px >> 5) & 0x3F) as u8;
let r5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g6 << 2) | (g6 >> 4);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 4;
rgba_out[dst] = r;
rgba_out[dst + 1] = g;
rgba_out[dst + 2] = b;
rgba_out[dst + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr565_to_rgb_u16_row(src: &[u8], rgb_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b = (px >> 11) & 0x1F;
let g = (px >> 5) & 0x3F;
let r = px & 0x1F;
let dst = x * 3;
rgb_u16_out[dst] = r;
rgb_u16_out[dst + 1] = g;
rgb_u16_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr565_to_rgba_u16_row(src: &[u8], rgba_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b = (px >> 11) & 0x1F;
let g = (px >> 5) & 0x3F;
let r = px & 0x1F;
let dst = x * 4;
rgba_u16_out[dst] = r;
rgba_u16_out[dst + 1] = g;
rgba_u16_out[dst + 2] = b;
rgba_u16_out[dst + 3] = 0xFFFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb555_to_rgb_row(src: &[u8], rgb_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r5 = ((px >> 10) & 0x1F) as u8;
let g5 = ((px >> 5) & 0x1F) as u8;
let b5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g5 << 3) | (g5 >> 2);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 3;
rgb_out[dst] = r;
rgb_out[dst + 1] = g;
rgb_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb555_to_rgba_row(src: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r5 = ((px >> 10) & 0x1F) as u8;
let g5 = ((px >> 5) & 0x1F) as u8;
let b5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g5 << 3) | (g5 >> 2);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 4;
rgba_out[dst] = r;
rgba_out[dst + 1] = g;
rgba_out[dst + 2] = b;
rgba_out[dst + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb555_to_rgb_u16_row(src: &[u8], rgb_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r = (px >> 10) & 0x1F;
let g = (px >> 5) & 0x1F;
let b = px & 0x1F;
let dst = x * 3;
rgb_u16_out[dst] = r;
rgb_u16_out[dst + 1] = g;
rgb_u16_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb555_to_rgba_u16_row(src: &[u8], rgba_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r = (px >> 10) & 0x1F;
let g = (px >> 5) & 0x1F;
let b = px & 0x1F;
let dst = x * 4;
rgba_u16_out[dst] = r;
rgba_u16_out[dst + 1] = g;
rgba_u16_out[dst + 2] = b;
rgba_u16_out[dst + 3] = 0xFFFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr555_to_rgb_row(src: &[u8], rgb_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b5 = ((px >> 10) & 0x1F) as u8;
let g5 = ((px >> 5) & 0x1F) as u8;
let r5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g5 << 3) | (g5 >> 2);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 3;
rgb_out[dst] = r;
rgb_out[dst + 1] = g;
rgb_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr555_to_rgba_row(src: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b5 = ((px >> 10) & 0x1F) as u8;
let g5 = ((px >> 5) & 0x1F) as u8;
let r5 = (px & 0x1F) as u8;
let r = (r5 << 3) | (r5 >> 2);
let g = (g5 << 3) | (g5 >> 2);
let b = (b5 << 3) | (b5 >> 2);
let dst = x * 4;
rgba_out[dst] = r;
rgba_out[dst + 1] = g;
rgba_out[dst + 2] = b;
rgba_out[dst + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr555_to_rgb_u16_row(src: &[u8], rgb_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b = (px >> 10) & 0x1F;
let g = (px >> 5) & 0x1F;
let r = px & 0x1F;
let dst = x * 3;
rgb_u16_out[dst] = r;
rgb_u16_out[dst + 1] = g;
rgb_u16_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr555_to_rgba_u16_row(src: &[u8], rgba_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b = (px >> 10) & 0x1F;
let g = (px >> 5) & 0x1F;
let r = px & 0x1F;
let dst = x * 4;
rgba_u16_out[dst] = r;
rgba_u16_out[dst + 1] = g;
rgba_u16_out[dst + 2] = b;
rgba_u16_out[dst + 3] = 0xFFFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb444_to_rgb_row(src: &[u8], rgb_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r4 = ((px >> 8) & 0x0F) as u8;
let g4 = ((px >> 4) & 0x0F) as u8;
let b4 = (px & 0x0F) as u8;
let r = (r4 << 4) | r4;
let g = (g4 << 4) | g4;
let b = (b4 << 4) | b4;
let dst = x * 3;
rgb_out[dst] = r;
rgb_out[dst + 1] = g;
rgb_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb444_to_rgba_row(src: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r4 = ((px >> 8) & 0x0F) as u8;
let g4 = ((px >> 4) & 0x0F) as u8;
let b4 = (px & 0x0F) as u8;
let r = (r4 << 4) | r4;
let g = (g4 << 4) | g4;
let b = (b4 << 4) | b4;
let dst = x * 4;
rgba_out[dst] = r;
rgba_out[dst + 1] = g;
rgba_out[dst + 2] = b;
rgba_out[dst + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb444_to_rgb_u16_row(src: &[u8], rgb_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r = (px >> 8) & 0x0F;
let g = (px >> 4) & 0x0F;
let b = px & 0x0F;
let dst = x * 3;
rgb_u16_out[dst] = r;
rgb_u16_out[dst + 1] = g;
rgb_u16_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn rgb444_to_rgba_u16_row(src: &[u8], rgba_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let r = (px >> 8) & 0x0F;
let g = (px >> 4) & 0x0F;
let b = px & 0x0F;
let dst = x * 4;
rgba_u16_out[dst] = r;
rgba_u16_out[dst + 1] = g;
rgba_u16_out[dst + 2] = b;
rgba_u16_out[dst + 3] = 0xFFFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr444_to_rgb_row(src: &[u8], rgb_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_out.len() >= width * 3, "rgb_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b4 = ((px >> 8) & 0x0F) as u8;
let g4 = ((px >> 4) & 0x0F) as u8;
let r4 = (px & 0x0F) as u8;
let r = (r4 << 4) | r4;
let g = (g4 << 4) | g4;
let b = (b4 << 4) | b4;
let dst = x * 3;
rgb_out[dst] = r;
rgb_out[dst + 1] = g;
rgb_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr444_to_rgba_row(src: &[u8], rgba_out: &mut [u8], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_out.len() >= width * 4, "rgba_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b4 = ((px >> 8) & 0x0F) as u8;
let g4 = ((px >> 4) & 0x0F) as u8;
let r4 = (px & 0x0F) as u8;
let r = (r4 << 4) | r4;
let g = (g4 << 4) | g4;
let b = (b4 << 4) | b4;
let dst = x * 4;
rgba_out[dst] = r;
rgba_out[dst + 1] = g;
rgba_out[dst + 2] = b;
rgba_out[dst + 3] = 0xFF;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr444_to_rgb_u16_row(src: &[u8], rgb_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgb_u16_out.len() >= width * 3, "rgb_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b = (px >> 8) & 0x0F;
let g = (px >> 4) & 0x0F;
let r = px & 0x0F;
let dst = x * 3;
rgb_u16_out[dst] = r;
rgb_u16_out[dst + 1] = g;
rgb_u16_out[dst + 2] = b;
}
}
#[cfg_attr(not(tarpaulin), inline(always))]
pub(crate) fn bgr444_to_rgba_u16_row(src: &[u8], rgba_u16_out: &mut [u16], width: usize) {
debug_assert!(src.len() >= width * 2, "src row too short");
debug_assert!(rgba_u16_out.len() >= width * 4, "rgba_u16_out too short");
for x in 0..width {
let px = u16::from_le_bytes([src[x * 2], src[x * 2 + 1]]);
let b = (px >> 8) & 0x0F;
let g = (px >> 4) & 0x0F;
let r = px & 0x0F;
let dst = x * 4;
rgba_u16_out[dst] = r;
rgba_u16_out[dst + 1] = g;
rgba_u16_out[dst + 2] = b;
rgba_u16_out[dst + 3] = 0xFFFF;
}
}
#[cfg(all(test, feature = "std"))]
mod tests {
use super::*;
#[test]
fn rgb565_known_values() {
let px: u16 = 0x07E0;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
rgb565_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb[0], 0, "R should be 0");
assert_eq!(rgb[1], 255, "G should be 255");
assert_eq!(rgb[2], 0, "B should be 0");
}
#[test]
fn rgb565_all_ones() {
let px: u16 = 0xFFFF;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
rgb565_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [255, 255, 255]);
}
#[test]
fn rgb565_all_zeros() {
let src = [0u8; 2];
let mut rgb = [0xFFu8; 3];
rgb565_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [0, 0, 0]);
}
#[test]
fn rgb565_r5_expansion_boundary() {
let mut prev = 0u8;
for c in 0u8..=31 {
let expanded = (c << 3) | (c >> 2);
if c > 0 {
assert!(expanded >= prev, "5-bit expansion not monotone at c={c}");
}
prev = expanded;
}
assert_eq!(
(31u8 << 3) | (31u8 >> 2),
255,
"5-bit max should expand to 255"
);
let zero5: u8 = 0;
assert_eq!(
(zero5 << 3) | (zero5 >> 2),
0,
"5-bit zero should expand to 0"
);
}
#[test]
fn rgb565_g6_expansion_boundary() {
let mut prev = 0u8;
for c in 0u8..=63 {
let expanded = (c << 2) | (c >> 4);
if c > 0 {
assert!(expanded >= prev, "6-bit expansion not monotone at c={c}");
}
prev = expanded;
}
assert_eq!(
(63u8 << 2) | (63u8 >> 4),
255,
"6-bit max should expand to 255"
);
let zero6: u8 = 0;
assert_eq!(
(zero6 << 2) | (zero6 >> 4),
0,
"6-bit zero should expand to 0"
);
}
#[test]
fn rgb565_u16_native_precision() {
let px: u16 = 0xFFFF;
let src = px.to_le_bytes();
let mut out = [0u16; 3];
rgb565_to_rgb_u16_row(&src, &mut out, 1);
assert_eq!(out, [31, 63, 31]);
}
#[test]
fn bgr565_channel_order() {
let px: u16 = 0x001F;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
bgr565_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb[0], 255, "R (first byte of output) should be 255");
assert_eq!(rgb[1], 0, "G should be 0");
assert_eq!(rgb[2], 0, "B should be 0");
}
#[test]
fn bgr565_all_ones() {
let px: u16 = 0xFFFF;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
bgr565_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [255, 255, 255]);
}
#[test]
fn bgr565_all_zeros() {
let src = [0u8; 2];
let mut rgb = [0xFFu8; 3];
bgr565_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [0, 0, 0]);
}
#[test]
fn bgr565_u16_native_precision() {
let px: u16 = 0xFFFF;
let src = px.to_le_bytes();
let mut out = [0u16; 3];
bgr565_to_rgb_u16_row(&src, &mut out, 1);
assert_eq!(out, [31, 63, 31]);
}
#[test]
fn rgb555_known_values() {
let px: u16 = 0x7C00;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
rgb555_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb[0], 255, "R should be 255");
assert_eq!(rgb[1], 0, "G should be 0");
assert_eq!(rgb[2], 0, "B should be 0");
}
#[test]
fn rgb555_all_ones() {
let px: u16 = 0x7FFF;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
rgb555_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [255, 255, 255]);
}
#[test]
fn rgb555_all_zeros() {
let src = [0u8; 2];
let mut rgb = [0xFFu8; 3];
rgb555_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [0, 0, 0]);
}
#[test]
fn rgb555_u16_native_precision() {
let px: u16 = 0x7FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 3];
rgb555_to_rgb_u16_row(&src, &mut out, 1);
assert_eq!(out, [31, 31, 31]);
}
#[test]
fn bgr555_channel_order() {
let px: u16 = 0x001F;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
bgr555_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb[0], 255, "R (first byte of output) should be 255");
assert_eq!(rgb[1], 0, "G should be 0");
assert_eq!(rgb[2], 0, "B should be 0");
}
#[test]
fn bgr555_all_ones() {
let px: u16 = 0x7FFF;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
bgr555_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [255, 255, 255]);
}
#[test]
fn bgr555_all_zeros() {
let src = [0u8; 2];
let mut rgb = [0xFFu8; 3];
bgr555_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [0, 0, 0]);
}
#[test]
fn bgr555_u16_native_precision() {
let px: u16 = 0x7FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 3];
bgr555_to_rgb_u16_row(&src, &mut out, 1);
assert_eq!(out, [31, 31, 31]);
}
#[test]
fn rgb444_known_values() {
let px: u16 = 0x0F00;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
rgb444_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb[0], 255, "R should be 255");
assert_eq!(rgb[1], 0, "G should be 0");
assert_eq!(rgb[2], 0, "B should be 0");
}
#[test]
fn rgb444_all_ones() {
let px: u16 = 0x0FFF;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
rgb444_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [255, 255, 255]);
}
#[test]
fn rgb444_all_zeros() {
let src = [0u8; 2];
let mut rgb = [0xFFu8; 3];
rgb444_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [0, 0, 0]);
}
#[test]
fn rgb444_4bit_expansion_boundary() {
let mut prev = 0u8;
for c in 0u8..=15 {
let expanded = (c << 4) | c;
if c > 0 {
assert!(expanded >= prev, "4-bit expansion not monotone at c={c}");
}
prev = expanded;
}
assert_eq!((15u8 << 4) | 15u8, 255, "4-bit max should expand to 255");
let zero4: u8 = 0;
assert_eq!((zero4 << 4) | zero4, 0, "4-bit zero should expand to 0");
}
#[test]
fn rgb444_u16_native_precision() {
let px: u16 = 0x0FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 3];
rgb444_to_rgb_u16_row(&src, &mut out, 1);
assert_eq!(out, [15, 15, 15]);
}
#[test]
fn bgr444_channel_order() {
let px: u16 = 0x000F;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
bgr444_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb[0], 255, "R (first byte of output) should be 255");
assert_eq!(rgb[1], 0, "G should be 0");
assert_eq!(rgb[2], 0, "B should be 0");
}
#[test]
fn bgr444_all_ones() {
let px: u16 = 0x0FFF;
let src = px.to_le_bytes();
let mut rgb = [0u8; 3];
bgr444_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [255, 255, 255]);
}
#[test]
fn bgr444_all_zeros() {
let src = [0u8; 2];
let mut rgb = [0xFFu8; 3];
bgr444_to_rgb_row(&src, &mut rgb, 1);
assert_eq!(rgb, [0, 0, 0]);
}
#[test]
fn bgr444_u16_native_precision() {
let px: u16 = 0x0FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 3];
bgr444_to_rgb_u16_row(&src, &mut out, 1);
assert_eq!(out, [15, 15, 15]);
}
#[test]
fn rgb565_rgba_alpha_forced() {
let pixels: &[u16] = &[0x0000, 0xFFFF, 0x07E0, 0xF800, 0x001F];
let src: std::vec::Vec<u8> = pixels.iter().flat_map(|p| p.to_le_bytes()).collect();
let mut rgba = std::vec![0u8; pixels.len() * 4];
rgb565_to_rgba_row(&src, &mut rgba, pixels.len());
for i in 0..pixels.len() {
assert_eq!(rgba[i * 4 + 3], 0xFF, "alpha at pixel {i} must be 0xFF");
}
}
#[test]
fn rgb555_rgba_alpha_forced() {
let pixels: &[u16] = &[0x0000, 0x7FFF, 0x03E0];
let src: std::vec::Vec<u8> = pixels.iter().flat_map(|p| p.to_le_bytes()).collect();
let mut rgba = std::vec![0u8; pixels.len() * 4];
rgb555_to_rgba_row(&src, &mut rgba, pixels.len());
for i in 0..pixels.len() {
assert_eq!(rgba[i * 4 + 3], 0xFF, "alpha at pixel {i} must be 0xFF");
}
}
#[test]
fn rgb444_rgba_alpha_forced() {
let pixels: &[u16] = &[0x0000, 0x0FFF, 0x0F00];
let src: std::vec::Vec<u8> = pixels.iter().flat_map(|p| p.to_le_bytes()).collect();
let mut rgba = std::vec![0u8; pixels.len() * 4];
rgb444_to_rgba_row(&src, &mut rgba, pixels.len());
for i in 0..pixels.len() {
assert_eq!(rgba[i * 4 + 3], 0xFF, "alpha at pixel {i} must be 0xFF");
}
}
#[test]
fn rgb565_rgba_u16_alpha_forced() {
let px: u16 = 0xF800; let src = px.to_le_bytes();
let mut out = [0u16; 4];
rgb565_to_rgba_u16_row(&src, &mut out, 1);
assert_eq!(out[3], 0xFFFF, "alpha must be 0xFFFF");
}
#[test]
fn bgr565_rgba_u16_alpha_forced() {
let px: u16 = 0x001F; let src = px.to_le_bytes();
let mut out = [0u16; 4];
bgr565_to_rgba_u16_row(&src, &mut out, 1);
assert_eq!(out[3], 0xFFFF, "alpha must be 0xFFFF");
}
#[test]
fn rgb555_rgba_u16_alpha_forced() {
let px: u16 = 0x7FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 4];
rgb555_to_rgba_u16_row(&src, &mut out, 1);
assert_eq!(out[3], 0xFFFF, "alpha must be 0xFFFF");
}
#[test]
fn bgr555_rgba_u16_alpha_forced() {
let px: u16 = 0x7FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 4];
bgr555_to_rgba_u16_row(&src, &mut out, 1);
assert_eq!(out[3], 0xFFFF, "alpha must be 0xFFFF");
}
#[test]
fn rgb444_rgba_u16_alpha_forced() {
let px: u16 = 0x0FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 4];
rgb444_to_rgba_u16_row(&src, &mut out, 1);
assert_eq!(out[3], 0xFFFF, "alpha must be 0xFFFF");
}
#[test]
fn bgr444_rgba_u16_alpha_forced() {
let px: u16 = 0x0FFF;
let src = px.to_le_bytes();
let mut out = [0u16; 4];
bgr444_to_rgba_u16_row(&src, &mut out, 1);
assert_eq!(out[3], 0xFFFF, "alpha must be 0xFFFF");
}
}