cgats 0.2.0

Parse, transform, and write CGATS color files
Documentation
//! Color hinting utilities

use std::fmt;

use crate::{DataFormat, field::{Field, Field::*}};
pub use deltae::DEMethod;

/// Color types represented in a CGATS `DATA_FORMAT`
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ColorType {
    /// Red, Green, Blue
    Rgb,
    /// Cyan, Magenta, Yellow, Black
    Cmyk,
    /// CMYK+1
    FiveClr,
    /// CMYK+2
    SixClr,
    /// CMYK+3
    SevenClr,
    /// CMYK+4
    EightClr,
    /// CMYK+N
    NClr,
    /// Spectral(Min, Max, Increment)
    Spectral(u16, u16, u16),
    /// Other Spectral data
    SpectralN,
    /// Density (Red, Green, Blue, Visual filters)
    Density,
    /// CIE L*a*b*
    Lab,
    /// Lightness, Chroma, Hue
    Lch,
    /// XYZ
    Xyz,
    /// XYy
    XYy,
    /// DeltaE
    DeltaE(DEMethod),
}

impl fmt::Display for ColorType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

pub(crate) const FORMAT_RGB: [Field; 3] = [RGB_R, RGB_G, RGB_B];
pub(crate) const FORMAT_CMYK: [Field; 4] = [CMYK_C, CMYK_M, CMYK_Y, CMYK_K];
pub(crate) const FORMAT_5CLR: [Field; 5] = [FIVECLR_1, FIVECLR_2, FIVECLR_3, FIVECLR_4, FIVECLR_5];
pub(crate) const FORMAT_6CLR: [Field; 6] = [SIXCLR_1, SIXCLR_2, SIXCLR_3, SIXCLR_4, SIXCLR_5, SIXCLR_6];
pub(crate) const FORMAT_7CLR: [Field; 7] = [
    SEVENCLR_1, SEVENCLR_2, SEVENCLR_3, SEVENCLR_4, SEVENCLR_5, SEVENCLR_6, SEVENCLR_7
];
pub(crate) const FORMAT_8CLR: [Field; 8] = [
    EIGHTCLR_1, EIGHTCLR_2, EIGHTCLR_3, EIGHTCLR_4, EIGHTCLR_5, EIGHTCLR_6, EIGHTCLR_7, EIGHTCLR_8
];
pub(crate) const FORMAT_NCLR: [Field; 1] = [NCLR(1)];
pub(crate) const FORMAT_DENSITY: [Field; 4] = [D_RED, D_GREEN, D_BLUE, D_VIS];
pub(crate) const FORMAT_LAB: [Field; 3] = [LAB_L, LAB_A, LAB_B];
pub(crate) const FORMAT_LCH: [Field; 3] = [LCH_L, LCH_C, LCH_H];
pub(crate) const FORMAT_XYZ: [Field; 3] = [XYZ_X, XYZ_Y, XYZ_Z];
pub(crate) const FORMAT_XYY: [Field; 3] = [XYY_X, XYY_CAPY, XYY_Y];
pub(crate) const FORMAT_SPECTRAL_380_780_10: [Field; 41] = [
    SPECTRAL_380, SPECTRAL_390, SPECTRAL_400, SPECTRAL_410, SPECTRAL_420, SPECTRAL_430,
    SPECTRAL_440, SPECTRAL_450, SPECTRAL_460, SPECTRAL_470, SPECTRAL_480, SPECTRAL_490,
    SPECTRAL_500, SPECTRAL_510, SPECTRAL_520, SPECTRAL_530, SPECTRAL_540, SPECTRAL_550,
    SPECTRAL_560, SPECTRAL_570, SPECTRAL_580, SPECTRAL_590, SPECTRAL_600, SPECTRAL_610,
    SPECTRAL_620, SPECTRAL_630, SPECTRAL_640, SPECTRAL_650, SPECTRAL_660, SPECTRAL_670,
    SPECTRAL_680, SPECTRAL_690, SPECTRAL_700, SPECTRAL_710, SPECTRAL_720, SPECTRAL_730,
    SPECTRAL_740, SPECTRAL_750, SPECTRAL_760, SPECTRAL_770, SPECTRAL_780,
];
pub(crate) const FORMAT_SPECTRAL_380_730_10: [Field; 36] = [
    SPECTRAL_380, SPECTRAL_390, SPECTRAL_400, SPECTRAL_410, SPECTRAL_420, SPECTRAL_430,
    SPECTRAL_440, SPECTRAL_450, SPECTRAL_460, SPECTRAL_470, SPECTRAL_480, SPECTRAL_490,
    SPECTRAL_500, SPECTRAL_510, SPECTRAL_520, SPECTRAL_530, SPECTRAL_540, SPECTRAL_550,
    SPECTRAL_560, SPECTRAL_570, SPECTRAL_580, SPECTRAL_590, SPECTRAL_600, SPECTRAL_610,
    SPECTRAL_620, SPECTRAL_630, SPECTRAL_640, SPECTRAL_650, SPECTRAL_660, SPECTRAL_670,
    SPECTRAL_680, SPECTRAL_690, SPECTRAL_700, SPECTRAL_710, SPECTRAL_720, SPECTRAL_730,
];
pub(crate) const FORMAT_SPECTRAL: [Field; 50] = [
    SPECTRAL_340, SPECTRAL_350, SPECTRAL_360, SPECTRAL_370, SPECTRAL_380, SPECTRAL_390,
    SPECTRAL_400, SPECTRAL_410, SPECTRAL_420, SPECTRAL_430, SPECTRAL_440, SPECTRAL_450,
    SPECTRAL_460, SPECTRAL_470, SPECTRAL_480, SPECTRAL_490, SPECTRAL_500, SPECTRAL_510,
    SPECTRAL_520, SPECTRAL_530, SPECTRAL_540, SPECTRAL_550, SPECTRAL_560, SPECTRAL_570,
    SPECTRAL_580, SPECTRAL_590, SPECTRAL_600, SPECTRAL_610, SPECTRAL_620, SPECTRAL_630,
    SPECTRAL_640, SPECTRAL_650, SPECTRAL_660, SPECTRAL_670, SPECTRAL_680, SPECTRAL_690,
    SPECTRAL_700, SPECTRAL_710, SPECTRAL_720, SPECTRAL_730, SPECTRAL_740, SPECTRAL_750,
    SPECTRAL_760, SPECTRAL_770, SPECTRAL_780, SPECTRAL_790, SPECTRAL_800, SPECTRAL_810,
    SPECTRAL_820, SPECTRAL_830,
];
pub(crate) const FORMAT_DE2000:  [Field; 1] = [DE_2000];
pub(crate) const FORMAT_DE1976:  [Field; 1] = [DE_1976];
pub(crate) const FORMAT_DE1994G: [Field; 1] = [DE_1994];
pub(crate) const FORMAT_DE1994T: [Field; 1] = [DE_1994T];
pub(crate) const FORMAT_DECMC:   [Field; 1] = [DE_CMC];
pub(crate) const FORMAT_DECMC2:  [Field; 1] = [DE_CMC2];

