diff options
-rw-r--r-- | Cargo.toml | 2 | ||||
-rw-r--r-- | core/src/image.rs | 91 | ||||
-rw-r--r-- | graphics/src/image.rs | 51 | ||||
-rw-r--r-- | tiny_skia/src/raster.rs | 2 | ||||
-rw-r--r-- | wgpu/src/image/raster.rs | 4 |
5 files changed, 73 insertions, 77 deletions
@@ -136,8 +136,8 @@ iced_winit = { version = "0.13.0-dev", path = "winit" } async-std = "1.0" bitflags = "2.0" -bytes = "1.6" bytemuck = { version = "1.0", features = ["derive"] } +bytes = "1.6" cosmic-text = "0.10" dark-light = "1.0" futures = "0.3" diff --git a/core/src/image.rs b/core/src/image.rs index 7316ede7..5b31fbcf 100644 --- a/core/src/image.rs +++ b/core/src/image.rs @@ -4,14 +4,27 @@ pub use bytes::Bytes; use crate::{Rectangle, Size}; use rustc_hash::FxHasher; -use std::hash::{Hash, Hasher as _}; +use std::hash::{Hash, Hasher}; use std::path::PathBuf; /// A handle of some image data. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Handle { - id: u64, - data: Data, +#[derive(Clone, PartialEq, Eq)] +pub enum Handle { + /// File data + Path(PathBuf), + + /// In-memory data + Bytes(Bytes), + + /// Decoded image pixels in RGBA format. + Rgba { + /// The width of the image. + width: u32, + /// The height of the image. + height: u32, + /// The pixels. + pixels: Bytes, + }, } impl Handle { @@ -19,7 +32,7 @@ impl Handle { /// /// Makes an educated guess about the image format by examining the data in the file. pub fn from_path<T: Into<PathBuf>>(path: T) -> Handle { - Self::from_data(Data::Path(path.into())) + Self::Path(path.into()) } /// Creates an image [`Handle`] containing the image pixels directly. This @@ -32,11 +45,11 @@ impl Handle { height: u32, pixels: impl Into<Bytes>, ) -> Handle { - Self::from_data(Data::Rgba { + Self::Rgba { width, height, pixels: pixels.into(), - }) + } } /// Creates an image [`Handle`] containing the image data directly. @@ -46,27 +59,25 @@ impl Handle { /// This is useful if you already have your image loaded in-memory, maybe /// because you downloaded or generated it procedurally. pub fn from_memory(bytes: impl Into<Bytes>) -> Handle { - Self::from_data(Data::Bytes(bytes.into())) - } - - fn from_data(data: Data) -> Handle { - let mut hasher = FxHasher::default(); - data.hash(&mut hasher); - - Handle { - id: hasher.finish(), - data, - } + Self::Bytes(bytes.into()) } /// Returns the unique identifier of the [`Handle`]. pub fn id(&self) -> u64 { - self.id + let mut hasher = FxHasher::default(); + self.hash(&mut hasher); + + hasher.finish() } +} - /// Returns a reference to the image [`Data`]. - pub fn data(&self) -> &Data { - &self.data +impl Hash for Handle { + fn hash<H: Hasher>(&self, state: &mut H) { + match self { + Self::Path(path) => path.hash(state), + Self::Bytes(bytes) => bytes.as_ptr().hash(state), + Self::Rgba { pixels, .. } => pixels.as_ptr().hash(state), + } } } @@ -79,38 +90,12 @@ where } } -impl Hash for Handle { - fn hash<H: std::hash::Hasher>(&self, state: &mut H) { - self.id.hash(state); - } -} - -/// The data of a raster image. -#[derive(Clone, PartialEq, Eq, Hash)] -pub enum Data { - /// File data - Path(PathBuf), - - /// In-memory data - Bytes(Bytes), - - /// Decoded image pixels in RGBA format. - Rgba { - /// The width of the image. - width: u32, - /// The height of the image. - height: u32, - /// The pixels. - pixels: Bytes, - }, -} - -impl std::fmt::Debug for Data { +impl std::fmt::Debug for Handle { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - Data::Path(path) => write!(f, "Path({path:?})"), - Data::Bytes(_) => write!(f, "Bytes(...)"), - Data::Rgba { width, height, .. } => { + Self::Path(path) => write!(f, "Path({path:?})"), + Self::Bytes(_) => write!(f, "Bytes(...)"), + Self::Rgba { width, height, .. } => { write!(f, "Pixels({width} * {height})") } } diff --git a/graphics/src/image.rs b/graphics/src/image.rs index c6135e9e..2a630530 100644 --- a/graphics/src/image.rs +++ b/graphics/src/image.rs @@ -50,7 +50,8 @@ impl Image { /// [`Handle`]: image::Handle pub fn load( handle: &image::Handle, -) -> ::image::ImageResult<::image::DynamicImage> { +) -> ::image::ImageResult<::image::ImageBuffer<::image::Rgba<u8>, image::Bytes>> +{ use bitflags::bitflags; bitflags! { @@ -100,8 +101,8 @@ pub fn load( } } - match handle.data() { - image::Data::Path(path) => { + let (width, height, pixels) = match handle { + image::Handle::Path(path) => { let image = ::image::open(path)?; let operation = std::fs::File::open(path) @@ -110,33 +111,43 @@ pub fn load( .and_then(|mut reader| Operation::from_exif(&mut reader).ok()) .unwrap_or_else(Operation::empty); - Ok(operation.perform(image)) + let rgba = operation.perform(image).into_rgba8(); + + ( + rgba.width(), + rgba.height(), + image::Bytes::from(rgba.into_raw()), + ) } - image::Data::Bytes(bytes) => { + image::Handle::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)) + let rgba = operation.perform(image).into_rgba8(); + + ( + rgba.width(), + rgba.height(), + image::Bytes::from(rgba.into_raw()), + ) } - image::Data::Rgba { + image::Handle::Rgba { width, height, pixels, - } => { - if let Some(image) = - ::image::ImageBuffer::from_vec(*width, *height, pixels.to_vec()) - { - Ok(::image::DynamicImage::ImageRgba8(image)) - } else { - Err(::image::error::ImageError::Limits( - ::image::error::LimitError::from_kind( - ::image::error::LimitErrorKind::DimensionError, - ), - )) - } - } + } => (*width, *height, pixels.clone()), + }; + + if let Some(image) = ::image::ImageBuffer::from_raw(width, height, pixels) { + Ok(image) + } else { + Err(::image::error::ImageError::Limits( + ::image::error::LimitError::from_kind( + ::image::error::LimitErrorKind::DimensionError, + ), + )) } } diff --git a/tiny_skia/src/raster.rs b/tiny_skia/src/raster.rs index 176b0da9..59f1e4d5 100644 --- a/tiny_skia/src/raster.rs +++ b/tiny_skia/src/raster.rs @@ -83,7 +83,7 @@ impl Cache { let id = handle.id(); if let hash_map::Entry::Vacant(entry) = self.entries.entry(id) { - let image = graphics::image::load(handle).ok()?.into_rgba8(); + let image = graphics::image::load(handle).ok()?; let mut buffer = vec![0u32; image.width() as usize * image.height() as usize]; diff --git a/wgpu/src/image/raster.rs b/wgpu/src/image/raster.rs index 7a837f28..60e9cbad 100644 --- a/wgpu/src/image/raster.rs +++ b/wgpu/src/image/raster.rs @@ -10,7 +10,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; #[derive(Debug)] pub enum Memory { /// Image data on host - Host(image_rs::ImageBuffer<image_rs::Rgba<u8>, Vec<u8>>), + Host(image_rs::ImageBuffer<image_rs::Rgba<u8>, image::Bytes>), /// Storage entry Device(atlas::Entry), /// Image not found @@ -51,7 +51,7 @@ impl Cache { } let memory = match graphics::image::load(handle) { - Ok(image) => Memory::Host(image.to_rgba8()), + Ok(image) => Memory::Host(image), Err(image_rs::error::ImageError::IoError(_)) => Memory::NotFound, Err(_) => Memory::Invalid, }; |