#![deny(warnings)] #![allow(dead_code)] //! [TSM.ID].[11031972] -- Platform X Ecosystem //! xcu-screen-capture -- Screen Capture with Color Space Conversion #[derive(Debug)] pub enum CaptureError { InvalidRegion(String), BufferTooSmall(String) } impl std::fmt::Display for CaptureError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::InvalidRegion(e)|Self::BufferTooSmall(e) => write!(f, "{e}") } } } impl std::error::Error for CaptureError {} #[derive(Debug, Clone)] pub struct CaptureRegion { pub x: u32, pub y: u32, pub width: u32, pub height: u32 } #[derive(Debug, Clone)] pub struct FrameBuffer { pub width: u32, pub height: u32, pub data: Vec, pub stride: u32 } impl FrameBuffer { pub fn pixel_count(&self) -> usize { (self.width * self.height) as usize } } pub fn rgba_to_yuv420(r: u8, g: u8, b: u8) -> (u8, u8, u8) { let rf = r as f64; let gf = g as f64; let bf = b as f64; let y = (0.299 * rf + 0.587 * gf + 0.114 * bf).clamp(0.0, 255.0) as u8; let u = (-0.169 * rf - 0.331 * gf + 0.500 * bf + 128.0).clamp(0.0, 255.0) as u8; let v = (0.500 * rf - 0.419 * gf - 0.081 * bf + 128.0).clamp(0.0, 255.0) as u8; (y, u, v) } pub fn yuv_to_rgba(y: u8, u: u8, v: u8) -> (u8, u8, u8) { let yf = y as f64; let uf = u as f64 - 128.0; let vf = v as f64 - 128.0; let r = (yf + 1.402 * vf).clamp(0.0, 255.0) as u8; let g = (yf - 0.344 * uf - 0.714 * vf).clamp(0.0, 255.0) as u8; let b = (yf + 1.772 * uf).clamp(0.0, 255.0) as u8; (r, g, b) } pub struct DiffEncoder; impl DiffEncoder { pub fn encode(prev: &[u8], curr: &[u8]) -> Vec { prev.iter().zip(curr.iter()).map(|(a, b)| a ^ b).collect() } pub fn decode(prev: &[u8], diff: &[u8]) -> Vec { prev.iter().zip(diff.iter()).map(|(a, d)| a ^ d).collect() } } #[cfg(test)] mod tests { use super::*; #[test] fn test_color_roundtrip() { let (y, u, v) = rgba_to_yuv420(128, 64, 200); let (r, g, b) = yuv_to_rgba(y, u, v); assert!((128i16 - r as i16).abs() < 5); } #[test] fn test_diff_roundtrip() { let prev = vec![10, 20, 30]; let curr = vec![15, 25, 35]; let diff = DiffEncoder::encode(&prev, &curr); let rec = DiffEncoder::decode(&prev, &diff); assert_eq!(rec, curr); } }