summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engine/src/image.rs174
-rw-r--r--engine/src/ui/imgui.rs20
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)