fer/
image.rs

1use std::marker::PhantomData;
2use std::num::NonZeroU32;
3
4use crate::pixels::PixelExt;
5use crate::{error, ImageView, ImageViewMut};
6
7#[derive(Debug)]
8enum BufferContainer<'a> {
9    MutU8(&'a mut [u8]),
10    VecU8(Vec<u8>),
11}
12
13impl<'a> BufferContainer<'a> {
14    fn as_vec(&self) -> Vec<u8> {
15        match self {
16            Self::MutU8(slice) => slice.to_vec(),
17            Self::VecU8(vec) => vec.clone(),
18        }
19    }
20}
21
22/// Simple container of image data.
23#[derive(Debug)]
24pub struct Image<'a, P: PixelExt> {
25    width: NonZeroU32,
26    height: NonZeroU32,
27    buffer: BufferContainer<'a>,
28    pixel_type: PhantomData<P>,
29}
30
31impl<'a, P: PixelExt> Image<'a, P> {
32    /// Create empty image with given dimensions and pixel type.
33    pub fn new(width: NonZeroU32, height: NonZeroU32) -> Self {
34        let pixels_count = (width.get() * height.get()) as usize;
35        let buffer = BufferContainer::VecU8(vec![0; pixels_count * P::size()]);
36        Self {
37            width,
38            height,
39            buffer,
40            pixel_type: PhantomData,
41        }
42    }
43
44    pub unsafe fn from_vec_u8(width: NonZeroU32, height: NonZeroU32, buffer: Vec<u8>) -> Self {
45        let size = (width.get() * height.get()) as usize * P::size();
46        if buffer.len() < size {
47            error!();
48        }
49        Self {
50            width,
51            height,
52            buffer: BufferContainer::VecU8(buffer),
53            pixel_type: PhantomData,
54        }
55    }
56
57    pub unsafe fn from_slice_u8(
58        width: NonZeroU32,
59        height: NonZeroU32,
60        buffer: &'a mut [u8],
61    ) -> Self {
62        let size = (width.get() * height.get()) as usize * P::size();
63        if buffer.len() < size {
64            error!();
65        }
66        Self {
67            width,
68            height,
69            buffer: BufferContainer::MutU8(buffer),
70            pixel_type: PhantomData,
71        }
72    }
73
74    /// Creates a copy of the image.
75    pub fn copy(&self) -> Image<'static, P> {
76        Image {
77            width: self.width,
78            height: self.height,
79            buffer: BufferContainer::VecU8(self.buffer.as_vec()),
80            pixel_type: self.pixel_type,
81        }
82    }
83
84    #[inline(always)]
85    pub fn width(&self) -> NonZeroU32 {
86        self.width
87    }
88
89    #[inline(always)]
90    pub fn height(&self) -> NonZeroU32 {
91        self.height
92    }
93
94    /// Buffer with image pixels.
95    #[inline(always)]
96    pub fn buffer(&self) -> &[u8] {
97        match &self.buffer {
98            BufferContainer::MutU8(p) => p,
99            BufferContainer::VecU8(v) => v,
100        }
101    }
102
103    /// Mutable buffer with image pixels.
104    #[inline(always)]
105    pub fn buffer_mut(&mut self) -> &mut [u8] {
106        match &mut self.buffer {
107            BufferContainer::MutU8(p) => p,
108            BufferContainer::VecU8(ref mut v) => v.as_mut_slice(),
109        }
110    }
111
112    #[inline(always)]
113    pub fn into_vec(self) -> Vec<u8> {
114        match self.buffer {
115            BufferContainer::MutU8(p) => p.into(),
116            BufferContainer::VecU8(v) => v,
117        }
118    }
119
120    #[inline(always)]
121    pub unsafe fn view(&self) -> ImageView<P> {
122        ImageView::new(self.width, self.height, self.buffer())
123    }
124
125    #[inline(always)]
126    pub unsafe fn view_mut(&mut self) -> ImageViewMut<P> {
127        ImageViewMut::new(self.width, self.height, self.buffer_mut())
128    }
129}
130
131/// Generic image container for internal purposes.
132pub(crate) struct InnerImage<'a, P>
133where
134    P: PixelExt,
135{
136    width: NonZeroU32,
137    height: NonZeroU32,
138    pixels: &'a mut [P],
139}
140
141impl<'a, P> InnerImage<'a, P>
142where
143    P: PixelExt,
144{
145    pub fn new(width: NonZeroU32, height: NonZeroU32, pixels: &'a mut [P]) -> Self {
146        Self {
147            width,
148            height,
149            pixels,
150        }
151    }
152
153    #[inline(always)]
154    pub unsafe fn src_view(&self) -> ImageView<P> {
155        ImageView::from_pixels(self.width, self.height, self.pixels)
156    }
157
158    #[inline(always)]
159    pub unsafe fn dst_view(&mut self) -> ImageViewMut<P> {
160        ImageViewMut::from_pixels(self.width, self.height, self.pixels)
161    }
162}