dds 0.2.0

DDS de/encoder written in 100% safe Rust
Documentation
use crate::util::closure_types3;
use crate::{yuv10, yuv16, yuv8, WithPrecision};
use crate::{Channels::*, ColorFormat};

use super::read_write::{
    for_each_bi_planar, for_each_bi_planar_rect, process_bi_planar_helper, BiPlaneInfo, PlaneRange,
};
use super::{Args, Decoder, DecoderSet, RArgs};

// helpers

macro_rules! underlying {
    ($channels:expr, $out:ty, $p1:ty, $p2:ty, $f:expr) => {{
        const CHANNELS: usize = $channels.count() as usize;
        type OutPixel = [$out; CHANNELS];
        type Plane1 = $p1;
        type Plane2 = $p2;

        const INFO: BiPlaneInfo = BiPlaneInfo {
            plane1_element_size: std::mem::size_of::<Plane1>() as u8,
            plane2_element_size: std::mem::size_of::<Plane2>() as u8,
            sub_sampling: (2, 2),
        };
        const SUB_SAMPLING_X: usize = INFO.sub_sampling.0 as usize;

        fn process_bi_planar(plane1: &[u8], plane2: &[u8], decoded: &mut [u8], range: PlaneRange) {
            let f = closure_types3::<
                [Plane1; SUB_SAMPLING_X],
                Plane2,
                u8,
                [OutPixel; SUB_SAMPLING_X],
                _,
            >($f);
            process_bi_planar_helper(plane1, plane2, decoded, range, f)
        }

        const NATIVE_COLOR: ColorFormat =
            ColorFormat::new($channels, <$out as WithPrecision>::PRECISION);

        Decoder::new_with_all_channels(
            NATIVE_COLOR,
            |Args(r, out, context)| {
                for_each_bi_planar(r, out, context, NATIVE_COLOR, INFO, process_bi_planar)
            },
            |RArgs(r, out, offset, context)| {
                for_each_bi_planar_rect(
                    r,
                    out,
                    offset,
                    context,
                    NATIVE_COLOR,
                    INFO,
                    process_bi_planar,
                )
            },
        )
    }};
}

macro_rules! rgb {
    ($out:ty, p1 = $p1:ty, p2 = $p2:ty, $f:expr) => {
        underlying!(Rgb, $out, $p1, $p2, $f)
    };
}

// decoders

pub(crate) const NV12: DecoderSet = DecoderSet::new(&[
    rgb!(u8, p1 = u8, p2 = [u8; 2], |y, [u, v], _| y
        .map(|y| yuv8::n8([y, u, v]))),
    rgb!(u16, p1 = u8, p2 = [u8; 2], |y, [u, v], _| y
        .map(|y| yuv8::n16([y, u, v]))),
    rgb!(f32, p1 = u8, p2 = [u8; 2], |y, [u, v], _| y
        .map(|y| yuv8::f32([y, u, v]))),
]);

fn to10(yuv: [u16; 3]) -> [u16; 3] {
    yuv.map(|v| v >> 6)
}
pub(crate) const P010: DecoderSet = DecoderSet::new(&[
    rgb!(u16, p1 = u16, p2 = [u16; 2], |y, [u, v], _| y
        .map(|y| yuv10::n16(to10([y, u, v])))),
    rgb!(u8, p1 = u16, p2 = [u16; 2], |y, [u, v], _| y
        .map(|y| yuv10::n8(to10([y, u, v])))),
    rgb!(f32, p1 = u16, p2 = [u16; 2], |y, [u, v], _| y
        .map(|y| yuv10::f32(to10([y, u, v])))),
]);

pub(crate) const P016: DecoderSet = DecoderSet::new(&[
    rgb!(u16, p1 = u16, p2 = [u16; 2], |y, [u, v], _| y
        .map(|y| yuv16::n16([y, u, v]))),
    rgb!(u8, p1 = u16, p2 = [u16; 2], |y, [u, v], _| y
        .map(|y| yuv16::n8([y, u, v]))),
    rgb!(f32, p1 = u16, p2 = [u16; 2], |y, [u, v], _| y
        .map(|y| yuv16::f32([y, u, v]))),
]);