aseprite_loader/binary/chunks/
color_profile.rs1use bitflags::bitflags;
2use nom::{
3 bytes::complete::take,
4 combinator::{flat_map, map},
5};
6use strum::FromRepr;
7
8use crate::binary::{
9 errors::ParseResult,
10 scalars::{dword, fixed, word, Fixed, Word},
11};
12
13#[derive(Debug)]
14pub struct ColorProfileChunk<'a> {
15 pub fixed_gamma: Option<Fixed>,
16 pub profile: ColorProfile<'a>,
17}
18
19#[derive(Debug, Copy, Clone, FromRepr)]
20pub enum ColorProfileType {
21 NoColorProfile,
22 Srgb,
23 EmbeddedICC,
24 Unknown(Word),
25}
26
27bitflags! {
28 pub struct ColorProfileFlags: Word {
29 const FIXED_GAMMA = 0x01;
30 }
31}
32
33#[derive(Debug)]
34pub enum ColorProfile<'a> {
35 NoColorProfile,
36 Srgb,
37 EmbeddedICC(&'a [u8]),
38 Unknown(Word),
39}
40
41pub fn parse_color_profile(input: &[u8]) -> ParseResult<'_, ColorProfileChunk<'_>> {
42 let (input, profile_type) = word(input)?;
43 let profile_type = ColorProfileType::from_repr(profile_type.into())
44 .unwrap_or(ColorProfileType::Unknown(profile_type));
45 let (input, flags) = word(input)?;
46 let flags = ColorProfileFlags::from_bits_truncate(flags);
47 let (input, fixed_gamma) = fixed(input)?;
48 let (input, _) = take(8usize)(input)?;
49 let (input, profile) = match profile_type {
50 ColorProfileType::NoColorProfile => (input, ColorProfile::NoColorProfile),
51 ColorProfileType::Srgb => (input, ColorProfile::Srgb),
52 ColorProfileType::EmbeddedICC => {
53 map(flat_map(dword, take), ColorProfile::EmbeddedICC)(input)?
54 }
55 ColorProfileType::Unknown(word) => (input, ColorProfile::Unknown(word)),
56 };
57 Ok((
58 input,
59 ColorProfileChunk {
60 fixed_gamma: if flags.contains(ColorProfileFlags::FIXED_GAMMA) {
61 Some(fixed_gamma)
62 } else {
63 None
64 },
65 profile,
66 },
67 ))
68}