devela/media/visual/image/raster/
borrow.rs1use crate::{Boundary1d, Extent2, PhantomData, is};
12use crate::{RasterBuf, RasterBufBytes, RasterFormat, RasterLayout, RasterSamplePacked};
13use crate::{RasterView, RasterViewBytes, RasterViewPacked};
14
15#[doc = crate::_tags!(image lifetime)]
18#[doc = crate::_doc_meta!{
20 location("media/visual/image/raster", struct RasterSlice),
21 #[cfg(target_pointer_width = "32")]
22 test_size_of(RasterSlice<u32, &[u32]> = 28|224),
23 #[cfg(target_pointer_width = "64")]
24 test_size_of(RasterSlice<u32, &[u32]> = 40|320),
25}]
26#[derive(Clone, Copy, Debug)]
37pub struct RasterSlice<T, B> {
38 format: RasterFormat,
39 layout: RasterLayout,
40 samples: B,
41 _sample: PhantomData<fn() -> T>,
42}
43
44#[rustfmt::skip]
45impl<T, B> RasterSlice<T, B> {
46 pub const fn format(&self) -> RasterFormat { self.format }
48 pub const fn layout(&self) -> RasterLayout { self.layout }
50 pub const fn extent(&self) -> Extent2<u32> { self.layout.extent }
52}
53#[rustfmt::skip]
54impl<'a, T> RasterSlice<T, &'a [T]> {
55 pub const fn new(format: RasterFormat, layout: RasterLayout, samples: &'a [T]) -> Option<Self> {
65 let Some(needed) = raster_typed_len::<T>(format, layout) else { return None; };
66 if samples.len() < needed { return None; }
67 let (samples, _) = samples.split_at(needed);
68 Some(Self { format, layout, samples, _sample: PhantomData })
69 }
70 pub const fn new_unchecked(format: RasterFormat, layout: RasterLayout, samples: &'a [T])
75 -> Self { Self { format, layout, samples, _sample: PhantomData }
76 }
77 pub const fn dense(format: RasterFormat, extent: Extent2<u32>, samples: &'a [T])
79 -> Option<Self> {
80 let Some(bytes_per_pixel) = raster_sample_bytes_u8::<T>() else { return None; };
81 let Some(layout) = RasterLayout::dense_interleaved(extent, bytes_per_pixel)
82 else { return None; };
83 Self::new(format, layout, samples)
84 }
85
86 pub const fn samples(&self) -> &[T] { self.samples }
88}
89#[rustfmt::skip]
90impl<'a, T> RasterSlice<T, &'a mut [T]> {
91 pub const fn new_mut(format: RasterFormat, layout: RasterLayout, samples: &'a mut [T])
101 -> Option<Self> {
102 let Some(needed) = raster_typed_len::<T>(format, layout) else { return None; };
103 if samples.len() < needed { return None; }
104 let (samples, _) = samples.split_at_mut(needed);
105 Some(Self { format, layout, samples, _sample: PhantomData })
106 }
107 pub const fn new_mut_unchecked(format: RasterFormat, layout: RasterLayout, samples: &'a mut [T])
112 -> Self { Self { format, layout, samples, _sample: PhantomData }
113 }
114 pub const fn dense_mut(format: RasterFormat, extent: Extent2<u32>, samples: &'a mut [T])
116 -> Option<Self> {
117 let Some(bytes_per_pixel) = raster_sample_bytes_u8::<T>() else { return None; };
118 let Some(layout) = RasterLayout::dense_interleaved(extent, bytes_per_pixel)
119 else { return None; };
120 Self::new_mut(format, layout, samples)
121 }
122
123 pub const fn samples(&self) -> &[T] { self.samples }
125 pub const fn samples_mut(&mut self) -> &mut [T] { self.samples }
127 pub const fn as_ref(&self) -> RasterSlice<T, &[T]> {
129 RasterSlice {
130 format: self.format, layout: self.layout, samples: self.samples, _sample: PhantomData,
131 }
132 }
133}
134
135impl<T, B: AsRef<[T]>> RasterView for RasterSlice<T, B> {
136 type Sample = T;
137 fn raster_extent(&self) -> Extent2<u32> {
138 self.layout.extent
139 }
140 fn raster_samples(&self) -> &[T] {
141 self.samples.as_ref()
142 }
143}
144impl<T, B: AsRef<[T]> + AsMut<[T]>> RasterBuf for RasterSlice<T, B> {
145 fn raster_samples_mut(&mut self) -> &mut [T] {
146 self.samples.as_mut()
147 }
148}
149impl<T: RasterSamplePacked, B: AsRef<[T]>> RasterViewPacked for RasterSlice<T, B> {
150 fn raster_depth(&self) -> u8 {
151 raster_depth_u8(self.format).expect("Raster format must have a valid u8 depth")
152 }
153 fn raster_bytes_per_line(&self) -> usize {
154 self.layout.bytes_per_line as usize
155 }
156}
157
158#[doc = crate::_tags!(image lifetime)]
161#[doc = crate::_doc_meta!{
163 location("media/visual/image/raster", struct RasterByteSlice),
164 #[cfg(target_pointer_width = "32")]
165 test_size_of(RasterByteSlice<&[u8]> = 28|224),
166 #[cfg(target_pointer_width = "64")]
167 test_size_of(RasterByteSlice<&[u8]> = 40|320),
168}]
169#[derive(Clone, Copy, Debug)]
177pub struct RasterByteSlice<B> {
178 format: RasterFormat,
179 layout: RasterLayout,
180 bytes: B,
181}
182#[rustfmt::skip]
183impl<B> RasterByteSlice<B> {
184 pub const fn format(&self) -> RasterFormat { self.format }
186 pub const fn layout(&self) -> RasterLayout { self.layout }
188 pub const fn extent(&self) -> Extent2<u32> { self.layout.extent }
190}
191#[rustfmt::skip]
192impl<'a> RasterByteSlice<&'a [u8]> {
193 pub const fn new(format: RasterFormat, layout: RasterLayout, bytes: &'a [u8]) -> Option<Self> {
202 let Some(min_len) = raster_byte_len(format, layout) else { return None; };
203 if bytes.len() < min_len { return None; }
204 Some(Self { format, layout, bytes })
205 }
206 pub const fn new_unchecked(format: RasterFormat, layout: RasterLayout, bytes: &'a [u8])
210 -> Self { Self { format, layout, bytes }
211 }
212 pub const fn dense(format: RasterFormat, extent: Extent2<u32>, bytes: &'a [u8])
214 -> Option<Self> {
215 let Some(bytes_per_pixel) = raster_bytes_per_pixel_u8(format) else { return None; };
216 let Some(layout) = RasterLayout::dense_interleaved(extent, bytes_per_pixel) else {
217 return None;
218 };
219 Self::new(format, layout, bytes)
220 }
221
222 pub const fn bytes(&self) -> &'a [u8] { self.bytes }
224}
225#[rustfmt::skip]
226impl<'a> RasterByteSlice<&'a mut [u8]> {
227 pub const fn new_mut(format: RasterFormat, layout: RasterLayout, bytes: &'a mut [u8])
236 -> Option<Self> {
237 let Some(min_len) = raster_byte_len(format, layout) else { return None; };
238 if bytes.len() < min_len { return None; }
239 Some(Self { format, layout, bytes })
240 }
241
242 pub const fn new_mut_unchecked(format: RasterFormat, layout: RasterLayout, bytes: &'a mut [u8])
246 -> Self { Self { format, layout, bytes }
247 }
248 pub const fn dense_mut(format: RasterFormat, extent: Extent2<u32>, bytes: &'a mut [u8])
250 -> Option<Self> {
251 let Some(bytes_per_pixel) = raster_bytes_per_pixel_u8(format) else { return None; };
252 let Some(layout) = RasterLayout::dense_interleaved(extent, bytes_per_pixel) else {
253 return None;
254 };
255 Self::new_mut(format, layout, bytes)
256 }
257
258 pub const fn bytes(&self) -> &[u8] { self.bytes }
260 pub const fn bytes_mut(&mut self) -> &mut [u8] { self.bytes }
262 pub const fn as_ref(&self) -> RasterByteSlice<&[u8]> {
264 RasterByteSlice { format: self.format, layout: self.layout, bytes: self.bytes }
265 }
266}
267
268impl<B: AsRef<[u8]>> RasterViewBytes for RasterByteSlice<B> {
269 fn raster_extent_bytes(&self) -> Extent2<u32> {
270 self.layout.extent
271 }
272 fn raster_depth(&self) -> u8 {
273 raster_depth_u8(self.format).expect("Raster format must have a valid u8 depth")
274 }
275 fn raster_bytes(&self) -> &[u8] {
276 self.bytes.as_ref()
277 }
278 fn raster_bytes_per_pixel_bytes(&self) -> usize {
279 self.layout.bytes_per_pixel as usize
280 }
281 fn raster_bytes_per_line(&self) -> usize {
282 self.layout.bytes_per_line as usize
283 }
284 fn raster_row_start_bytes(&self) -> Boundary1d {
285 self.layout.row_start
286 }
287}
288impl<B: AsRef<[u8]> + AsMut<[u8]>> RasterBufBytes for RasterByteSlice<B> {
289 fn raster_bytes_mut(&mut self) -> &mut [u8] {
290 self.bytes.as_mut()
291 }
292}
293
294const fn raster_depth_u8(format: RasterFormat) -> Option<u8> {
297 match format.depth_bits() {
298 Some(bits) if bits <= u8::MAX as u16 => Some(bits as u8),
299 _ => None,
300 }
301}
302const fn raster_bytes_per_pixel_u8(format: RasterFormat) -> Option<u8> {
303 match format.stored_bytes_per_pixel() {
304 Some(bytes) if bytes <= u8::MAX as u16 => Some(bytes as u8),
305 _ => None,
306 }
307}
308const fn raster_sample_bytes_u8<T>() -> Option<u8> {
310 let bytes = size_of::<T>();
311 is! { bytes == 0 || bytes > u8::MAX as usize, None, Some(bytes as u8) }
312}
313const fn raster_typed_len<T>(format: RasterFormat, layout: RasterLayout) -> Option<usize> {
315 let Some(sample_bytes) = raster_sample_bytes_u8::<T>() else {
316 return None;
317 };
318 is! { !layout.is_dense(), return None } is! { !matches!(layout.row_start, Boundary1d::Upper), return None }
322 is! { layout.bytes_per_pixel != sample_bytes, return None }
323 is! { !raster_format_matches_layout(format, layout), return None }
324 raster_sample_len(layout.extent)
325}
326const fn raster_byte_len(format: RasterFormat, layout: RasterLayout) -> Option<usize> {
328 is! { !raster_format_matches_layout(format, layout), return None }
329 layout.min_len_bytes() }
331const fn raster_format_matches_layout(format: RasterFormat, layout: RasterLayout) -> bool {
336 let Some(_depth) = raster_depth_u8(format) else {
337 return false;
338 };
339 let Some(bytes_per_pixel) = raster_bytes_per_pixel_u8(format) else {
340 return false;
341 };
342 bytes_per_pixel == layout.bytes_per_pixel
343}
344const fn raster_sample_len(extent: Extent2<u32>) -> Option<usize> {
346 let [width, height] = extent.dim;
347 (width as usize).checked_mul(height as usize)
348}