use image::{ColorType, DynamicImage, GenericImageView, ImageError};
use image::codecs::jpeg::JpegEncoder;
use image::imageops::FilterType;
use crate::{Kind, AjazzError};
use crate::info::{ImageFormat, ImageMirroring, ImageMode, ImageRotation};
pub fn convert_image(kind: Kind, image: DynamicImage) -> Result<Vec<u8>, ImageError> {
convert_image_with_format(kind.key_image_format(), image)
}
pub fn convert_image_with_format(image_format: ImageFormat, image: DynamicImage) -> Result<Vec<u8>, ImageError> {
let (ws, hs) = image_format.size;
let image = image.resize_exact(ws as u32, hs as u32, FilterType::Nearest);
let image = match image_format.rotation {
ImageRotation::Rot0 => image,
ImageRotation::Rot90 => image.rotate90(),
ImageRotation::Rot180 => image.rotate180(),
ImageRotation::Rot270 => image.rotate270(),
};
let image = match image_format.mirror {
ImageMirroring::None => image,
ImageMirroring::X => image.fliph(),
ImageMirroring::Y => image.flipv(),
ImageMirroring::Both => image.fliph().flipv(),
};
let image_data = image.into_rgb8().to_vec();
match image_format.mode {
ImageMode::None => Ok(vec![]),
ImageMode::JPEG => {
let mut buf = Vec::new();
let mut encoder = JpegEncoder::new_with_quality(&mut buf, 90);
encoder.encode(&image_data, ws as u32, hs as u32, ColorType::Rgb8.into())?;
Ok(buf)
}
}
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn convert_image_async(kind: Kind, image: DynamicImage) -> Result<Vec<u8>, AjazzError> {
Ok(tokio::task::block_in_place(move || convert_image(kind, image))?)
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn convert_image_with_format_async(format: ImageFormat, image: DynamicImage) -> Result<Vec<u8>, AjazzError> {
Ok(tokio::task::block_in_place(move || convert_image_with_format(format, image))?)
}
pub struct ImageRect {
pub w: u16,
pub h: u16,
pub data: Vec<u8>,
}
impl ImageRect {
pub fn from_image(image: DynamicImage) -> Result<ImageRect, AjazzError> {
let (image_w, image_h) = image.dimensions();
let image_data = image.into_rgb8().to_vec();
let mut buf = Vec::new();
let mut encoder = JpegEncoder::new_with_quality(&mut buf, 90);
encoder.encode(&image_data, image_w, image_h, ColorType::Rgb8.into())?;
Ok(ImageRect {
w: image_w as u16,
h: image_h as u16,
data: buf,
})
}
#[cfg(feature = "async")]
#[cfg_attr(docsrs, doc(cfg(feature = "async")))]
pub fn from_image_async(image: DynamicImage) -> Result<ImageRect, AjazzError> {
tokio::task::block_in_place(move || ImageRect::from_image(image))
}
}