use core::ops::{Index, IndexMut};
use std::mem;
use num_traits::identities::Zero;
use crate::core::iter::{PixelIter, PixelIterMut};
use crate::core::traits::{GenericImage, GenericImageView, Pixel};
macro_rules! impl_GenericImageView {
($id:ident) => {
type T = T;
fn width(&self) -> u32 {
self.width
}
fn height(&self) -> u32 {
self.height
}
fn pixel(&self, x: u32, y: u32) -> Option<Self::T> {
if x >= self.width() || y >= self.height() {
return None;
}
Some(self[y as usize][x as usize])
}
};
}
macro_rules! impl_GenericImage {
($id:ident) => {
fn set_pixel(&mut self, x: u32, y: u32, pix: &Self::T) -> Result<(), ()> {
if x >= self.width() || y >= self.height() {
return Err(());
}
self[y as usize][x as usize] = *pix;
Ok(())
}
};
}
macro_rules! impl_Index {
($id:ident) => {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
let pixels_per_row = self.width() / T::subpixels() as u32;
let stride_elems = self.stride() / mem::size_of::<T::T>();
let off: usize = index * stride_elems;
let slice = &self.raw[off..off + stride_elems];
let (head, body, _tail) = unsafe { slice.align_to::<T>() };
assert!(head.is_empty(), "raw data is not aligned");
assert_eq!(
body.len(),
pixels_per_row as usize,
"invalid number of row items"
);
body
}
};
}
macro_rules! impl_IndexMut {
($id:ident) => {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let pixels_per_row = self.width() / T::subpixels() as u32;
let stride_elems = self.stride() / mem::size_of::<T::T>();
let off: usize = index * stride_elems;
let slice = &mut self.raw[off..off + stride_elems];
let (head, body, _tail) = unsafe { slice.align_to_mut::<T>() };
assert!(head.is_empty(), "raw data is not aligned");
assert_eq!(
body.len(),
pixels_per_row as usize,
"invalid number of row items"
);
body
}
};
}
macro_rules! impl_Iterator {
($id:ident) => {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.x >= self.width {
self.x = 0;
self.y += 1;
}
if self.y >= self.height {
return None;
}
let x = self.x;
self.x += 1;
Some(&self.img[self.y as usize][x as usize])
}
};
}
macro_rules! impl_IteratorMut {
($id:ident) => {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if self.x >= self.width {
self.x = 0;
self.y += 1;
}
if self.y >= self.height {
return None;
}
let x = self.x;
self.x += 1;
unsafe { mem::transmute(&self.img[self.y as usize][x as usize]) }
}
};
}
pub struct ImageView<'a, T: Pixel> {
raw: &'a [T::T],
width: u32,
height: u32,
stride: usize,
}
impl<'a, T: Pixel> ImageView<'a, T> {
pub fn new(raw: &'a [T::T], width: u32, height: u32) -> Option<Self> {
if raw.len() % height as usize != 0 {
return None;
}
let pixels_per_row = width / T::subpixels() as u32;
let min_stride = pixels_per_row as usize * T::channels() as usize * mem::size_of::<T::T>();
let stride = raw.len() * mem::size_of::<T::T>() / height as usize;
if stride < min_stride {
return None;
}
Some(ImageView {
raw,
width,
height,
stride,
})
}
pub fn raw(&self) -> &[T::T] {
&self.raw
}
pub fn stride(&self) -> usize {
self.stride
}
}
impl<'a, T: Pixel + 'a> GenericImageView<'a> for ImageView<'a, T> {
impl_GenericImageView!(ImageView);
type SubImage = SubImageView<'a, Self>;
fn view(&'a self, x: u32, y: u32, width: u32, height: u32) -> Option<Self::SubImage> {
SubImageView::new(self, x, y, width, height)
}
}
impl<'a, T: Pixel> Index<usize> for ImageView<'a, T> {
impl_Index!(ImageView);
}
impl<'a, T: Pixel> Iterator for PixelIter<'a, ImageView<'a, T>> {
impl_Iterator!(ImageView);
}
impl<'a, T: Pixel> IntoIterator for &'a ImageView<'a, T> {
type Item = &'a T;
type IntoIter = PixelIter<'a, ImageView<'a, T>>;
fn into_iter(self) -> Self::IntoIter {
PixelIter::new(self)
}
}
pub struct ImageViewMut<'a, T: Pixel> {
raw: &'a mut [T::T],
width: u32,
height: u32,
stride: usize,
}
impl<'a, T: Pixel> ImageViewMut<'a, T> {
pub fn new(raw: &'a mut [T::T], width: u32, height: u32) -> Option<Self> {
if raw.len() % height as usize != 0 {
return None;
}
let pixels_per_row = width / T::subpixels() as u32;
let min_stride = pixels_per_row as usize * T::channels() as usize * mem::size_of::<T::T>();
let stride = raw.len() * mem::size_of::<T::T>() / height as usize;
if stride < min_stride {
return None;
}
Some(ImageViewMut {
raw,
width,
height,
stride,
})
}
pub fn raw(&self) -> &[T::T] {
&self.raw
}
pub fn raw_mut(&mut self) -> &mut [T::T] {
&mut self.raw
}
pub fn stride(&self) -> usize {
self.stride
}
}
impl<'a, T: Pixel + 'a> GenericImageView<'a> for ImageViewMut<'a, T> {
impl_GenericImageView!(ImageViewMut);
type SubImage = SubImageView<'a, Self>;
fn view(&'a self, x: u32, y: u32, width: u32, height: u32) -> Option<Self::SubImage> {
SubImageView::new(self, x, y, width, height)
}
}
impl<'a, T: Pixel + 'a> GenericImage<'a> for ImageViewMut<'a, T> {
impl_GenericImage!(ImageViewMut);
}
impl<'a, T: Pixel> Index<usize> for ImageViewMut<'a, T> {
impl_Index!(ImageViewMut);
}
impl<'a, T: Pixel> IndexMut<usize> for ImageViewMut<'a, T> {
impl_IndexMut!(ImageViewMut);
}
impl<'a, T: Pixel> Iterator for PixelIter<'a, ImageViewMut<'a, T>> {
impl_Iterator!(ImageViewMut);
}
impl<'a, T: Pixel> Iterator for PixelIterMut<'a, ImageViewMut<'a, T>> {
impl_IteratorMut!(ImageViewMut);
}
impl<'a, T: Pixel> IntoIterator for &'a ImageViewMut<'a, T> {
type Item = &'a T;
type IntoIter = PixelIter<'a, ImageViewMut<'a, T>>;
fn into_iter(self) -> Self::IntoIter {
PixelIter::new(self)
}
}
impl<'a, T: Pixel> IntoIterator for &'a mut ImageViewMut<'a, T> {
type Item = &'a mut T;
type IntoIter = PixelIterMut<'a, ImageViewMut<'a, T>>;
fn into_iter(self) -> Self::IntoIter {
PixelIterMut::new(self)
}
}
pub struct ImageBuffer<T: Pixel> {
raw: Vec<T::T>,
width: u32,
height: u32,
stride: usize,
}
impl<T: Pixel> ImageBuffer<T> {
pub fn new(width: u32, height: u32) -> Self {
let pixels_per_row = width / T::subpixels() as u32;
let stride = pixels_per_row as usize * T::channels() as usize * mem::size_of::<T::T>();
ImageBuffer {
raw: vec![T::T::zero(); height as usize * pixels_per_row as usize * T::len()],
width,
height,
stride,
}
}
pub fn from_raw(width: u32, height: u32, raw: Vec<T::T>) -> Option<Self> {
if raw.len() % height as usize != 0 {
return None;
}
let pixels_per_row = width / T::subpixels() as u32;
let min_stride = pixels_per_row as usize * T::channels() as usize * mem::size_of::<T::T>();
let stride = raw.len() * mem::size_of::<T::T>() / height as usize;
if stride < min_stride {
return None;
}
Some(ImageBuffer {
raw,
width,
height,
stride,
})
}
pub fn raw(&self) -> &[T::T] {
&self.raw
}
pub fn raw_mut(&mut self) -> &mut [T::T] {
&mut self.raw
}
pub fn stride(&self) -> usize {
self.stride
}
}
impl<'a, T: Pixel + 'a> GenericImageView<'a> for ImageBuffer<T> {
impl_GenericImageView!(ImageBuffer);
type SubImage = SubImageView<'a, Self>;
fn view(&'a self, x: u32, y: u32, width: u32, height: u32) -> Option<Self::SubImage> {
SubImageView::new(self, x, y, width, height)
}
}
impl<'a, T: Pixel + 'a> GenericImage<'a> for ImageBuffer<T> {
impl_GenericImage!(ImageBuffer);
}
impl<T: Pixel> Index<usize> for ImageBuffer<T> {
impl_Index!(ImageBuffer);
}
impl<T: Pixel> IndexMut<usize> for ImageBuffer<T> {
impl_IndexMut!(ImageBuffer);
}
impl<'a, T: Pixel> Iterator for PixelIter<'a, ImageBuffer<T>> {
impl_Iterator!(ImageBuffer);
}
impl<'a, T: Pixel> Iterator for PixelIterMut<'a, ImageBuffer<T>> {
impl_IteratorMut!(ImageBuffer);
}
impl<'a, T: Pixel> IntoIterator for &'a ImageBuffer<T> {
type Item = &'a T;
type IntoIter = PixelIter<'a, ImageBuffer<T>>;
fn into_iter(self) -> Self::IntoIter {
PixelIter::new(self)
}
}
impl<'a, T: Pixel> IntoIterator for &'a mut ImageBuffer<T> {
type Item = &'a mut T;
type IntoIter = PixelIterMut<'a, ImageBuffer<T>>;
fn into_iter(self) -> Self::IntoIter {
PixelIterMut::new(self)
}
}
impl<T: Pixel> Into<Vec<T::T>> for ImageBuffer<T> {
fn into(self) -> Vec<T::T> {
self.raw
}
}
impl<'a, T: Pixel> From<&ImageView<'a, T>> for ImageBuffer<T> {
fn from(view: &ImageView<'a, T>) -> Self {
ImageBuffer::from_raw(view.width(), view.height(), view.raw().to_vec()).unwrap()
}
}
impl<'a, T: Pixel> From<&ImageViewMut<'a, T>> for ImageBuffer<T> {
fn from(view: &ImageViewMut<'a, T>) -> Self {
ImageBuffer::from_raw(view.width(), view.height(), view.raw().to_vec()).unwrap()
}
}
pub struct SubImageView<'a, I: GenericImageView<'a>> {
parent: &'a I,
x: u32,
y: u32,
width: u32,
height: u32,
}
impl<'a, I: GenericImageView<'a>> SubImageView<'a, I> {
pub fn new(parent: &'a I, x: u32, y: u32, width: u32, height: u32) -> Option<Self> {
if x + width > parent.width() || y + height > parent.height() {
return None;
}
Some(SubImageView {
parent,
x,
y,
width,
height,
})
}
}
impl<'a, I: GenericImageView<'a>> GenericImageView<'a> for SubImageView<'a, I> {
type T = I::T;
type SubImage = Self;
fn width(&self) -> u32 {
self.width
}
fn height(&self) -> u32 {
self.height
}
fn pixel(&self, x: u32, y: u32) -> Option<Self::T> {
self.parent.pixel(x + self.x, y + self.y)
}
fn view(&'a self, x: u32, y: u32, width: u32, height: u32) -> Option<Self::SubImage> {
SubImageView::new(self.parent, x + self.x, y + self.y, width, height)
}
}
impl<'a, T: Pixel> Index<usize> for SubImageView<'a, ImageView<'a, T>> {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
let row = &self.parent[index + self.y as usize];
&row[self.x as usize..]
}
}
impl<'a, T: Pixel> Index<usize> for SubImageView<'a, ImageViewMut<'a, T>> {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
let row = &self.parent[index + self.y as usize];
&row[self.x as usize..]
}
}
impl<'a, T: Pixel> Index<usize> for SubImageView<'a, ImageBuffer<T>> {
type Output = [T];
fn index(&self, index: usize) -> &Self::Output {
let row = &self.parent[index + self.y as usize];
&row[self.x as usize..]
}
}