impl DataFormat {
    fn push_if_has_all(&self, fields: &[Field], cdt: ColorType, vec: &mut Vec<ColorType>) -> bool {
        if fields.iter().all(|field| self.fields.contains(field)) {
            vec.push(cdt);
            true
        } else {
            false
        }
    }

    fn push_if_has_any(&self, fields: &[Field], cdt: ColorType, vec: &mut Vec<ColorType>) -> bool {
        if fields.iter().any(|field| self.fields.contains(field)) {
            vec.push(cdt);
            true
        } else {
            false
        }
    }

    /// Returns a list of [`ColorType`]s based on the contents of the fields
    pub fn color_types(&self) -> Vec<ColorType> {
        let mut cdt = Vec::new();

        self.push_if_has_all(&FORMAT_RGB, ColorType::Rgb, &mut cdt);
        self.push_if_has_all(&FORMAT_CMYK, ColorType::Cmyk, &mut cdt);
        self.push_if_has_all(&FORMAT_5CLR, ColorType::FiveClr, &mut cdt);
        self.push_if_has_all(&FORMAT_6CLR, ColorType::SixClr, &mut cdt);
        self.push_if_has_all(&FORMAT_7CLR, ColorType::SevenClr, &mut cdt);
        self.push_if_has_all(&FORMAT_8CLR, ColorType::EightClr, &mut cdt);
        self.push_if_has_all(&FORMAT_NCLR, ColorType::NClr, &mut cdt);
        self.push_if_has_any(&FORMAT_DENSITY, ColorType::Density, &mut cdt);
        self.push_if_has_all(&FORMAT_LAB, ColorType::Lab, &mut cdt);
        self.push_if_has_all(&FORMAT_LCH, ColorType::Lch, &mut cdt);
        self.push_if_has_all(&FORMAT_XYZ, ColorType::Xyz, &mut cdt);
        self.push_if_has_all(&FORMAT_XYY, ColorType::XYy, &mut cdt);

        // Not mutually exclusive spectral types
        if  self.push_if_has_all(&FORMAT_SPECTRAL_380_780_10, ColorType::Spectral(380, 780, 10), &mut cdt) ||
            self.push_if_has_all(&FORMAT_SPECTRAL_380_730_10, ColorType::Spectral(380, 730, 10), &mut cdt) ||
            self.push_if_has_any(&FORMAT_SPECTRAL, ColorType::SpectralN, &mut cdt)
        {}

        self.push_if_has_all(&FORMAT_DE2000, ColorType::DeltaE(DEMethod::DE2000), &mut cdt);
        self.push_if_has_all(&FORMAT_DE1976, ColorType::DeltaE(DEMethod::DE1976), &mut cdt);
        self.push_if_has_all(&FORMAT_DE1994G, ColorType::DeltaE(DEMethod::DE1994G), &mut cdt);
        self.push_if_has_all(&FORMAT_DE1994T, ColorType::DeltaE(DEMethod::DE1994T), &mut cdt);
        self.push_if_has_all(&FORMAT_DECMC, ColorType::DeltaE(DEMethod::DECMC(1.0,1.0)), &mut cdt);
        self.push_if_has_all(&FORMAT_DECMC2, ColorType::DeltaE(DEMethod::DECMC(2.0, 1.0)), &mut cdt);

        cdt
    }
}