use crate::{
formats::PixelFormatSpec,
math::{PixelBox, PixelSize},
};
pub trait BitmapRawData {
fn data(&self) -> &[u8];
fn width(&self) -> usize;
fn height(&self) -> usize;
fn stride(&self) -> usize;
fn size(&self) -> PixelSize {
PixelSize::new(self.width() as i32, self.height() as i32)
}
}
pub trait BitmapRawDataMut: BitmapRawData {
fn data_mut(&mut self) -> &mut [u8];
}
#[derive(PartialEq, Clone)]
pub struct OwnedBitmapData {
pub(crate) data: Vec<u8>,
pub(crate) width: usize,
pub(crate) height: usize,
pub(crate) stride: usize,
}
impl BitmapRawData for OwnedBitmapData {
fn data(&self) -> &[u8] {
self.data.as_slice()
}
fn width(&self) -> usize {
self.width
}
fn height(&self) -> usize {
self.height
}
fn stride(&self) -> usize {
self.stride
}
}
impl BitmapRawDataMut for OwnedBitmapData {
fn data_mut(&mut self) -> &mut [u8] {
self.data.as_mut_slice()
}
}
#[derive(Clone)]
pub struct BorrowedBitmapData<'l> {
pub(crate) data: &'l [u8],
pub(crate) width: usize,
pub(crate) height: usize,
pub(crate) stride: usize,
}
impl<'l> BitmapRawData for BorrowedBitmapData<'l> {
fn data(&self) -> &[u8] {
self.data
}
fn width(&self) -> usize {
self.width
}
fn height(&self) -> usize {
self.height
}
fn stride(&self) -> usize {
self.stride
}
}
pub struct MutableBitmapData<'l> {
pub(crate) data: &'l mut [u8],
pub(crate) width: usize,
pub(crate) height: usize,
pub(crate) stride: usize,
}
impl<'l> BitmapRawData for MutableBitmapData<'l> {
fn data(&self) -> &[u8] {
self.data
}
fn width(&self) -> usize {
self.width
}
fn height(&self) -> usize {
self.height
}
fn stride(&self) -> usize {
self.stride
}
}
impl<'l> BitmapRawDataMut for MutableBitmapData<'l> {
fn data_mut(&mut self) -> &mut [u8] {
self.data
}
}
pub trait BitmapAccess<Format: PixelFormatSpec>: std::fmt::Debug + BitmapRawData {
fn make_view(&self, area: PixelBox) -> BitmapRef<'_, Format> {
let data_offset =
(area.min.y as usize * self.stride()) + area.min.x as usize * Format::PIXEL_STRIDE;
BitmapRef::new_with_stride(
&self.data()[data_offset..],
area.width() as usize,
area.height() as usize,
self.stride(),
)
}
}
pub trait BitmapAccessMut<Format: PixelFormatSpec>:
BitmapAccess<Format> + BitmapRawDataMut
{
fn make_view_mut(&mut self, area: PixelBox) -> BitmapMut<'_, Format> {
let data_offset =
(area.min.y as usize * self.stride()) + area.min.x as usize * Format::PIXEL_STRIDE;
let stride = self.stride();
BitmapMut::new_with_stride(
&mut self.data_mut()[data_offset..],
area.width() as usize,
area.height() as usize,
stride,
)
}
}
#[derive(Clone, PartialEq)]
pub struct Bitmap<Format: PixelFormatSpec> {
data: OwnedBitmapData,
_ghost: std::marker::PhantomData<Format>,
}
impl<Format: PixelFormatSpec> Bitmap<Format> {
pub fn new(width: usize, height: usize) -> Self {
Self {
data: OwnedBitmapData {
data: vec![0; width * height * Format::PIXEL_STRIDE],
width,
height,
stride: width * Format::PIXEL_STRIDE,
},
_ghost: Default::default(),
}
}
pub fn new_from_vec(data: Vec<u8>, width: usize, height: usize, stride: usize) -> Self {
Self {
data: OwnedBitmapData {
data,
width,
height,
stride,
},
_ghost: Default::default(),
}
}
pub fn as_ref(&self) -> BitmapRef<'_, Format> {
BitmapRef::new_with_stride(
&self.data.data,
self.data.width,
self.data.height,
self.data.stride,
)
}
pub fn as_mut(&mut self) -> BitmapMut<'_, Format> {
BitmapMut::new_with_stride(
&mut self.data.data,
self.data.width,
self.data.height,
self.data.stride,
)
}
}
impl<Format: PixelFormatSpec> BitmapRawData for Bitmap<Format> {
fn data(&self) -> &[u8] {
&self.data.data
}
fn stride(&self) -> usize {
self.data.stride
}
fn width(&self) -> usize {
self.data.width
}
fn height(&self) -> usize {
self.data.height
}
}
impl<Format: PixelFormatSpec> BitmapRawDataMut for Bitmap<Format> {
fn data_mut(&mut self) -> &mut [u8] {
&mut self.data.data
}
}
impl<Format: PixelFormatSpec> std::fmt::Debug for Bitmap<Format> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Bitmap")
.field("format", &Format::NAME)
.field("width", &self.data.width)
.field("height", &self.data.height)
.field("stride", &self.data.stride)
.finish_non_exhaustive()
}
}
impl<Format: PixelFormatSpec> BitmapAccess<Format> for Bitmap<Format> {}
impl<Format: PixelFormatSpec> BitmapAccessMut<Format> for Bitmap<Format> {}
#[derive(Clone)]
pub struct BitmapRef<'l, Format: PixelFormatSpec> {
data: BorrowedBitmapData<'l>,
_ghost: std::marker::PhantomData<Format>,
}
impl<'l, Format: PixelFormatSpec> BitmapRef<'l, Format> {
pub fn new(data: &'l [u8], width: usize, height: usize) -> Self {
Self {
data: BorrowedBitmapData {
data,
width,
height,
stride: width * Format::PIXEL_STRIDE,
},
_ghost: Default::default(),
}
}
pub fn new_with_stride(data: &'l [u8], width: usize, height: usize, stride: usize) -> Self {
Self {
data: BorrowedBitmapData {
data,
width,
height,
stride,
},
_ghost: Default::default(),
}
}
}
impl<'l, Format: PixelFormatSpec> BitmapRawData for BitmapRef<'l, Format> {
fn data(&self) -> &[u8] {
self.data.data
}
fn width(&self) -> usize {
self.data.width
}
fn height(&self) -> usize {
self.data.height
}
fn stride(&self) -> usize {
self.data.stride
}
}
impl<'l, Format: PixelFormatSpec> std::fmt::Debug for BitmapRef<'l, Format> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct("BitmapRef")
.field("format", &Format::NAME)
.field("width", &self.data.width)
.field("height", &self.data.height)
.field("stride", &self.data.stride)
.finish_non_exhaustive()
}
}
impl<'l, Format: PixelFormatSpec> BitmapAccess<Format> for BitmapRef<'l, Format> {}
pub struct BitmapMut<'l, Format: PixelFormatSpec> {
data: MutableBitmapData<'l>,
_ghost: std::marker::PhantomData<Format>,
}
impl<'l, Format: PixelFormatSpec> BitmapMut<'l, Format> {
pub fn new(data: &'l mut [u8], width: usize, height: usize) -> Self {
Self {
data: MutableBitmapData {
data,
width,
height,
stride: width * Format::PIXEL_STRIDE,
},
_ghost: Default::default(),
}
}
pub fn new_with_stride(data: &'l mut [u8], width: usize, height: usize, stride: usize) -> Self {
Self {
data: MutableBitmapData {
data,
width,
height,
stride,
},
_ghost: Default::default(),
}
}
pub fn new_from_raw(raw: &'l mut dyn BitmapRawDataMut) -> Self {
Self {
data: MutableBitmapData {
width: raw.width(),
height: raw.height(),
stride: raw.stride(),
data: raw.data_mut(),
},
_ghost: Default::default(),
}
}
}
impl<'l, Format: PixelFormatSpec> std::fmt::Debug for BitmapMut<'l, Format> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct("BitmapMut")
.field("format", &Format::NAME)
.field("width", &self.data.width)
.field("height", &self.data.height)
.field("stride", &self.data.stride)
.finish_non_exhaustive()
}
}
impl<'l, Format: PixelFormatSpec> BitmapRawData for BitmapMut<'l, Format> {
fn data(&self) -> &[u8] {
&self.data.data
}
fn width(&self) -> usize {
self.data.width
}
fn height(&self) -> usize {
self.data.height
}
fn stride(&self) -> usize {
self.data.stride
}
}
impl<'l, Format: PixelFormatSpec> BitmapRawDataMut for BitmapMut<'l, Format> {
fn data_mut(&mut self) -> &mut [u8] {
&mut self.data.data
}
}
impl<'l, Format: PixelFormatSpec> BitmapAccess<Format> for BitmapMut<'l, Format> {}
impl<'l, Format: PixelFormatSpec> BitmapAccessMut<Format> for BitmapMut<'l, Format> {}