quickraw 0.1.6

A pure rust library to handle camera raw files
Documentation
use super::super::data;
use super::*;
use crate::raw::RawImage;
use crate::RawFileReadingError;

fn prepare(
    basic_info: &quickexif::ParsedInfo,
    only_thumbnail: bool,
) -> Result<(&str, Option<u16>, [f32; 9]), RawFileReadingError> {
    let make = basic_info
        .str("make")
        .map_err(|_| RawFileReadingError::CannotReadMake)?;
    let model = basic_info
        .str("model")
        .map_err(|_| RawFileReadingError::CannotReadModel)?
        .split_whitespace()
        .collect::<String>();

    let dng_version = basic_info.u16("dng_version").ok();

    let cam_matrix = if only_thumbnail {
        [0f32; 9]
    } else {
        match dng_version {
            None => *data::CAM_XYZ_MAP
                .get(model.as_str())
                .ok_or_else(|| RawFileReadingError::ModelIsNotSupportedYet(model.clone()))?,
            Some(_) => {
                let mut matrix = [0f32; 9];
                for (i, item) in matrix.iter_mut().enumerate() {
                    *item = basic_info.f64(format!("c{}", i).as_str())? as f32;
                }
                utility::matrix3_inverse(&mut matrix);
                utility::matrix3_normalize(&mut matrix);
                matrix
            }
        }
    };

    Ok((make, dng_version, cam_matrix))
}

pub(in super::super) fn select_and_decode_exif_info(
    file_buffer: &[u8],
    basic_info: quickexif::ParsedInfo,
) -> Result<quickexif::ParsedInfo, RawFileReadingError> {
    let (make, dng_version, _) = prepare(&basic_info, true)?;

    let rule = match dng_version {
        None => match make {
            "NIKON" | "NIKON CORPORATION" => Ok(&nikon::IMAGE_RULE),
            "SONY" => Ok(&sony::IMAGE_RULE),
            "Panasonic" => Ok(&panasonic::IMAGE_RULE),
            "OLYMPUS CORPORATION" | "OLYMPUS IMAGING CORP." => Ok(&olympus::IMAGE_RULE),
            "FUJIFILM" => Ok(&fujifilm::IMAGE_RULE),
            _ => Err(RawFileReadingError::MakerIsNotSupportedYet(make.to_owned())),
        },
        Some(_version) => Ok(&adobe::IMAGE_RULE),
    }?;

    Ok(quickexif::parse_with_prev_info(
        file_buffer,
        rule,
        basic_info,
    )?)
}

pub(in super::super) fn select_and_decode_thumbnail(
    file_buffer: &[u8],
    basic_info: quickexif::ParsedInfo,
) -> Result<(&[u8], Orientation), RawFileReadingError> {
    let (make, dng_version, _) = prepare(&basic_info, true)?;

    macro_rules! decode {
        ($t:ident) => {{
            let raw_info =
                quickexif::parse_with_prev_info(file_buffer, &$t::THUMBNAIL_RULE, basic_info)?;
            let decoder = $t::General::new(raw_info);
            let thumbnail = decoder.get_thumbnail(&file_buffer)?;
            let orientation = decoder.get_orientation();
            (thumbnail, orientation)
        }};
    }

    match dng_version {
        None => match make {
            "NIKON" | "NIKON CORPORATION" => Ok(decode!(nikon)),
            "SONY" => Ok(decode!(sony)),
            "Panasonic" => Ok(decode!(panasonic)),
            "OLYMPUS CORPORATION" | "OLYMPUS IMAGING CORP." => Ok(decode!(olympus)),
            "FUJIFILM" => Ok(decode!(fujifilm)),
            _ => Err(RawFileReadingError::MakerIsNotSupportedYet(make.to_owned())),
        },
        Some(_version) => Ok(decode!(adobe)),
    }
}

pub(in super::super) fn select_and_decode(
    file_buffer: &[u8],
    basic_info: quickexif::ParsedInfo,
) -> Result<RawImage, RawFileReadingError> {
    let (make, dng_version, cam_matrix) = prepare(&basic_info, false)?;

    macro_rules! decode {
        ($t:ident) => {{
            let raw_info =
                quickexif::parse_with_prev_info(file_buffer, &$t::IMAGE_RULE, basic_info)?;
            let width = raw_info.usize("width")?;
            let height = raw_info.usize("height")?;

            let decoder = $t::General::new(raw_info);
            let cfa_pattern = decoder.get_cfa_pattern()?;
            let crop = decoder.get_crop();
            let orientation = decoder.get_orientation();
            let white_balance = decoder.get_white_balance()?;
            let image = decoder.decode_with_preprocess(file_buffer)?;

            RawImage::new(
                image,
                width,
                height,
                cfa_pattern,
                crop,
                orientation,
                (white_balance, cam_matrix),
            )
        }};
    }

    let raw_image = match dng_version {
        None => match make {
            "NIKON" | "NIKON CORPORATION" => Ok(decode!(nikon)),
            "SONY" => Ok(decode!(sony)),
            "Panasonic" => Ok(decode!(panasonic)),
            "OLYMPUS CORPORATION" | "OLYMPUS IMAGING CORP." => Ok(decode!(olympus)),
            "FUJIFILM" => Ok(decode!(fujifilm)),
            _ => Err(RawFileReadingError::MakerIsNotSupportedYet(make.to_owned())),
        },
        Some(_version) => Ok(decode!(adobe)),
    }?;

    Ok(raw_image)
}