1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
use four_cc::FourCC;
use libheif_sys as lh;

pub type ColorProfileType = FourCC;

pub mod color_profile_types {
    use super::{ColorProfileType, FourCC};

    /// Color profile is not present inside image
    pub const NOT_PRESENT: ColorProfileType = FourCC(0u32.to_le_bytes());
    /// NCLX color profile
    pub const NCLX: ColorProfileType = FourCC(*b"nclx");
    /// Restricted ICC color profile
    pub const R_ICC: ColorProfileType = FourCC(*b"rICC");
    /// Prof color profile
    pub const PROF: ColorProfileType = FourCC(*b"prof");
}

#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, enumn::N)]
#[repr(C)]
pub enum ColorPrimaries {
    Unspecified = lh::heif_color_primaries_heif_color_primaries_unspecified as _,
    ITU_R_BT_470_6_System_M =
        lh::heif_color_primaries_heif_color_primaries_ITU_R_BT_470_6_System_M as _,
    ITU_R_BT_470_6_System_B_G =
        lh::heif_color_primaries_heif_color_primaries_ITU_R_BT_470_6_System_B_G as _,
    ITU_R_BT_601_6 = lh::heif_color_primaries_heif_color_primaries_ITU_R_BT_601_6 as _,
    ITU_R_BT_709_5 = lh::heif_color_primaries_heif_color_primaries_ITU_R_BT_709_5 as _,
    ITU_R_BT_2020_2_and_2100_0 =
        lh::heif_color_primaries_heif_color_primaries_ITU_R_BT_2020_2_and_2100_0 as _,
    GenericFilm = lh::heif_color_primaries_heif_color_primaries_generic_film as _,
    SMPTE_240M = lh::heif_color_primaries_heif_color_primaries_SMPTE_240M as _,
    SMPTE_ST_428_1 = lh::heif_color_primaries_heif_color_primaries_SMPTE_ST_428_1 as _,
    SMPTE_RP_431_2 = lh::heif_color_primaries_heif_color_primaries_SMPTE_RP_431_2 as _,
    SMPTE_EG_432_1 = lh::heif_color_primaries_heif_color_primaries_SMPTE_EG_432_1 as _,
    EBU_Tech_3213_E = lh::heif_color_primaries_heif_color_primaries_EBU_Tech_3213_E as _,
    /// This value is used when library `libheif` returns unknown value of color primaries.
    Unknown,
}

#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, enumn::N)]
#[repr(C)]
pub enum TransferCharacteristics {
    ITU_R_BT_709_5 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_709_5 as _,
    Unspecified = lh::heif_transfer_characteristics_heif_transfer_characteristic_unspecified as _,
    ITU_R_BT_470_6_System_M =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_470_6_System_M as _,
    ITU_R_BT_470_6_System_B_G =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_470_6_System_B_G
            as _,
    ITU_R_BT_601_6 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_601_6 as _,
    SMPTE_240M = lh::heif_transfer_characteristics_heif_transfer_characteristic_SMPTE_240M as _,
    Linear = lh::heif_transfer_characteristics_heif_transfer_characteristic_linear as _,
    Logarithmic100 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_logarithmic_100 as _,
    Logarithmic100Sqrt10 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_logarithmic_100_sqrt10 as _,
    IEC_61966_2_4 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_IEC_61966_2_4 as _,
    ITU_R_BT_1361 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_1361 as _,
    IEC_61966_2_1 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_IEC_61966_2_1 as _,
    ITU_R_BT_2020_2_10bit =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_2020_2_10bit as _,
    ITU_R_BT_2020_2_12bit =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_2020_2_12bit as _,
    ITU_R_BT_2100_0_PQ =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_2100_0_PQ as _,
    SMPTE_ST_428_1 =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_SMPTE_ST_428_1 as _,
    ITU_R_BT_2100_0_HLG =
        lh::heif_transfer_characteristics_heif_transfer_characteristic_ITU_R_BT_2100_0_HLG as _,
    /// This value is used when library `libheif` returns unknown value of transfer characteristics.
    Unknown,
}

