use crate::pixels::InnerPixel;
use crate::{ArrayChunks, ImageError, PixelTrait, PixelType};
pub unsafe trait ImageView {
type Pixel: InnerPixel;
fn width(&self) -> u32;
fn height(&self) -> u32;
fn iter_rows(&self, start_row: u32) -> impl Iterator<Item = &[Self::Pixel]>;
fn iter_2_rows(
&self,
start_y: u32,
max_rows: u32,
) -> ArrayChunks<impl Iterator<Item = &[Self::Pixel]>, 2> {
ArrayChunks::new(self.iter_rows(start_y).take(max_rows as usize))
}
fn iter_4_rows(
&self,
start_y: u32,
max_rows: u32,
) -> ArrayChunks<impl Iterator<Item = &[Self::Pixel]>, 4> {
ArrayChunks::new(self.iter_rows(start_y).take(max_rows as usize))
}
fn iter_rows_with_step(
&self,
start_y: f64,
step: f64,
max_rows: u32,
) -> impl Iterator<Item = &[Self::Pixel]> {
let steps = (self.height() as f64 - start_y) / step;
let steps = (steps.max(0.).ceil() as usize).min(max_rows as usize);
let mut rows = self.iter_rows(start_y as u32);
let mut y = start_y;
let mut next_row_y = start_y as usize;
let mut cur_row = None;
(0..steps).filter_map(move |_| {
let req_row_y = y as usize;
if next_row_y <= req_row_y {
for _ in next_row_y..=req_row_y {
cur_row = rows.next();
}
next_row_y = req_row_y + 1;
}
y += step;
cur_row
})
}
}
pub unsafe trait ImageViewMut: ImageView {
fn iter_rows_mut(&mut self, start_row: u32) -> impl Iterator<Item = &mut [Self::Pixel]>;
fn iter_2_rows_mut(&mut self) -> ArrayChunks<impl Iterator<Item = &mut [Self::Pixel]>, 2> {
ArrayChunks::new(self.iter_rows_mut(0))
}
fn iter_4_rows_mut(&mut self) -> ArrayChunks<impl Iterator<Item = &mut [Self::Pixel]>, 4> {
ArrayChunks::new(self.iter_rows_mut(0))
}
}
pub trait IntoImageView {
fn pixel_type(&self) -> Option<PixelType>;
fn width(&self) -> u32;
fn height(&self) -> u32;
fn image_view<P: PixelTrait>(&self) -> Option<impl ImageView<Pixel = P>>;
}
pub trait IntoImageViewMut: IntoImageView {
fn image_view_mut<P: PixelTrait>(&mut self) -> Option<impl ImageViewMut<Pixel = P>>;
}
pub(crate) fn try_pixel_type(image: &impl IntoImageView) -> Result<PixelType, ImageError> {
image.pixel_type().ok_or(ImageError::UnsupportedPixelType)
}