diff options
author | 2023-03-07 03:47:49 +0100 | |
---|---|---|
committer | 2023-03-07 03:47:49 +0100 | |
commit | 3a26baa564524b0f25c5cb180b592c8b004b68a9 (patch) | |
tree | c6a51e9116e7f29552130778fe071efa9b1d1262 /graphics/src/image.rs | |
parent | 9b4bcd287a7f4822314e158990d1dc023d5aab51 (diff) | |
download | iced-3a26baa564524b0f25c5cb180b592c8b004b68a9.tar.gz iced-3a26baa564524b0f25c5cb180b592c8b004b68a9.tar.bz2 iced-3a26baa564524b0f25c5cb180b592c8b004b68a9.zip |
Remove `image` abstractions in `iced_graphics`
Diffstat (limited to 'graphics/src/image.rs')
-rw-r--r-- | graphics/src/image.rs | 98 |
1 files changed, 91 insertions, 7 deletions
diff --git a/graphics/src/image.rs b/graphics/src/image.rs index 04f4ff9d..2f634252 100644 --- a/graphics/src/image.rs +++ b/graphics/src/image.rs @@ -1,10 +1,94 @@ -//! Render images. -#[cfg(feature = "image_rs")] -pub mod raster; +//! Load and operate on images. +use crate::core::image::{Data, Handle}; -#[cfg(feature = "svg")] -pub mod vector; +use bitflags::bitflags; -pub mod storage; +pub use ::image as image_rs; -pub use storage::Storage; +pub fn load(handle: &Handle) -> image_rs::ImageResult<image_rs::DynamicImage> { + match handle.data() { + Data::Path(path) => { + let image = ::image::open(path)?; + + let operation = std::fs::File::open(path) + .ok() + .map(std::io::BufReader::new) + .and_then(|mut reader| Operation::from_exif(&mut reader).ok()) + .unwrap_or_else(Operation::empty); + + Ok(operation.perform(image)) + } + Data::Bytes(bytes) => { + let image = ::image::load_from_memory(bytes)?; + let operation = + Operation::from_exif(&mut std::io::Cursor::new(bytes)) + .ok() + .unwrap_or_else(Operation::empty); + + Ok(operation.perform(image)) + } + Data::Rgba { + width, + height, + pixels, + } => { + if let Some(image) = image_rs::ImageBuffer::from_vec( + *width, + *height, + pixels.to_vec(), + ) { + Ok(image_rs::DynamicImage::ImageRgba8(image)) + } else { + Err(image_rs::error::ImageError::Limits( + image_rs::error::LimitError::from_kind( + image_rs::error::LimitErrorKind::DimensionError, + ), + )) + } + } + } +} + +bitflags! { + struct Operation: u8 { + const FLIP_HORIZONTALLY = 0b001; + const ROTATE_180 = 0b010; + const FLIP_DIAGONALLY = 0b100; + } +} + +impl Operation { + // Meaning of the returned value is described e.g. at: + // https://magnushoff.com/articles/jpeg-orientation/ + fn from_exif<R>(reader: &mut R) -> Result<Self, exif::Error> + where + R: std::io::BufRead + std::io::Seek, + { + let exif = exif::Reader::new().read_from_container(reader)?; + + Ok(exif + .get_field(exif::Tag::Orientation, exif::In::PRIMARY) + .and_then(|field| field.value.get_uint(0)) + .and_then(|value| u8::try_from(value).ok()) + .and_then(|value| Self::from_bits(value.saturating_sub(1))) + .unwrap_or_else(Self::empty)) + } + + fn perform(self, mut image: image::DynamicImage) -> image::DynamicImage { + use image::imageops; + + if self.contains(Self::FLIP_DIAGONALLY) { + imageops::flip_vertical_in_place(&mut image) + } + + if self.contains(Self::ROTATE_180) { + imageops::rotate180_in_place(&mut image); + } + + if self.contains(Self::FLIP_HORIZONTALLY) { + imageops::flip_horizontal_in_place(&mut image); + } + + image + } +} |