#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, enumn::N)]
#[repr(C)]
pub enum MatrixCoefficients {
    RGB_GBR = lh::heif_matrix_coefficients_heif_matrix_coefficients_RGB_GBR as _,
    ITU_R_BT_709_5 = lh::heif_matrix_coefficients_heif_matrix_coefficients_ITU_R_BT_709_5 as _,
    Unspecified = lh::heif_matrix_coefficients_heif_matrix_coefficients_unspecified as _,
    US_FCC_T47 = lh::heif_matrix_coefficients_heif_matrix_coefficients_US_FCC_T47 as _,
    ITU_R_BT_470_6_System_B_G = lh::heif_matrix_coefficients_heif_matrix_coefficients_ITU_R_BT_470_6_System_B_G as _,
    ITU_R_BT_601_6 = lh::heif_matrix_coefficients_heif_matrix_coefficients_ITU_R_BT_601_6 as _,
    SMPTE_240M = lh::heif_matrix_coefficients_heif_matrix_coefficients_SMPTE_240M as _,
    YCgCo = lh::heif_matrix_coefficients_heif_matrix_coefficients_YCgCo as _,
    ITU_R_BT_2020_2_NonConstantLuminance = lh::heif_matrix_coefficients_heif_matrix_coefficients_ITU_R_BT_2020_2_non_constant_luminance as _,
    ITU_R_BT_2020_2_ConstantLuminance = lh::heif_matrix_coefficients_heif_matrix_coefficients_ITU_R_BT_2020_2_constant_luminance as _,
    SMPTE_ST_2085 = lh::heif_matrix_coefficients_heif_matrix_coefficients_SMPTE_ST_2085 as _,
    ChromaticityDerivedNonConstantLuminance = lh::heif_matrix_coefficients_heif_matrix_coefficients_chromaticity_derived_non_constant_luminance as _,
    ChromaticityDerivedConstantLuminance = lh::heif_matrix_coefficients_heif_matrix_coefficients_chromaticity_derived_constant_luminance as _,
    ICtCp = lh::heif_matrix_coefficients_heif_matrix_coefficients_ICtCp as _,
    /// This value is used when library `libheif` returns unknown value of matrix coefficients.
    Unknown,
}

pub trait ColorProfile {
    fn profile_type(&self) -> ColorProfileType;
}

pub struct ColorProfileRaw {
    pub(crate) typ: ColorProfileType,
    pub data: Vec<u8>,
}

impl ColorProfileRaw {
    pub fn new(typ: ColorProfileType, data: Vec<u8>) -> Self {
        Self { typ, data }
    }
}

impl ColorProfile for ColorProfileRaw {
    fn profile_type(&self) -> ColorProfileType {
        self.typ
    }
}

pub struct ColorProfileNCLX {
    pub(crate) inner: *mut lh::heif_color_profile_nclx,
}

impl Drop for ColorProfileNCLX {
    fn drop(&mut self) {
        unsafe {
            lh::heif_nclx_color_profile_free(self.inner);
        }
    }
}

impl ColorProfile for ColorProfileNCLX {
    fn profile_type(&self) -> ColorProfileType {
        color_profile_types::NCLX
    }
}

impl ColorProfileNCLX {
    pub fn new() -> Option<Self> {
        let inner = unsafe { lh::heif_nclx_color_profile_alloc() };
        (!inner.is_null()).then_some(Self { inner })
    }

    #[inline(always)]
    fn inner_ref(&self) -> &lh::heif_color_profile_nclx {
        unsafe { &(*self.inner) }
    }

    #[inline(always)]
    fn inner_mut(&mut self) -> &mut lh::heif_color_profile_nclx {
        unsafe { &mut (*self.inner) }
    }

    pub fn version(&self) -> u8 {
        self.inner_ref().version
    }

    pub fn color_primaries(&self) -> ColorPrimaries {
        ColorPrimaries::n(self.inner_ref().color_primaries).unwrap_or(ColorPrimaries::Unknown)
    }

    pub fn set_color_primaries(&mut self, v: ColorPrimaries) {
        if v != ColorPrimaries::Unknown {
            self.inner_mut().color_primaries = v as _;
        }
    }

    pub fn transfer_characteristics(&self) -> TransferCharacteristics {
        TransferCharacteristics::n(self.inner_ref().transfer_characteristics)
            .unwrap_or(TransferCharacteristics::Unknown)
    }

    pub fn matrix_coefficients(&self) -> MatrixCoefficients {
        MatrixCoefficients::n(self.inner_ref().matrix_coefficients)
            .unwrap_or(MatrixCoefficients::Unknown)
    }

    pub fn full_range_flag(&self) -> u8 {
        self.inner_ref().full_range_flag
    }

    pub fn color_primary_red_x(&self) -> f32 {
        self.inner_ref().color_primary_red_x
    }

    pub fn color_primary_red_y(&self) -> f32 {
        self.inner_ref().color_primary_red_y
    }

    pub fn color_primary_green_x(&self) -> f32 {
        self.inner_ref().color_primary_green_x
    }

    pub fn color_primary_green_y(&self) -> f32 {
        self.inner_ref().color_primary_green_y
    }

    pub fn color_primary_blue_x(&self) -> f32 {
        self.inner_ref().color_primary_blue_x
    }

    pub fn color_primary_blue_y(&self) -> f32 {
        self.inner_ref().color_primary_blue_y
    }

    pub fn color_primary_white_x(&self) -> f32 {
        self.inner_ref().color_primary_white_x
    }

    pub fn color_primary_white_y(&self) -> f32 {
        self.inner_ref().color_primary_white_y
    }
}