1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
use std::sync::Arc;
#[derive(Clone)]
#[allow(dead_code)]
pub struct CompressedCanvasState {
data: Arc<[u8]>,
// FIXME: These fields are never read; we should either take advantage of or remove them.
height: u32,
width: u32,
}
/// For reference, a rectangle with height=1050 and width=1404
/// will have the following size at rest:
///
/// (notice better compression at first due to relatively low-entropy canvas
/// compression plateuaus around 93% as the entropy peaks)
///
/// raw: 5896.8 kB -- zstd: 7.875 kB (99.86645% compression)
/// raw: 5896.8 kB -- zstd: 25.405 kB (99.569176% compression)
/// raw: 5896.8 kB -- zstd: 210.628 kB (96.4281% compression)
/// raw: 5896.8 kB -- zstd: 367.217 kB (93.7726% compression)
/// raw: 5896.8 kB -- zstd: 367.217 kB (93.7726% compression)
/// raw: 5896.8 kB -- zstd: 356.432 kB (93.9555% compression)
/// raw: 5896.8 kB -- zstd: 361.935 kB (93.86218% compression)
impl CompressedCanvasState {
/// Creates a CompressedCanvasState from the output of FramebufferIO::dump_region(..)
/// Consumes the RgbaImage that's provided to it.
pub fn new(img: &[u8], height: u32, width: u32) -> CompressedCanvasState {
CompressedCanvasState {
data: zstd::encode_all(img, 0).unwrap().into(),
height,
width,
}
}
/// Returns an ImageBuffer which can be used to restore the contents of a screen
/// region using the FramebufferIO::restore_region(..)
pub fn decompress(&self) -> Vec<u8> {
zstd::decode_all(&*self.data).unwrap()
}
}
#[cfg(feature = "image")]
use crate::framebuffer::common;
#[cfg(feature = "image")]
pub fn rgbimage_from_u8_slice(w: u32, h: u32, buff: &[u8]) -> Option<image::RgbImage> {
// rgb565 is the input so it is 16bits (2 bytes) per pixel
let input_bytespp = 2;
let input_line_len = w * input_bytespp;
if h * input_line_len != buff.len() as u32 {
return None;
}
Some(image::ImageBuffer::from_fn(w, h, |x, y| {
let in_index: usize = ((y * input_line_len) + ((input_bytespp * x) as u32)) as usize;
let data = common::color::NATIVE_COMPONENTS(buff[in_index], buff[in_index + 1]).to_rgb8();
image::Rgb(data)
}))
}