ezk-image 0.4.3

Convert pixel and color formats such and RGB, YUV (YCbCr), ICtCp
Documentation
use super::{RgbaBlock, RgbaPixel, RgbaSrc};
use crate::planes::read_planes;
use crate::primitive::Primitive;
use crate::vector::Vector;
use crate::{ConvertError, ImageRef, ImageRefExt};
use std::marker::PhantomData;

pub(crate) struct ReadRgba<'a, const SWIZZLE: u8, P: Primitive> {
    rgba: &'a [u8],

    rgba_stride: usize,

    max_value: f32,

    _m: PhantomData<&'a [P]>,
}

impl<'a, const SWIZZLE: u8, P: Primitive> ReadRgba<'a, SWIZZLE, P> {
    pub(crate) fn new(src: &'a dyn ImageRef) -> Result<Self, ConvertError> {
        src.bounds_check()?;

        let [(rgba, rgba_stride)] = read_planes(src.planes())?;

        Ok(Self {
            rgba,
            rgba_stride,
            max_value: crate::formats::max_value_for_bits(src.format().bits_per_component()),
            _m: PhantomData,
        })
    }
}

impl<const SWIZZLE: u8, P: Primitive> RgbaSrc for ReadRgba<'_, SWIZZLE, P> {
    #[inline(always)]
    unsafe fn read<V: Vector>(&mut self, x: usize, y: usize) -> RgbaBlock<V> {
        let rgba00offset = y * self.rgba_stride + x * 4 * P::SIZE;
        let rgba10offset = (y + 1) * self.rgba_stride + x * 4 * P::SIZE;

        let [[r00, g00, b00, a00], [r01, g01, b01, a01]] =
            P::load_4x_interleaved_2x::<V>(&self.rgba[rgba00offset..]);
        let [[r10, g10, b10, a10], [r11, g11, b11, a11]] =
            P::load_4x_interleaved_2x::<V>(&self.rgba[rgba10offset..]);

        let r00 = r00.vdivf(self.max_value);
        let g00 = g00.vdivf(self.max_value);
        let b00 = b00.vdivf(self.max_value);
        let a00 = a00.vdivf(self.max_value);

        let r01 = r01.vdivf(self.max_value);
        let g01 = g01.vdivf(self.max_value);
        let b01 = b01.vdivf(self.max_value);
        let a01 = a01.vdivf(self.max_value);

        let r10 = r10.vdivf(self.max_value);
        let g10 = g10.vdivf(self.max_value);
        let b10 = b10.vdivf(self.max_value);
        let a10 = a10.vdivf(self.max_value);

        let r11 = r11.vdivf(self.max_value);
        let g11 = g11.vdivf(self.max_value);
        let b11 = b11.vdivf(self.max_value);
        let a11 = a11.vdivf(self.max_value);

        let px00 = RgbaPixel::from_components::<SWIZZLE>(r00, g00, b00, a00);
        let px01 = RgbaPixel::from_components::<SWIZZLE>(r01, g01, b01, a01);
        let px10 = RgbaPixel::from_components::<SWIZZLE>(r10, g10, b10, a10);
        let px11 = RgbaPixel::from_components::<SWIZZLE>(r11, g11, b11, a11);

        RgbaBlock {
            px00,
            px01,
            px10,
            px11,
        }
    }
}