From 665f8a901bf9627ab9e1a561e157fa659b4d6942 Mon Sep 17 00:00:00 2001 From: Florian Hars Date: Sun, 9 Jan 2022 14:28:46 +0100 Subject: [PATCH 1/2] replace deprecated image methods --- src/images.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/images.rs b/src/images.rs index 2794239..52fea99 100644 --- a/src/images.rs +++ b/src/images.rs @@ -1,7 +1,7 @@ use std::str::FromStr; use image::io::Reader; -use image::jpeg::JPEGEncoder; +use image::jpeg::JpegEncoder; use image::DynamicImage; use image::{imageops::FilterType, ColorType, Pixel, Rgba}; @@ -143,8 +143,8 @@ pub(crate) fn load_image( // Convert to vector with correct encoding let v = match colour_order { - ColourOrder::BGR => image.to_bgr().into_vec(), - ColourOrder::RGB => image.to_rgb().into_vec(), + ColourOrder::BGR => image.to_bgr8().into_vec(), + ColourOrder::RGB => image.to_rgb8().into_vec(), }; if v.len() != x * y * 3 { @@ -157,7 +157,7 @@ pub(crate) fn load_image( /// Encodes a BGR bitmap into a JPEG image for outputting to a V2 device pub(crate) fn encode_jpeg(image: &[u8], width: usize, height: usize) -> Result, Error> { let mut buf = Vec::new(); - let mut encoder = JPEGEncoder::new_with_quality(&mut buf, 100); + let mut encoder = JpegEncoder::new_with_quality(&mut buf, 100); encoder.encode(image, width as u32, height as u32, ColorType::Rgb8)?; Ok(buf) } From 34852109c5ca9cd89feb2ef7934653d56a79bf46 Mon Sep 17 00:00:00 2001 From: Florian Hars Date: Sun, 9 Jan 2022 15:00:41 +0100 Subject: [PATCH 2/2] separate loading image files from setting button images This is more efficient if one wants to display the same image more than once. Like, for example, if one wants to play minsweeper on a streamdeck XL. --- src/lib.rs | 60 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 56651c5..c66226c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,3 @@ -use std::borrow::Cow; use std::io::Error as IoError; use std::time::Duration; @@ -69,6 +68,10 @@ pub enum Error { NoData, } +pub struct DeviceImage { + data: Vec, +} + /// Device USB Product Identifiers (PIDs) pub mod pids { pub const ORIGINAL: u16 = 0x0060; @@ -236,6 +239,22 @@ impl StreamDeck { self.kind.image_size() } + /// Convert an image into the device dependent format + fn convert_image(&self, image: Vec) -> Result { + // Check image dimensions + if image.len() != self.kind.image_size_bytes() { + return Err(Error::InvalidImageSize); + } + let image = match self.kind.image_mode() { + ImageMode::Bmp => image, + ImageMode::Jpeg => { + let (w, h) = self.kind.image_size(); + encode_jpeg(&image, w, h)? + } + }; + Ok(DeviceImage{ data: image }) + } + /// Set a button to the provided RGB colour pub fn set_button_rgb(&mut self, key: u8, colour: &Colour) -> Result<(), Error> { let mut image = vec![0u8; self.kind.image_size_bytes()]; @@ -259,8 +278,7 @@ impl StreamDeck { _ => unreachable!(), }; } - - self.write_button_image(key, &image)?; + self.write_button_image(key, &self.convert_image(image)?)?; Ok(()) } @@ -269,10 +287,10 @@ impl StreamDeck { pub fn set_button_image(&mut self, key: u8, image: DynamicImage) -> Result<(), Error> { let image = apply_transform(image, self.kind.image_rotation(), self.kind.image_mirror()); let image = match self.kind.image_colour_order() { - ColourOrder::BGR => image.into_bgr().into_vec(), - ColourOrder::RGB => image.into_rgb().into_vec(), + ColourOrder::BGR => image.into_bgra8().into_vec(), + ColourOrder::RGB => image.into_rgb8().into_vec(), }; - self.write_button_image(key, &image) + self.write_button_image(key, &self.convert_image(image)?) } /// Sets a button to the provided text. @@ -310,6 +328,16 @@ impl StreamDeck { image: &str, opts: &ImageOptions, ) -> Result<(), Error> { + + self.write_button_image(key, &self.load_image(image, opts)?) + } + + /// Load an image file into the device specific representation + pub fn load_image( + &self, + image: &str, + opts: &ImageOptions, + ) -> Result { let (x, y) = self.kind.image_size(); let rotate = self.kind.image_rotation(); let mirror = self.kind.image_mirror(); @@ -323,10 +351,7 @@ impl StreamDeck { opts, self.kind.image_colour_order(), )?; - - self.write_button_image(key, &image)?; - - Ok(()) + self.convert_image(image) } /// Transforms a key from zero-indexed left-to-right into the device-correct coordinate system @@ -350,22 +375,11 @@ impl StreamDeck { /// Writes an image to a button /// Image at this point in correct dimensions and in device native colour order. - fn write_button_image(&mut self, key: u8, image: &[u8]) -> Result<(), Error> { - // Check image dimensions - if image.len() != self.kind.image_size_bytes() { - return Err(Error::InvalidImageSize); - } + pub fn write_button_image(&mut self, key: u8, image: &DeviceImage) -> Result<(), Error> { + let image = &image.data; let key = self.translate_key_index(key)?; - let image = match self.kind.image_mode() { - ImageMode::Bmp => Cow::from(image), - ImageMode::Jpeg => { - let (w, h) = self.kind.image_size(); - Cow::from(encode_jpeg(image, w, h)?) - } - }; - let mut buf = vec![0u8; self.kind.image_report_len()]; let base = self.kind.image_base(); let hdrlen = self.kind.image_report_header_len();