quickraw 0.1.6

A pure rust library to handle camera raw files
Documentation
use crate::ColorConversion;

use super::{interp::*, *};

impl PixelInfo {
    #[inline(always)]
    fn new(i: usize, v: u16, w: usize, h: usize) -> Self {
        let x = i % w;
        let y = i / w;
        let is_top = y == 0;
        let is_left = x == 0;
        let is_bottom = y == h - 1;
        let is_right = x == w - 1;
        let is_column_even = x % 2 == 0;
        let is_row_even = y % 2 == 0;

        Self {
            i,
            v: v as i32,
            x,
            y,
            is_top,
            is_bottom,
            is_left,
            is_right,
            is_column_even,
            is_row_even,
        }
    }
}
impl RawImage {
    pub(crate) fn super_pixel_render<T>(&self, cc: &ColorConversion, cast_fn: fn(u16) -> T) -> (Vec<T>, usize, usize) {
        let image = self.image.as_slice();
        let w = self.width;
        let h = self.height;

        let iter = image.chunks_exact(w * 2).enumerate();

        macro_rules! render {
            ($cfa:tt) => {
                iter.flat_map(|(block_index, block)| {
                    let offset = block_index * w * 2;
                    block.iter().take(w).enumerate().step_by(2).map(move |(i, &v)| {
                        let i = offset + i;
                        let rgb = SuperPixel::$cfa(i, v, image, w);
                        cc.convert(rgb)
                    })
                })
                .flatten()
                .map(cast_fn)
                .collect()
            };
        }

        let data: Vec<T> = match self.cfa_pattern {
            CFAPattern::RGGB => render!(rggb),
            CFAPattern::BGGR => render!(bggr),
            CFAPattern::GRBG => render!(grbg),
            CFAPattern::GBRG => render!(gbrg),
            CFAPattern::XTrans0 | CFAPattern::XTrans1 => unimplemented!(),
        };

        (data, w / 2, h / 2)
    }

    pub(crate) fn linear_render<T>(&self, cc: &ColorConversion, cast_fn: fn(u16) -> T) -> (Vec<T>, usize, usize) {
        let image = self.image.as_slice();
        let w = self.width;
        let h = self.height;

        let iter = image.iter().enumerate().map(|(i, &v)| PixelInfo::new(i, v, w, h));

        macro_rules! render {
            ($cfa:tt) => {
                iter.flat_map(|pi| {
                    let rgb = Linear::$cfa(pi, image, w);
                    cc.convert(rgb)
                })
                .map(cast_fn)
                .collect()
            };
        }

        let data: Vec<T> = match self.cfa_pattern {
            CFAPattern::RGGB => render!(rggb),
            CFAPattern::BGGR => render!(bggr),
            CFAPattern::GRBG => render!(grbg),
            CFAPattern::GBRG => render!(gbrg),
            CFAPattern::XTrans0 => render!(xtrans0),
            CFAPattern::XTrans1 => render!(xtrans1),
        };

        (data, w, h)
    }

    pub(crate) fn no_demosaic_render<T>(&self, cc: &ColorConversion, cast_fn: fn(u16) -> T) -> (Vec<T>, usize, usize) {
        let image = self.image.as_slice();
        let w = self.width;
        let h = self.height;

        let iter = image.iter().enumerate().map(|(i, &v)| PixelInfo::new(i, v, w, h));

        macro_rules! render {
            ($cfa:tt) => {
                iter.flat_map(|pi| {
                    let (r, g, b) = None::$cfa(pi, image, w);
                    [
                        cc.gamma_lut[r as usize],
                        cc.gamma_lut[g as usize],
                        cc.gamma_lut[b as usize],
                    ]
                })
                .map(cast_fn)
                .collect()
            };
        }

        let data: Vec<T> = match self.cfa_pattern {
            CFAPattern::RGGB => render!(rggb),
            CFAPattern::BGGR => render!(bggr),
            CFAPattern::GRBG => render!(grbg),
            CFAPattern::GBRG => render!(gbrg),
            CFAPattern::XTrans0 | CFAPattern::XTrans1 => unimplemented!(),
        };

        (data, w, h)
    }
}