Files
multiverse/xcom-ultra/xcu-screen-capture/src/lib.rs
T

35 lines
2.2 KiB
Rust

#![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<u8>, 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<u8> { prev.iter().zip(curr.iter()).map(|(a, b)| a ^ b).collect() }
pub fn decode(prev: &[u8], diff: &[u8]) -> Vec<u8> { 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); }
}