use crate::*;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Colr {
Nclx {
colour_primaries: u16,
transfer_characteristics: u16,
matrix_coefficients: u16,
full_range_flag: bool,
},
Ricc {
profile: Vec<u8>,
},
Prof {
profile: Vec<u8>,
},
}
impl Colr {
pub fn new(
colour_primaries: u16,
transfer_characteristics: u16,
matrix_coefficients: u16,
full_range_flag: bool,
) -> Result<Self> {
Ok(Colr::Nclx {
colour_primaries,
transfer_characteristics,
matrix_coefficients,
full_range_flag,
})
}
}
impl Atom for Colr {
const KIND: FourCC = FourCC::new(b"colr");
fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
let colour_type = FourCC::decode(buf)?;
if colour_type == FourCC::new(b"nclx") {
let colour_primaries = u16::decode(buf)?;
let transfer_characteristics = u16::decode(buf)?;
let matrix_coefficients = u16::decode(buf)?;
let full_range_flag = u8::decode(buf)? == 0x80;
Ok(Colr::Nclx {
colour_primaries,
transfer_characteristics,
matrix_coefficients,
full_range_flag,
})
} else if colour_type == FourCC::new(b"prof") {
let profile_len = buf.remaining();
let profile = buf.slice(profile_len).to_vec();
Ok(Colr::Prof { profile })
} else if colour_type == FourCC::new(b"rICC") {
let profile_len = buf.remaining();
let profile = buf.slice(profile_len).to_vec();
Ok(Colr::Ricc { profile })
} else {
Err(Error::UnexpectedBox(colour_type))
}
}
fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
match self {
Colr::Nclx {
colour_primaries,
transfer_characteristics,
matrix_coefficients,
full_range_flag,
} => {
b"nclx".encode(buf)?;
colour_primaries.encode(buf)?;
transfer_characteristics.encode(buf)?;
matrix_coefficients.encode(buf)?;
if *full_range_flag {
0x80u8.encode(buf)?;
} else {
0x00u8.encode(buf)?;
}
}
Colr::Ricc { profile } => {
b"rICC".encode(buf)?;
profile.encode(buf)?;
}
Colr::Prof { profile } => {
b"prof".encode(buf)?;
profile.encode(buf)?;
}
}
Ok(())
}
}
impl Default for Colr {
fn default() -> Self {
Colr::Nclx {
colour_primaries: 1,
transfer_characteristics: 13,
matrix_coefficients: 5,
full_range_flag: true,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nclx_decode() {
const ENCODED: &[u8] = &[
0x00, 0x00, 0x00, 0x13, 0x63, 0x6f, 0x6c, 0x72, 0x6e, 0x63, 0x6c, 0x78, 0x00, 0x01,
0x00, 0x01, 0x00, 0x01, 0x00,
];
let buf = &mut std::io::Cursor::new(&ENCODED);
let colr = Colr::decode(buf).expect("failed to decode colr");
assert_eq!(
colr,
Colr::Nclx {
colour_primaries: 1,
transfer_characteristics: 1,
matrix_coefficients: 1,
full_range_flag: false
}
);
}
#[test]
fn test_nclx_encode() {
const ENCODED: &[u8] = &[
0x00, 0x00, 0x00, 0x13, 0x63, 0x6f, 0x6c, 0x72, 0x6e, 0x63, 0x6c, 0x78, 0x00, 0x01,
0x00, 0x0d, 0x00, 0x06, 0x80,
];
let colr = Colr::Nclx {
colour_primaries: 1,
transfer_characteristics: 13,
matrix_coefficients: 6,
full_range_flag: true,
};
let mut buf = Vec::new();
colr.encode(&mut buf).unwrap();
assert_eq!(buf.as_slice(), ENCODED);
}
}