pub trait PixelChunk: Copy + Clone + Default + IntoIterator<Item = Self> {
type PixelType: Clone;
fn pixels() -> usize;
fn get_pixel(&self, index: usize) -> Option<Self>
where
Self: Sized;
fn set_pixel(&mut self, index: usize, pixel: Self::PixelType);
fn fill_pixel(&mut self, pixel: Self::PixelType) {
for i in 0..Self::pixels() {
self.set_pixel(i, pixel.clone());
}
}
fn filled_pixel(pixel: Self::PixelType) -> Self
where
Self: Default + Sized,
{
let mut chunk = Self::default();
for i in 0..Self::pixels() {
let cloned_pixel = pixel.clone();
chunk.set_pixel(i, cloned_pixel);
}
chunk
}
}
pub struct PixelChunkIterator<T: PixelChunk> {
chunk: T,
index: usize,
}
impl<T: PixelChunk> Iterator for PixelChunkIterator<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
let pixel = self.chunk.get_pixel(self.index);
self.index += 1;
pixel
}
}
#[derive(Debug, PartialEq, Clone, Copy, Default)]
pub struct Pixel8 {
pub value: u8,
}
impl PixelChunk for Pixel8 {
type PixelType = Pixel8;
#[inline]
fn pixels() -> usize {
1
}
fn get_pixel(&self, index: usize) -> Option<Self> {
match index {
0 => Some(*self),
_ => None,
}
}
fn set_pixel(&mut self, _index: usize, pixel: Self::PixelType) {
*self = pixel;
}
}
impl IntoIterator for Pixel8 {
type Item = Pixel8;
type IntoIter = PixelChunkIterator<Self>;
fn into_iter(self) -> Self::IntoIter {
PixelChunkIterator {
chunk: self,
index: 0,
}
}
}
impl From<u8> for Pixel8 {
#[inline]
fn from(value: u8) -> Self {
Pixel8 { value }
}
}
impl From<Pixel8> for u8 {
#[inline]
fn from(pixel: Pixel8) -> u8 {
pixel.value
}
}
#[derive(Debug, PartialEq, Clone, Copy, Default)]
pub struct Pixel4 {
pub value: u8,
}
impl PixelChunk for Pixel4 {
type PixelType = Pixel4;
#[inline]
fn pixels() -> usize {
2
}
fn get_pixel(&self, index: usize) -> Option<Self> {
match index {
0 => Some((self.value >> 4).into()),
1 => Some((self.value & 0xF).into()),
_ => None,
}
}
fn set_pixel(&mut self, index: usize, pixel: Self::PixelType) {
match index {
0 => {
self.value = (self.value & 0xF) | (pixel.value << 4);
}
1 => {
self.value = (self.value & 0xF0) | (pixel.value & 0xF);
}
_ => {}
}
}
}
impl IntoIterator for Pixel4 {
type Item = Pixel4;
type IntoIter = PixelChunkIterator<Self>;
fn into_iter(self) -> Self::IntoIter {
PixelChunkIterator {
chunk: self,
index: 0,
}
}
}
impl From<u8> for Pixel4 {
#[inline]
fn from(value: u8) -> Self {
Pixel4 { value }
}
}
impl From<Pixel4> for u8 {
#[inline]
fn from(pixel: Pixel4) -> u8 {
pixel.value
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_create_pixel4() {
let pixel = Pixel4 { value: 0xF0 };
assert_eq!(pixel.get_pixel(0), Some(Pixel4 { value: 0xF }));
assert_eq!(pixel.value, 0xF0);
}
#[test]
fn can_get_pixels_from_pixel4() {
let pixel = Pixel4 { value: 0xFA };
assert_eq!(pixel.get_pixel(0).unwrap().value, 0xF);
assert_eq!(pixel.get_pixel(1).unwrap().value, 0xA);
assert_eq!(pixel.get_pixel(2), None);
assert_eq!(pixel.get_pixel(42), None);
}
#[test]
fn check_alignment_and_size() {
assert_eq!(std::mem::align_of::<Pixel4>(), 1);
assert_eq!(std::mem::size_of::<Pixel4>(), 1);
assert_eq!(std::mem::size_of::<Vec<Pixel4>>(), 24);
let px: Pixel4 = 0xF0.into();
let mut val = vec![px, px, px];
for _i in 0..24 {
val.push(px);
}
assert_eq!(std::mem::size_of_val(&val), 24);
}
#[test]
fn can_set_pixel4() {
let mut pixel = Pixel4 { value: 0xA0 };
pixel.set_pixel(1, Pixel4 { value: 0xB });
assert_eq!(pixel.value, 0xAB);
}
#[test]
fn can_set_pixel4_with_u8() {
let mut pixel: Pixel4 = 0xA1.into();
assert_eq!(pixel.get_pixel(0).unwrap().value, 0xA);
assert_eq!(pixel.get_pixel(1).unwrap().value, 0x1);
pixel.set_pixel(1, 0xB.into());
assert_eq!(pixel.value, 0xAB);
}
#[test]
fn can_get_u8_from_pixel4() {
let pixel = Pixel4 { value: 0xAB };
assert_eq!(u8::from(pixel), 0xAB);
}
#[test]
fn can_iterate_over_pixel4() {
let pixel = Pixel4 { value: 0xAB };
let mut iter = pixel.into_iter();
assert_eq!(iter.next().unwrap().value, 0xA);
assert_eq!(iter.next().unwrap().value, 0xB);
assert_eq!(iter.next(), None);
let mut iter = pixel.into_iter();
assert_eq!(iter.next().unwrap().value, 0xA);
let mut test = 0xA;
for p in pixel {
assert_eq!(p.value, test);
test += 1;
}
assert_eq!(test, 0xC);
}
#[test]
fn can_iterate_over_pixel8() {
let pixel = Pixel8 { value: 0xAB };
let mut iter = pixel.into_iter();
assert_eq!(iter.next().unwrap().value, 0xAB);
assert_eq!(iter.next(), None);
let mut iter = pixel.into_iter();
assert_eq!(iter.next().unwrap().value, 0xAB);
let mut test = 0xAB;
for p in pixel {
assert_eq!(p.value, test);
test += 1;
}
assert_eq!(test, 0xAC);
}
}