#![allow(dead_code)]
pub fn rgba_to_gbr_planes(
pixels: &[[u8; 4]],
w: usize,
h: usize,
) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
debug_assert_eq!(pixels.len(), w * h, "pixel slice length must equal w*h");
let n = w * h;
let mut plane_g = Vec::with_capacity(n);
let mut plane_b = Vec::with_capacity(n);
let mut plane_r = Vec::with_capacity(n);
for px in pixels {
let [r, g, b, _a] = *px;
plane_g.push(g);
plane_b.push(b);
plane_r.push(r);
}
(plane_g, plane_b, plane_r)
}
pub fn gbr_planes_to_rgba(
plane_g: &[u8],
plane_b: &[u8],
plane_r: &[u8],
w: usize,
h: usize,
) -> Vec<[u8; 4]> {
let n = w * h;
debug_assert_eq!(plane_g.len(), n);
debug_assert_eq!(plane_b.len(), n);
debug_assert_eq!(plane_r.len(), n);
let mut out = Vec::with_capacity(n);
for i in 0..n {
out.push([plane_r[i], plane_g[i], plane_b[i], 255u8]);
}
out
}
pub fn pack_gbr_interleaved(pixels: &[[u8; 4]], w: usize, h: usize) -> Vec<[u8; 3]> {
debug_assert_eq!(pixels.len(), w * h, "pixel slice length must equal w*h");
let n = w * h;
let mut out = Vec::with_capacity(n);
for px in pixels {
let [r, g, b, _a] = *px;
out.push([g, b, r]);
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_round_trip_rgba_gbr_rgba() {
let pixels: Vec<[u8; 4]> = vec![
[255, 0, 0, 255], [0, 255, 0, 128], [0, 0, 255, 64], [123, 45, 67, 200], [0, 0, 0, 0], [255, 255, 255, 255], ];
let w = 2;
let h = 3;
let (pg, pb, pr) = rgba_to_gbr_planes(&pixels, w, h);
let restored = gbr_planes_to_rgba(&pg, &pb, &pr, w, h);
assert_eq!(restored.len(), pixels.len());
for (i, (orig, got)) in pixels.iter().zip(restored.iter()).enumerate() {
assert_eq!(got[0], orig[0], "R mismatch at {i}");
assert_eq!(got[1], orig[1], "G mismatch at {i}");
assert_eq!(got[2], orig[2], "B mismatch at {i}");
assert_eq!(got[3], 255u8, "alpha should be 255 at {i}");
}
}
#[test]
fn test_known_pixel_correctness() {
let pixels = vec![[0x10u8, 0x20, 0x30, 0xFF]];
let (pg, pb, pr) = rgba_to_gbr_planes(&pixels, 1, 1);
assert_eq!(pg[0], 0x20, "plane_g should be G");
assert_eq!(pb[0], 0x30, "plane_b should be B");
assert_eq!(pr[0], 0x10, "plane_r should be R");
}
#[test]
fn test_plane_lengths() {
let w = 7;
let h = 5;
let pixels: Vec<[u8; 4]> = (0..w * h)
.map(|i| [(i & 0xFF) as u8, ((i + 1) & 0xFF) as u8, ((i + 2) & 0xFF) as u8, 255])
.collect();
let (pg, pb, pr) = rgba_to_gbr_planes(&pixels, w, h);
assert_eq!(pg.len(), w * h);
assert_eq!(pb.len(), w * h);
assert_eq!(pr.len(), w * h);
}
#[test]
fn test_pack_gbr_interleaved_ordering() {
let pixels = vec![
[0xAAu8, 0xBB, 0xCC, 0xFF],
[0x11u8, 0x22, 0x33, 0x00],
];
let packed = pack_gbr_interleaved(&pixels, 2, 1);
assert_eq!(packed.len(), 2);
assert_eq!(packed[0], [0xBB, 0xCC, 0xAA]);
assert_eq!(packed[1], [0x22, 0x33, 0x11]);
}
#[test]
fn test_empty_image() {
let pixels: Vec<[u8; 4]> = Vec::new();
let (pg, pb, pr) = rgba_to_gbr_planes(&pixels, 0, 0);
assert!(pg.is_empty());
assert!(pb.is_empty());
assert!(pr.is_empty());
let restored = gbr_planes_to_rgba(&pg, &pb, &pr, 0, 0);
assert!(restored.is_empty());
}
}