Skip to content

Commit

Permalink
Merge pull request #17 from fhars/load-image
Browse files Browse the repository at this point in the history
Separate loading image files from setting button images
  • Loading branch information
ryankurte committed Jan 9, 2022
2 parents ce82a89 + 3485210 commit 40596fc
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 27 deletions.
8 changes: 4 additions & 4 deletions src/images.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -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 {
Expand All @@ -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<Vec<u8>, 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)
}
Expand Down
60 changes: 37 additions & 23 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::borrow::Cow;
use std::io::Error as IoError;
use std::time::Duration;

Expand Down Expand Up @@ -69,6 +68,10 @@ pub enum Error {
NoData,
}

pub struct DeviceImage {
data: Vec<u8>,
}

/// Device USB Product Identifiers (PIDs)
pub mod pids {
pub const ORIGINAL: u16 = 0x0060;
Expand Down Expand Up @@ -236,6 +239,22 @@ impl StreamDeck {
self.kind.image_size()
}

/// Convert an image into the device dependent format
fn convert_image(&self, image: Vec<u8>) -> Result<DeviceImage, Error> {
// 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()];
Expand All @@ -259,8 +278,7 @@ impl StreamDeck {
_ => unreachable!(),
};
}

self.write_button_image(key, &image)?;
self.write_button_image(key, &self.convert_image(image)?)?;

Ok(())
}
Expand All @@ -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.
Expand Down Expand Up @@ -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<DeviceImage, Error> {
let (x, y) = self.kind.image_size();
let rotate = self.kind.image_rotation();
let mirror = self.kind.image_mirror();
Expand All @@ -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
Expand All @@ -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();
Expand Down

0 comments on commit 40596fc

Please sign in to comment.