diff options
| author | HampusM <hampus@hampusmat.com> | 2026-07-16 17:02:49 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-07-16 17:02:49 +0200 |
| commit | 2ee2f0dfde751d9680748871644cdd21e2d95f22 (patch) | |
| tree | 205da49372eb909ca4d39b927e4447f6bca59e8e /engine | |
| parent | b6b4e4a8d14a4fb91af5169a8d1957b23a387ada (diff) | |
feat(engine): replace Image::try_from_bytes fn with from_pixels fn
Diffstat (limited to 'engine')
| -rw-r--r-- | engine/src/image.rs | 174 | ||||
| -rw-r--r-- | engine/src/ui/imgui.rs | 20 |
2 files changed, 88 insertions, 106 deletions
diff --git a/engine/src/image.rs b/engine/src/image.rs index 51ba459..1dc129e 100644 --- a/engine/src/image.rs +++ b/engine/src/image.rs @@ -1,13 +1,14 @@ -use std::any::type_name; use std::fs::File; use std::io::{BufRead, BufReader, Seek}; +use std::marker::PhantomData; +use std::ops::Deref; use std::path::Path; use image_rs::GenericImageView as _; -use zerocopy::{FromBytes, Immutable}; -use crate::color::Color; +use crate::color::{Color, Luma, LumaA, Pixel as ColorPixel, Rgb, Rgba}; use crate::data_types::dimens::Dimens; +use crate::vector::Vec2; #[derive(Debug, Clone)] pub struct Image @@ -48,30 +49,15 @@ impl Image }) } - pub fn try_from_bytes( - bytes: &[u8], - dimens: Dimens<u32>, - color_type: ColorType, - ) -> Result<Self, FromBytesError> + pub fn from_pixels<PixelT, Buf>( + pixels: PixelBuffer<PixelT, Buf>, + ) -> Result<Self, PixelBufferLenIncorrectForSize> + where + PixelT: ColorPixel, + Buf: Deref<Target = [PixelT::Component]>, + Self: TryFrom<PixelBuffer<PixelT, Buf>, Error = PixelBufferLenIncorrectForSize>, { - use image_rs::{Luma, LumaA, Rgb, Rgba}; - - let inner = match color_type { - ColorType::L8 => image_buf_from_bytes::<Luma<u8>>(dimens, bytes)?.into(), - ColorType::La8 => image_buf_from_bytes::<LumaA<u8>>(dimens, bytes)?.into(), - ColorType::Rgb8 => image_buf_from_bytes::<Rgb<u8>>(dimens, bytes)?.into(), - ColorType::Rgba8 => image_buf_from_bytes::<Rgba<u8>>(dimens, bytes)?.into(), - ColorType::L16 => image_buf_from_bytes::<Luma<u16>>(dimens, bytes)?.into(), - ColorType::La16 => image_buf_from_bytes::<LumaA<u16>>(dimens, bytes)?.into(), - ColorType::Rgb16 => image_buf_from_bytes::<Rgb<u16>>(dimens, bytes)?.into(), - ColorType::Rgba16 => image_buf_from_bytes::<Rgba<u16>>(dimens, bytes)?.into(), - ColorType::Rgb32F => image_buf_from_bytes::<Rgb<f32>>(dimens, bytes)?.into(), - ColorType::Rgba32F => { - image_buf_from_bytes::<Rgba<f32>>(dimens, bytes)?.into() - } - }; - - Ok(Self { inner }) + Self::try_from(pixels) } pub fn from_color(dimens: impl Into<Dimens<u32>>, color: impl Into<Color<u8>>) @@ -154,6 +140,73 @@ impl Image } } +macro_rules! gen_try_from_pixel_buffer_impl { + ($pixel: ident<$component: ty>) => { + impl<Buf> TryFrom<PixelBuffer<$pixel<$component>, Buf>> for Image + where + Buf: Deref<Target = [$component]>, + { + type Error = PixelBufferLenIncorrectForSize; + + fn try_from( + pixels: PixelBuffer<$pixel<$component>, Buf>, + ) -> Result<Self, Self::Error> + { + Ok( + Image { + inner: image_rs::ImageBuffer::< + image_rs::$pixel<$component>, + Vec<_>, + >::from_raw( + pixels.size.width, + pixels.size.height, + pixels.buf.deref().to_vec(), + ) + .ok_or(PixelBufferLenIncorrectForSize)? + .into(), + }, + ) + } + } + }; +} + +gen_try_from_pixel_buffer_impl!(Rgb<u8>); +gen_try_from_pixel_buffer_impl!(Rgb<u16>); +gen_try_from_pixel_buffer_impl!(Rgb<f32>); + +gen_try_from_pixel_buffer_impl!(Rgba<u8>); +gen_try_from_pixel_buffer_impl!(Rgba<u16>); +gen_try_from_pixel_buffer_impl!(Rgba<f32>); + +gen_try_from_pixel_buffer_impl!(Luma<u8>); +gen_try_from_pixel_buffer_impl!(Luma<u16>); + +gen_try_from_pixel_buffer_impl!(LumaA<u8>); +gen_try_from_pixel_buffer_impl!(LumaA<u16>); + +#[derive(Debug)] +pub struct PixelBuffer<PixelT, Buf> +where + PixelT: ColorPixel, + Buf: Deref<Target = [PixelT::Component]>, +{ + buf: Buf, + size: Dimens<u32>, + _pd: PhantomData<PixelT>, +} + +impl<PixelT, Buf> PixelBuffer<PixelT, Buf> +where + PixelT: ColorPixel, + Buf: Deref<Target = [PixelT::Component]>, +{ + pub fn new(buf: Buf, size: Dimens<u32>) -> Self + { + Self { buf, size, _pd: PhantomData } + } +} + /// An enumeration over supported color types and bit depths #[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)] #[non_exhaustive] @@ -251,70 +304,5 @@ pub enum Error pub struct DecodeError(image_rs::ImageError); #[derive(Debug, thiserror::Error)] -pub enum FromBytesError -{ - #[error( - "The number of bytes provided is not enough to fit a image with the given size" - )] - NotEnoughBytesForDimensions, - - #[error("Failed to cast bytes to subpixels")] - CastToSubPixelsFailed(#[from] CastToSubPixelsError), -} - -#[derive(Debug, thiserror::Error)] -pub enum CastToSubPixelsError -{ - #[error( - "Source address {:?} ({}) isn't a multiple of the alignment of the type {} ({})", - src, - src_type_name, - dst_type_name, - dst_align - )] - Alignment - { - src_type_name: &'static str, - dst_type_name: &'static str, - src: *const u8, - dst_align: usize, - }, - - #[error( - "Source size {} ({}) is incorrect size for type {}", - src_size, - src_type_name, - dst_type_name - )] - Size - { - src_type_name: &'static str, - dst_type_name: &'static str, - src_size: usize, - }, -} - -fn image_buf_from_bytes<Pixel>( - dimens: Dimens<u32>, - bytes: &[u8], -) -> Result<image_rs::ImageBuffer<Pixel, Vec<Pixel::Subpixel>>, FromBytesError> -where - Pixel: image_rs::Pixel<Subpixel: FromBytes + Immutable>, -{ - let buf = <[Pixel::Subpixel]>::ref_from_bytes(bytes).map_err(|err| match err { - zerocopy::CastError::Alignment(_) => CastToSubPixelsError::Alignment { - src_type_name: type_name::<&[u8]>(), - dst_type_name: type_name::<&[Pixel]>(), - src: bytes.as_ptr(), - dst_align: align_of_val::<[Pixel]>(&[]), - }, - zerocopy::ConvertError::Size(_) => CastToSubPixelsError::Size { - src_type_name: type_name::<&[u8]>(), - dst_type_name: type_name::<&[Pixel]>(), - src_size: bytes.len(), - }, - })?; - - image_rs::ImageBuffer::from_raw(dimens.width, dimens.height, buf.to_vec()) - .ok_or(FromBytesError::NotEnoughBytesForDimensions) -} +#[error("Length of pixel buffer is incorrect for the given image size")] +pub struct PixelBufferLenIncorrectForSize; diff --git a/engine/src/ui/imgui.rs b/engine/src/ui/imgui.rs index bb13d8d..976d5ed 100644 --- a/engine/src/ui/imgui.rs +++ b/engine/src/ui/imgui.rs @@ -1,7 +1,6 @@ use std::path::{Path, PathBuf}; use std::sync::LazyLock; -use dear_imgui_rs::texture::TextureFormat as ImguiTextureFormat; use dear_imgui_rs::{ DrawCmd as ImguiDrawCmd, Key as ImguiKey, @@ -22,11 +21,7 @@ use ecs::{Component, Query, Sole}; use crate::asset::{Assets, Handle as AssetHandle, Label as AssetLabel}; use crate::data_types::dimens::Dimens; use crate::delta_time::DeltaTime; -use crate::image::{ - ColorType as ImageColorType, - FromBytesError as ImageFromBytesError, - Image, -}; +use crate::image::Image; use crate::input::keyboard::{Key, Keyboard}; use crate::input::mouse::{Button as MouseButton, Buttons as MouseButtons, Mouse}; use crate::mesh::vertex_buffer::{ @@ -713,10 +708,13 @@ fn calc_draw_cmd_scissor_box( fn create_font_texture( font_texture_data: &dear_imgui_rs::texture::TextureData, -) -> Result<Texture, ImageFromBytesError> +) -> Result<Texture, crate::image::PixelBufferLenIncorrectForSize> { Ok(Texture { - image: Image::try_from_bytes( + image: Image::from_pixels(crate::image::PixelBuffer::< + crate::data_types::color::Rgba<u8>, + _, + >::new( font_texture_data .pixels() .expect("Font texture data does not contain any pixels"), @@ -728,11 +726,7 @@ fn create_font_texture( "Font texture height value does not fit in 32-bit unsigned int", ), }, - match font_texture_data.format() { - ImguiTextureFormat::RGBA32 => ImageColorType::Rgba8, - ImguiTextureFormat::Alpha8 => unimplemented!(), - }, - )?, + ))?, properties: TextureProperties::builder() .minifying_filter(TextureFiltering::Linear) .magnifying_filter(TextureFiltering::Linear) |
