use crate::{
Extent2, RasterBuf, RasterBufBytes, RasterFormat, RasterLayout, RasterSamplePacked, RasterView,
RasterViewBytes, RasterViewPacked, is,
};
#[doc = crate::_tags!(image lifetime)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
#[derive(Clone, Copy, Debug)]
pub struct RasterRef<'a, T> {
format: RasterFormat,
layout: RasterLayout,
samples: &'a [T],
}
#[doc = crate::_tags!(image lifetime)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
#[derive(Debug)]
pub struct RasterMut<'a, T> {
format: RasterFormat,
layout: RasterLayout,
samples: &'a mut [T],
}
#[doc = crate::_tags!(image lifetime)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
#[derive(Clone, Copy, Debug)]
pub struct RasterBytesRef<'a> {
format: RasterFormat,
layout: RasterLayout,
bytes: &'a [u8],
}
#[doc = crate::_tags!(image lifetime)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
#[derive(Debug)]
pub struct RasterBytesMut<'a> {
format: RasterFormat,
layout: RasterLayout,
bytes: &'a mut [u8],
}
#[rustfmt::skip]
impl<'a, T> RasterRef<'a, T> {
pub const fn new(format: RasterFormat, layout: RasterLayout, samples: &'a [T]) -> Option<Self> {
is! { !layout.is_dense(), return None }
is! { layout.bytes_per_pixel as usize != size_of::<T>(), return None }
let Some(min_len) = layout.min_len_bytes() else { return None; };
let needed = min_len / size_of::<T>();
is! { samples.len() < needed, return None }
Some(Self { format, layout, samples })
}
pub const fn new_unchecked(format: RasterFormat, layout: RasterLayout, samples: &'a [T])
-> Self { Self { format, layout, samples } }
pub const fn dense(format: RasterFormat, extent: Extent2<u32>, samples: &'a [T])
-> Option<Self> {
let Some(layout) = RasterLayout::dense_interleaved(extent, size_of::<T>() as u8)
else { return None; };
Self::new(format, layout, samples)
}
pub const fn format(&self) -> RasterFormat { self.format }
pub const fn layout(&self) -> RasterLayout { self.layout }
pub const fn extent(&self) -> Extent2<u32> { self.layout.extent }
pub const fn samples(&self) -> &'a [T] { self.samples }
}
#[rustfmt::skip]
impl<'a, T> RasterMut<'a, T> {
pub const fn new(format: RasterFormat, layout: RasterLayout, samples: &'a mut [T])
-> Option<Self> {
if !layout.is_dense() { return None; }
if layout.bytes_per_pixel as usize != size_of::<T>() { return None; }
let Some(min_len) = layout.min_len_bytes() else { return None; };
let needed = min_len / size_of::<T>();
if samples.len() < needed { return None; }
Some(Self { format, layout, samples })
}
pub const fn new_unchecked(format: RasterFormat, layout: RasterLayout, samples: &'a mut [T])
-> Self { Self { format, layout, samples } }
pub const fn dense(format: RasterFormat, extent: Extent2<u32>, samples: &'a mut [T])
-> Option<Self> {
let Some(layout) = RasterLayout::dense_interleaved(extent, size_of::<T>() as u8)
else { return None; };
Self::new(format, layout, samples)
}
pub const fn format(&self) -> RasterFormat { self.format }
pub const fn layout(&self) -> RasterLayout { self.layout }
pub const fn extent(&self) -> Extent2<u32> { self.layout.extent }
pub const fn samples(&self) -> &[T] { self.samples }
pub const fn samples_mut(&mut self) -> &mut [T] { self.samples }
pub const fn as_ref(&self) -> RasterRef<'_, T> {
RasterRef { format: self.format, layout: self.layout, samples: self.samples }
}
}
#[rustfmt::skip]
impl<'a> RasterBytesRef<'a> {
pub const fn new(format: RasterFormat, layout: RasterLayout, bytes: &'a [u8])
-> Option<Self> {
is! { raster_depth_u8(format).is_none(), return None }
let Some(min_len) = layout.min_len_bytes() else { return None; };
is! { bytes.len() < min_len, return None }
Some(Self { format, layout, bytes })
}
pub const fn new_unchecked(format: RasterFormat, layout: RasterLayout, bytes: &'a [u8])
-> Self { Self { format, layout, bytes } }
pub const fn dense(format: RasterFormat, extent: Extent2<u32>, bytes: &'a [u8])
-> Option<Self> {
let Some(bytes_per_pixel) = raster_bytes_per_pixel_u8(format) else { return None; };
let Some(layout) = RasterLayout::dense_interleaved(extent, bytes_per_pixel) else {
return None;
};
Self::new(format, layout, bytes)
}
pub const fn format(&self) -> RasterFormat { self.format }
pub const fn layout(&self) -> RasterLayout { self.layout }
pub const fn extent(&self) -> Extent2<u32> { self.layout.extent }
pub const fn bytes(&self) -> &'a [u8] { self.bytes }
}
#[rustfmt::skip]
impl<'a> RasterBytesMut<'a> {
pub const fn new(format: RasterFormat, layout: RasterLayout, bytes: &'a mut [u8])
-> Option<Self> {
is! { raster_depth_u8(format).is_none(), return None }
let Some(min_len) = layout.min_len_bytes() else { return None; };
is! { bytes.len() < min_len, return None }
Some(Self { format, layout, bytes })
}
pub const fn new_unchecked(format: RasterFormat, layout: RasterLayout, bytes: &'a mut [u8])
-> Self { Self { format, layout, bytes } }
pub const fn dense(format: RasterFormat, extent: Extent2<u32>, bytes: &'a mut [u8])
-> Option<Self> {
let Some(bytes_per_pixel) = raster_bytes_per_pixel_u8(format) else { return None; };
let Some(layout) = RasterLayout::dense_interleaved(extent, bytes_per_pixel) else {
return None;
};
Self::new(format, layout, bytes)
}
pub const fn format(&self) -> RasterFormat { self.format }
pub const fn layout(&self) -> RasterLayout { self.layout }
pub const fn extent(&self) -> Extent2<u32> { self.layout.extent }
pub fn bytes(&self) -> &[u8] { self.bytes }
pub fn bytes_mut(&mut self) -> &mut [u8] { self.bytes }
pub fn as_ref(&self) -> RasterBytesRef<'_> {
RasterBytesRef { format: self.format, layout: self.layout, bytes: self.bytes }
}
}
impl<T> RasterView for RasterRef<'_, T> {
type Sample = T;
fn raster_extent(&self) -> Extent2<u32> {
self.layout.extent
}
fn raster_samples(&self) -> &[T] {
self.samples
}
}
impl<T> RasterView for RasterMut<'_, T> {
type Sample = T;
fn raster_extent(&self) -> Extent2<u32> {
self.layout.extent
}
fn raster_samples(&self) -> &[T] {
self.samples
}
}
impl<T> RasterBuf for RasterMut<'_, T> {
fn raster_samples_mut(&mut self) -> &mut [T] {
self.samples
}
}
impl RasterViewBytes for RasterBytesRef<'_> {
fn raster_extent_bytes(&self) -> Extent2<u32> {
self.layout.extent
}
fn raster_depth(&self) -> u8 {
raster_depth_u8(self.format).expect("Raster format must have a valid u8 depth")
}
fn raster_bytes(&self) -> &[u8] {
self.bytes
}
fn raster_bytes_per_line(&self) -> usize {
self.layout.bytes_per_line
}
}
impl RasterViewBytes for RasterBytesMut<'_> {
fn raster_extent_bytes(&self) -> Extent2<u32> {
self.layout.extent
}
fn raster_depth(&self) -> u8 {
raster_depth_u8(self.format).expect("Raster format must have a valid u8 depth")
}
fn raster_bytes(&self) -> &[u8] {
self.bytes
}
fn raster_bytes_per_line(&self) -> usize {
self.layout.bytes_per_line
}
}
impl RasterBufBytes for RasterBytesMut<'_> {
fn raster_bytes_mut(&mut self) -> &mut [u8] {
self.bytes
}
}
impl<T: RasterSamplePacked> RasterViewPacked for RasterRef<'_, T> {
fn raster_depth(&self) -> u8 {
raster_depth_u8(self.format).expect("Raster format must have a valid u8 depth")
}
fn raster_bytes_per_line(&self) -> usize {
self.layout.bytes_per_line
}
}
impl<T: RasterSamplePacked> RasterViewPacked for RasterMut<'_, T> {
fn raster_depth(&self) -> u8 {
raster_depth_u8(self.format).expect("Raster format must have a valid u8 depth")
}
fn raster_bytes_per_line(&self) -> usize {
self.layout.bytes_per_line
}
}
const fn raster_depth_u8(format: RasterFormat) -> Option<u8> {
match format.depth_bits() {
Some(bits) if bits <= u8::MAX as u16 => Some(bits as u8),
_ => None,
}
}
const fn raster_bytes_per_pixel_u8(format: RasterFormat) -> Option<u8> {
match format.stored_bytes_per_pixel() {
Some(bytes) if bytes <= u8::MAX as u16 => Some(bytes as u8),
_ => None,
}
}