#![allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IccProfileClass {
Display,
Output,
Input,
ColorSpace,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum IccColorSpace {
Rgb,
Cmyk,
Lab,
Xyz,
}
#[derive(Debug, Clone)]
pub struct IccProfile {
pub description: String,
pub class: IccProfileClass,
pub color_space: IccColorSpace,
pub version: (u8, u8, u8),
pub white_point: [f32; 3],
}
impl Default for IccProfile {
fn default() -> Self {
Self {
description: "sRGB IEC61966-2.1".to_string(),
class: IccProfileClass::Display,
color_space: IccColorSpace::Rgb,
version: (4, 3, 0),
white_point: [0.9504559, 1.0, 1.0890578],
}
}
}
pub fn export_icc_profile(profile: &IccProfile) -> Vec<u8> {
let mut blob = Vec::new();
blob.extend_from_slice(b"ICCP");
blob.push(profile.version.0);
blob.push(profile.version.1);
blob.push(profile.version.2);
blob.extend_from_slice(profile.description.as_bytes());
blob
}
pub fn is_rgb_profile(profile: &IccProfile) -> bool {
profile.color_space == IccColorSpace::Rgb
}
pub fn profile_white_point(profile: &IccProfile) -> [f32; 3] {
profile.white_point
}
pub fn validate_icc_profile(profile: &IccProfile) -> bool {
!profile.description.is_empty() && profile.white_point[1] > 0.0
}
pub fn class_tag(class: IccProfileClass) -> &'static str {
match class {
IccProfileClass::Display => "mntr",
IccProfileClass::Output => "prtr",
IccProfileClass::Input => "scnr",
IccProfileClass::ColorSpace => "spac",
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_profile_is_rgb() {
assert!(is_rgb_profile(&IccProfile::default()));
}
#[test]
fn test_export_starts_with_magic() {
let blob = export_icc_profile(&IccProfile::default());
assert_eq!(&blob[..4], b"ICCP");
}
#[test]
fn test_export_nonempty() {
assert!(!export_icc_profile(&IccProfile::default()).is_empty());
}
#[test]
fn test_validate_default_profile() {
assert!(validate_icc_profile(&IccProfile::default()));
}
#[test]
fn test_validate_empty_description_fails() {
let p = IccProfile {
description: String::new(),
..Default::default()
};
assert!(!validate_icc_profile(&p));
}
#[test]
fn test_white_point_y_is_one() {
let wp = profile_white_point(&IccProfile::default());
assert!((wp[1] - 1.0).abs() < 0.01);
}
#[test]
fn test_class_tag_display() {
assert_eq!(class_tag(IccProfileClass::Display), "mntr");
}
#[test]
fn test_class_tag_output() {
assert_eq!(class_tag(IccProfileClass::Output), "prtr");
}
#[test]
fn test_version_in_export() {
let p = IccProfile {
version: (4, 3, 0),
..Default::default()
};
let blob = export_icc_profile(&p);
assert!(blob.contains(&4u8));
}
#[test]
fn test_is_rgb_cmyk_false() {
let p = IccProfile {
color_space: IccColorSpace::Cmyk,
..Default::default()
};
assert!(!is_rgb_profile(&p));
}
}