#[cfg(feature = "unsafe_layout")]
use crate::MemPod;
use crate::{Extent2, is};
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
pub trait RasterView {
type Sample;
fn raster_extent(&self) -> Extent2<u32>;
fn raster_samples(&self) -> &[Self::Sample];
}
#[rustfmt::skip]
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
pub trait RasterBuf: RasterView {
fn raster_samples_mut(&mut self) -> &mut [Self::Sample];
fn raster_fill(&mut self, sample: Self::Sample) where Self::Sample: Clone {
self.raster_samples_mut().fill(sample);
}
}
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
pub trait Raster: RasterBuf {
type ResizeError;
fn raster_new(extent: Extent2<u32>, fill: Self::Sample) -> Result<Self, Self::ResizeError>
where
Self: Sized,
Self::Sample: Clone;
fn raster_resize(
&mut self,
extent: Extent2<u32>,
fill: Self::Sample,
) -> Result<(), Self::ResizeError>
where
Self::Sample: Clone;
}
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
pub trait RasterViewBytes {
fn raster_extent_bytes(&self) -> Extent2<u32>;
fn raster_depth(&self) -> u8;
fn raster_bytes(&self) -> &[u8];
fn raster_bytes_per_line(&self) -> usize;
fn raster_len_bytes(&self) -> usize {
self.raster_bytes().len()
}
fn raster_bits_per_pixel_bytes(&self) -> Option<u16> {
let [w, _] = self.raster_extent_bytes().dim;
is! { w == 0, return None }
let bits = self.raster_bytes_per_line().checked_mul(8)?;
let bpp = bits / w as usize;
u16::try_from(bpp).ok()
}
}
impl<T> RasterViewBytes for T
where
T: RasterViewPacked,
T::Sample: RasterSampleBytes,
{
fn raster_extent_bytes(&self) -> Extent2<u32> {
self.raster_extent()
}
fn raster_depth(&self) -> u8 {
RasterViewPacked::raster_depth(self)
}
fn raster_bytes(&self) -> &[u8] {
<T::Sample as RasterSampleBytes>::slice_as_bytes(self.raster_samples())
}
fn raster_bytes_per_line(&self) -> usize {
RasterViewPacked::raster_bytes_per_line(self)
}
}
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
pub trait RasterBufBytes: RasterViewBytes {
fn raster_bytes_mut(&mut self) -> &mut [u8];
}
impl<T> RasterBufBytes for T
where
T: RasterBuf + RasterViewPacked,
T::Sample: RasterSampleBytes,
{
fn raster_bytes_mut(&mut self) -> &mut [u8] {
<T::Sample as RasterSampleBytes>::slice_as_bytes_mut(self.raster_samples_mut())
}
}
#[rustfmt::skip]
trait RasterSampleBytes: RasterSamplePacked {
fn slice_as_bytes(samples: &[Self]) -> &[u8] where Self: Sized;
fn slice_as_bytes_mut(samples: &mut [Self]) -> &mut [u8] where Self: Sized;
}
#[rustfmt::skip]
#[cfg(not(feature = "unsafe_layout"))]
mod safe_impls {
impl super::RasterSampleBytes for u8 {
fn slice_as_bytes(samples: &[Self]) -> &[u8] { samples }
fn slice_as_bytes_mut(samples: &mut [Self]) -> &mut [u8] { samples }
}
impl<const N: usize> super::RasterSampleBytes for [u8; N] {
fn slice_as_bytes(samples: &[Self]) -> &[u8] { samples.as_flattened() }
fn slice_as_bytes_mut(samples: &mut [Self]) -> &mut [u8] { samples.as_flattened_mut() }
}
}
#[cfg(feature = "unsafe_layout")]
impl<T: MemPod> RasterSampleBytes for T {
fn slice_as_bytes(samples: &[Self]) -> &[u8] {
let len = core::mem::size_of_val(samples);
unsafe { core::slice::from_raw_parts(samples.as_ptr().cast::<u8>(), len) }
}
fn slice_as_bytes_mut(samples: &mut [Self]) -> &mut [u8] {
let len = core::mem::size_of_val(samples);
unsafe { core::slice::from_raw_parts_mut(samples.as_mut_ptr().cast::<u8>(), len) }
}
}
trait Sealed {}
#[cfg(feature = "unsafe_layout")]
impl<T: MemPod> Sealed for T {}
#[cfg(not(feature = "unsafe_layout"))]
impl Sealed for u8 {}
#[cfg(not(feature = "unsafe_layout"))]
impl<const N: usize> Sealed for [u8; N] {}
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
#[expect(private_bounds, reason = "Sealed trait")]
pub trait RasterSamplePacked: Sealed {}
impl<T: Sealed> RasterSamplePacked for T {}
#[doc = crate::_tags!(image)]
#[doc = crate::_doc_meta!{location("media/visual/image/raster")}]
pub trait RasterViewPacked: RasterView
where
Self::Sample: RasterSamplePacked,
{
fn raster_depth(&self) -> u8;
fn raster_bits_per_pixel(&self) -> u16 {
(size_of::<Self::Sample>() * 8) as u16
}
fn raster_bytes_per_pixel(&self) -> usize {
size_of::<Self::Sample>()
}
fn raster_bytes_per_line(&self) -> usize {
let [w, _h] = self.raster_extent().dim;
w as usize * self.raster_bytes_per_pixel()
}
}