use std::{
iter::FusedIterator,
marker::PhantomData,
ops::{Index, IndexMut},
};
use crate::prelude::*;
use super::raw::PlumWrapper;
#[derive(Debug, Clone)]
pub struct Frame<'img, Fmt: ColorFmt, Img: Image<Fmt> + ?Sized>(
pub(super) &'img Img,
pub(super) usize,
pub(super) PhantomData<Fmt>,
);
#[derive(Debug)]
pub struct FrameMut<'img, Fmt: ColorFmt, Img: Image<Fmt> + ?Sized>(
pub(super) &'img mut Img,
pub(super) usize,
pub(super) PhantomData<Fmt>,
);
impl<'img, Fmt: ColorFmt, Img: Image<Fmt> + ?Sized> Frame<'img, Fmt, Img> {
pub fn new(img: &'img Img, frame_idx: usize) -> Self {
Self(img, frame_idx, PhantomData)
}
pub fn image(&self) -> &'img Img {
self.0
}
pub fn pixel(&self, x: usize, y: usize) -> Fmt {
self.image().pixel(self.1, x, y)
}
}
impl<'img, Fmt: ColorFmt, Img: Image<Fmt> + ?Sized> FrameMut<'img, Fmt, Img> {
pub fn new(img: &'img mut Img, frame_idx: usize) -> Self {
Self(img, frame_idx, PhantomData)
}
pub fn image(&self) -> &Img {
self.0
}
pub fn image_mut(&'img mut self) -> &'img mut Img {
self.0
}
pub fn pixel(&self, x: usize, y: usize) -> Fmt {
self.image().pixel(self.1, x, y)
}
}
impl<Fmt: ColorFmt> Index<(usize, usize)> for Frame<'_, Fmt, DirectImage<Fmt>> {
type Output = Fmt;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
PlumWrapper::pixel_ref(self.0, self.1, x, y)
}
}
impl<Fmt: ColorFmt> Index<(usize, usize)> for FrameMut<'_, Fmt, DirectImage<Fmt>> {
type Output = Fmt;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
PlumWrapper::pixel_ref(self.0, self.1, x, y)
}
}
impl<Fmt: ColorFmt> IndexMut<(usize, usize)> for FrameMut<'_, Fmt, DirectImage<Fmt>> {
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
let frame_idx = self.1;
PlumWrapper::pixel_mut(self.0, frame_idx, x, y)
}
}
impl<Fmt: ColorFmt> Index<(usize, usize)> for Frame<'_, Fmt, PalettedImage<Fmt>> {
type Output = u8;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
self.0.index_at(self.1, x, y)
}
}
impl<Fmt: ColorFmt> Index<(usize, usize)> for FrameMut<'_, Fmt, PalettedImage<Fmt>> {
type Output = u8;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
self.0.index_at(self.1, x, y)
}
}
impl<Fmt: ColorFmt> IndexMut<(usize, usize)> for FrameMut<'_, Fmt, PalettedImage<Fmt>> {
fn index_mut(&mut self, (x, y): (usize, usize)) -> &mut Self::Output {
self.0.index_at_mut(self.1, x, y)
}
}
#[derive(Debug, Clone)]
pub struct Frames<'img, Fmt: ColorFmt, Img: Image<Fmt> + ?Sized> {
pub(super) img: &'img Img,
pub(super) begin: usize,
pub(super) end: usize,
pub(super) _pix_fmt: PhantomData<Fmt>,
}
impl<'img, Fmt: ColorFmt, Img: Image<Fmt>> Iterator for Frames<'img, Fmt, Img> {
type Item = Frame<'img, Fmt, Img>;
fn next(&mut self) -> Option<Self::Item> {
if self.begin == self.end {
return None;
}
let frame = self.img.frame(self.begin);
self.begin += 1;
Some(frame)
}
fn size_hint(&self) -> (usize, Option<usize>) {
let nb_frames = self.end - self.begin;
(nb_frames, Some(nb_frames))
}
}
impl<Fmt: ColorFmt, Img: Image<Fmt>> DoubleEndedIterator for Frames<'_, Fmt, Img> {
fn next_back(&mut self) -> Option<Self::Item> {
if self.begin == self.end {
return None;
}
self.end -= 1;
Some(self.img.frame(self.end))
}
}
impl<Fmt: ColorFmt, Img: Image<Fmt>> FusedIterator for Frames<'_, Fmt, Img> {}
impl<Fmt: ColorFmt, Img: Image<Fmt>> ExactSizeIterator for Frames<'_, Fmt, Img> {}