av_data/
pixel.rs

1//! Expose all necessary data structures to represent pixels.
2//!
3//! Re-exports num_traits::FromPrimitive and num_traits::cast::ToPrimitive
4//! in order to make easy to cast a parsed value into correct enum structures.
5
6use num_derive::{FromPrimitive, ToPrimitive};
7pub use num_traits::cast::ToPrimitive;
8pub use num_traits::FromPrimitive;
9use std::fmt;
10use std::ops::Index;
11use std::slice;
12
13/// YUV color range.
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15#[allow(clippy::upper_case_acronyms)]
16pub enum YUVRange {
17    /// Pixels in the range [16, 235].
18    Limited,
19    /// Pixels in the range [0, 255].
20    Full,
21}
22
23impl fmt::Display for YUVRange {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        match *self {
26            YUVRange::Limited => write!(f, "Limited range"),
27            YUVRange::Full => write!(f, "Full range"),
28        }
29    }
30}
31
32/// Describes the matrix coefficients used in deriving
33/// luma and chroma signals from the green, blue and red or X, Y and Z primaries.
34///
35/// Values adopted from Table 4 of ISO/IEC 23001-8:2013/DCOR1.
36#[allow(clippy::upper_case_acronyms)]
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromPrimitive, ToPrimitive)]
38pub enum MatrixCoefficients {
39    /// The identity matrix.
40    /// Typically used for:
41    ///
42    /// - GBR (often referred to as RGB)
43    /// - YZX (often referred to as XYZ)
44    /// - IEC 61966-2-1 sRGB
45    /// - SMPTE ST 428-1 (2019)
46    Identity = 0,
47    /// - Rec. ITU-R BT.709-6
48    /// - Rec. ITU-R BT.1361-0 conventional colour gamut system and extended colour
49    ///   gamut system (historical)
50    /// - IEC 61966-2-4 xvYCC709
51    /// - SMPTE RP 177 (1993) Annex B
52    BT709 = 1,
53    /// Image characteristics are unknown or are determined by the application.
54    Unspecified = 2,
55    /// For future use by ITU-T | ISO/IEC.
56    Reserved = 3,
57    /// United States Federal Communications Commission (2003) Title 47 Code of
58    /// Federal Regulations 73.682 (a) (20)
59    BT470M = 4,
60    /// - Rec. ITU-R BT.470-6 System B, G (historical)
61    /// - Rec. ITU-R BT.601-7 625
62    /// - Rec. ITU-R BT.1358-0 625 (historical)
63    /// - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
64    /// - IEC 61966-2-1 sYCC
65    /// - IEC 61966-2-4 xvYCC601
66    ///
67    /// (functionally the same as the value 6)
68    BT470BG = 5,
69    /// - Rec. ITU-R BT.601-7 525
70    /// - Rec. ITU-R BT.1358-1 525 or 625 (historical)
71    /// - Rec. ITU-R BT.1700-0 NTSC
72    /// - SMPTE ST 170 (2004)
73    ///
74    /// (functionally the same as the value 5)
75    ST170M = 6,
76    /// SMPTE ST 240 (1999)
77    ST240M = 7,
78    /// The YCoCg color model, also known as the YCgCo color model,
79    /// is the color space formed from a simple transformation of
80    /// an associated RGB color space into a luma value and
81    /// two chroma values called chrominance green and chrominance orange.
82    YCgCo = 8,
83    /// - Rec. ITU-R BT.2020-2 (non-constant luminance)
84    /// - Rec. ITU-R BT.2100-2 Y′CbCr
85    BT2020NonConstantLuminance = 9,
86    /// Rec. ITU-R BT.2020-2 (constant luminance)
87    BT2020ConstantLuminance = 10,
88    /// SMPTE ST 2085 (2015)
89    ST2085 = 11,
90    /// Chromaticity-derived non-constant luminance system.
91    ChromaticityDerivedNonConstantLuminance = 12,
92    /// Chromaticity-derived constant luminance system.
93    ChromaticityDerivedConstantLuminance = 13,
94    /// Rec. ITU-R BT.2100-2 ICTCP
95    ICtCp = 14,
96}
97
98impl fmt::Display for MatrixCoefficients {
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        match *self {
101            MatrixCoefficients::Identity => write!(f, "Identity"),
102            MatrixCoefficients::BT709 => write!(f, "ITU BT.709"),
103            MatrixCoefficients::Unspecified => write!(f, "Unspecified"),
104            MatrixCoefficients::Reserved => write!(f, "Reserved"),
105            MatrixCoefficients::BT470M => write!(f, "ITU BT.470M"),
106            MatrixCoefficients::BT470BG => write!(f, "ITU BT.470BG"),
107            MatrixCoefficients::ST170M => write!(f, "SMPTE ST-170M"),
108            MatrixCoefficients::ST240M => write!(f, "SMPTE ST-240M"),
109            MatrixCoefficients::YCgCo => write!(f, "YCgCo"),
110            MatrixCoefficients::BT2020NonConstantLuminance => {
111                write!(f, "ITU BT.2020 (Non Constant Luminance)")
112            }
113            MatrixCoefficients::BT2020ConstantLuminance => {
114                write!(f, "ITU BT.2020 (Constant Luminance)")
115            }
116            MatrixCoefficients::ST2085 => write!(f, "SMPTE ST-2085"),
117            MatrixCoefficients::ChromaticityDerivedNonConstantLuminance => {
118                write!(f, "Chromaticity Derived (Non ConstantLuminance)")
119            }
120            MatrixCoefficients::ChromaticityDerivedConstantLuminance => {
121                write!(f, "Chromaticity Derived (Constant Luminance)")
122            }
123            MatrixCoefficients::ICtCp => write!(f, "ICtCp"),
124        }
125    }
126}
127
128/// Indicates the chromaticity coordinates of the source colour primaries as specified in Table 2 in terms
129/// of the CIE 1931 definition of x and y as specified by ISO 11664-1.
130///
131/// Values adopted from Table 4 of ISO/IEC 23001-8:2013/DCOR1.
132#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromPrimitive, ToPrimitive)]
133#[allow(clippy::upper_case_acronyms)]
134pub enum ColorPrimaries {
135    /// For future use by ITU-T | ISO/IEC.
136    Reserved0 = 0,
137    /// - Rec. ITU-R BT.709-6
138    /// - Rec. ITU-R BT.1361-0 conventional colour gamut
139    ///   system and extended colour gamut system (historical)
140    /// - IEC 61966-2-1 sRGB or sYCC
141    /// - IEC 61966-2-4
142    /// - Society of Motion Picture and Television Engineers
143    ///   (SMPTE) RP 177 (1993) Annex B
144    BT709 = 1,
145    /// Image characteristics are unknown or are determined by
146    /// the application.
147    Unspecified = 2,
148    /// For future use by ITU-T | ISO/IEC.
149    Reserved = 3,
150    /// - Rec. ITU-R BT.470-6 System M (historical)
151    /// - United States National Television System Committee
152    ///   1953 Recommendation for transmission standards for
153    ///   color television
154    /// - United States Federal Communications Commission
155    ///   (2003) Title 47 Code of Federal Regulations 73.682 (a) (20)
156    BT470M = 4,
157    /// - Rec. ITU-R BT.470-6 System B, G (historical)
158    /// - Rec. ITU-R BT.601-7 625
159    /// - Rec. ITU-R BT.1358-0 625 (historical)
160    /// - Rec. ITU-R BT.1700-0 625 PAL and 625 SECAM
161    BT470BG = 5,
162    /// - Rec. ITU-R BT.601-7 525
163    /// - Rec. ITU-R BT.1358-1 525 or 625 (historical)
164    /// - Rec. ITU-R BT.1700-0 NTSC
165    /// - SMPTE ST 170 (2004)
166    ///
167    /// (functionally the same as the value 7)
168    ST170M = 6,
169    /// - SMPTE ST 240 (1999)
170    ///
171    /// (functionally the same as the value 6)
172    ST240M = 7,
173    /// Generic film (colour filters using Illuminant C)
174    Film = 8,
175    /// - Rec. ITU-R BT.2020-2
176    /// - Rec. ITU-R BT.2100-2
177    BT2020 = 9,
178    /// - SMPTE ST 428-1 (2019)
179    /// - (CIE 1931 XYZ as in ISO 11664-1)
180    ST428 = 10,
181    /// SMPTE RP 431-2 (2011)
182    P3DCI = 11,
183    /// SMPTE EG 432-1 (2010)
184    P3Display = 12,
185    /// No corresponding industry specification identified.
186    Tech3213 = 22,
187}
188
189impl fmt::Display for ColorPrimaries {
190    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
191        match *self {
192            ColorPrimaries::Reserved0 => write!(f, "Identity"),
193            ColorPrimaries::BT709 => write!(f, "ITU BT.709"),
194            ColorPrimaries::Unspecified => write!(f, "Unspecified"),
195            ColorPrimaries::Reserved => write!(f, "Reserved"),
196            ColorPrimaries::BT470M => write!(f, "ITU BT.470M"),
197            ColorPrimaries::BT470BG => write!(f, "ITU BT.470BG"),
198            ColorPrimaries::ST170M => write!(f, "SMPTE ST-170M"),
199            ColorPrimaries::ST240M => write!(f, "SMPTE ST-240M"),
200            ColorPrimaries::Film => write!(f, "Film"),
201            ColorPrimaries::BT2020 => write!(f, "ITU BT.2020"),
202            ColorPrimaries::ST428 => write!(f, "SMPTE ST-428"),
203            ColorPrimaries::P3DCI => write!(f, "DCI P3"),
204            ColorPrimaries::P3Display => write!(f, "Display P3"),
205            ColorPrimaries::Tech3213 => write!(f, "EBU Tech3213"),
206        }
207    }
208}
209
210/// Either indicates the reference opto-electronic transfer characteristic
211/// function of the source picture as a function of a source input linear optical intensity
212/// input Lc with a nominal real-valued range of 0 to 1 or indicates the inverse of the
213/// reference electro-optical transfer characteristic function as a function of an
214/// output linear optical intensity Lo with a nominal real-valued range of 0 to 1.
215///
216/// Values adopted from Table 4 of ISO/IEC 23001-8:2013/DCOR1.
217#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, FromPrimitive, ToPrimitive)]
218#[allow(clippy::upper_case_acronyms)]
219pub enum TransferCharacteristic {
220    /// For future use by ITU-T | ISO/IEC.
221    Reserved0 = 0,
222    /// - Rec. ITU-R BT.709-6
223    /// - Rec. ITU-R BT.1361-0 conventional
224    ///   colour gamut system (historical)
225    ///
226    /// (functionally the same as the values 6, 14 and 15)
227    BT1886 = 1,
228    /// Image characteristics are unknown or
229    /// are determined by the application.
230    Unspecified = 2,
231    /// For future use by ITU-T | ISO/IEC.
232    Reserved = 3,
233    /// Assumed display gamma 2.2.
234    ///
235    /// - Rec. ITU-R BT.470-6 System M
236    ///   (historical)
237    /// - United States National Television
238    ///   System Committee 1953
239    ///   Recommendation for transmission
240    ///   standards for color television
241    /// - United States Federal Communications
242    ///   Commission (2003) Title 47 Code of
243    ///   Federal Regulations 73.682 (a) (20)
244    /// - Rec. ITU-R BT.1700-0 625 PAL and
245    ///   625 SECAM
246    BT470M = 4,
247    /// Assumed display gamma 2.8.
248    ///
249    /// Rec. ITU-R BT.470-6 System B, G (historical)
250    BT470BG = 5,
251    /// - Rec. ITU-R BT.601-7 525 or 625
252    /// - Rec. ITU-R BT.1358-1 525 or 625
253    ///   (historical)
254    /// - Rec. ITU-R BT.1700-0 NTSC
255    /// - SMPTE ST 170 (2004)
256    ///
257    /// (functionally the same as the values 1, 14 and 15)
258    ST170M = 6,
259    /// SMPTE ST 240 (1999)
260    ST240M = 7,
261    /// Linear transfer characteristics
262    Linear = 8,
263    /// Logarithmic transfer characteristic
264    /// (100:1 range)
265    Logarithmic100 = 9,
266    /// Logarithmic transfer characteristic
267    /// (100 * Sqrt( 10 ) : 1 range)
268    Logarithmic316 = 10,
269    /// IEC 61966-2-4
270    XVYCC = 11,
271    /// Rec. ITU-R BT.1361-0 extended
272    /// colour gamut system (historical)
273    BT1361E = 12,
274    /// - IEC 61966-2-1 sRGB (with
275    ///   MatrixCoefficients equal to 0)
276    /// - IEC 61966-2-1 sYCC (with
277    ///   MatrixCoefficients equal to 5)
278    SRGB = 13,
279    /// Rec. ITU-R BT.2020-2 (10-bit system)
280    ///
281    /// (functionally the same as the values 1, 6 and 15)
282    BT2020Ten = 14,
283    /// Rec. ITU-R BT.2020-2 (12-bit system)
284    ///
285    /// (functionally the same as the values 1, 6 and 14)
286    BT2020Twelve = 15,
287    /// - SMPTE ST 2084 (2014) for 10-, 12-,
288    ///   14- and 16-bit systems
289    /// - Rec. ITU-R BT.2100-2 perceptual
290    ///   quantization (PQ) system
291    PerceptualQuantizer = 16,
292    /// SMPTE ST 428-1 (2019)
293    ST428 = 17,
294    /// - ARIB STD-B67 (2015)
295    /// - Rec. ITU-R BT.2100-2 hybrid log-
296    ///   gamma (HLG) system
297    HybridLogGamma = 18,
298}
299
300impl fmt::Display for TransferCharacteristic {
301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
302        match *self {
303            TransferCharacteristic::Reserved0 => write!(f, "Identity"),
304            TransferCharacteristic::BT1886 => write!(f, "ITU BT.1886"),
305            TransferCharacteristic::Unspecified => write!(f, "Unspecified"),
306            TransferCharacteristic::Reserved => write!(f, "Reserved"),
307            TransferCharacteristic::BT470M => write!(f, "ITU BT.470M"),
308            TransferCharacteristic::BT470BG => write!(f, "ITU BT.470BG"),
309            TransferCharacteristic::ST170M => write!(f, "SMPTE ST-170M"),
310            TransferCharacteristic::ST240M => write!(f, "SMPTE ST-240M"),
311            TransferCharacteristic::Linear => write!(f, "Linear"),
312            TransferCharacteristic::Logarithmic100 => write!(f, "Logarithmic 100:1 range"),
313            TransferCharacteristic::Logarithmic316 => write!(f, "Logarithmic 316:1 range"),
314            TransferCharacteristic::XVYCC => write!(f, "XVYCC"),
315            TransferCharacteristic::BT1361E => write!(f, "ITU BT.1361 Extended Color Gamut"),
316            TransferCharacteristic::SRGB => write!(f, "sRGB"),
317            TransferCharacteristic::BT2020Ten => write!(f, "ITU BT.2020 for 10bit systems"),
318            TransferCharacteristic::BT2020Twelve => write!(f, "ITU BT.2020 for 12bit systems"),
319            TransferCharacteristic::PerceptualQuantizer => write!(f, "Perceptual Quantizer"),
320            TransferCharacteristic::ST428 => write!(f, "SMPTE ST-428"),
321            TransferCharacteristic::HybridLogGamma => write!(f, "Hybrid Log-Gamma"),
322        }
323    }
324}
325
326/// Indicates the chroma sampling grid alignment for video fields or frames using the 4:2:0
327/// colour format (in which the two chroma arrays have half the width
328/// and half the height of the associated luma array)
329///
330/// Values adopted from Table 4 of ISO/IEC 23001-8:2013/DCOR1.
331#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
332#[allow(missing_docs)]
333pub enum ChromaLocation {
334    Unspecified = 0,
335    Left,
336    Center,
337    TopLeft,
338    Top,
339    BottomLeft,
340    Bottom,
341}
342
343impl fmt::Display for ChromaLocation {
344    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
345        use self::ChromaLocation::*;
346        match *self {
347            Unspecified => write!(f, "Unspecified"),
348            Left => write!(f, "Left"),
349            Center => write!(f, "Center"),
350            TopLeft => write!(f, "TopLeft"),
351            Top => write!(f, "Top"),
352            BottomLeft => write!(f, "BottomLeft"),
353            Bottom => write!(f, "Bottom"),
354        }
355    }
356}
357
358/// All YUV color representations.
359#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
360#[allow(clippy::upper_case_acronyms)]
361pub enum YUVSystem {
362    /// YCbCr is a family of color spaces used as a part of the color image pipeline
363    /// in video and digital photography systems. Y′ is the luma component and CB and CR
364    /// are the blue-difference and red-difference chroma components.
365    YCbCr(YUVRange),
366    /// The YCoCg color model, also known as the YCgCo color model,
367    /// is the color space formed from a simple transformation of
368    /// an associated RGB color space into a luma value and
369    /// two chroma values called chrominance green and chrominance orange.
370    YCoCg,
371    /// ICtCp is a color representation format specified in the Rec. ITU-R BT.2100 standard
372    /// that is used as a part of the color image pipeline in video and digital photography
373    /// systems for high dynamic range (HDR) and wide color gamut (WCG) imagery.
374    ICtCp,
375}
376
377impl fmt::Display for YUVSystem {
378    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
379        use self::YUVSystem::*;
380        match *self {
381            YCbCr(range) => write!(f, "YCbCr ({})", range),
382            YCoCg => write!(f, "YCbCg"),
383            ICtCp => write!(f, "ICtCp"),
384        }
385    }
386}
387
388/// Trichromatic color encoding system.
389#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
390#[allow(clippy::upper_case_acronyms)]
391pub enum TrichromaticEncodingSystem {
392    /// Image represented by three color channels: Red, Green, and Blue.
393    RGB,
394    /// Image represented by a luminance (luma) channel and two chroma channels.
395    YUV(YUVSystem),
396    /// In the CIE 1931 model, Y is the luminance, Z is quasi-equal to blue (of CIE RGB),
397    /// and X is a mix of the three CIE RGB curves chosen to be nonnegative.
398    /// Setting Y as luminance has the useful result that for any given Y value,
399    /// the XZ plane will contain all possible chromaticities at that luminance.
400    XYZ,
401}
402
403impl fmt::Display for TrichromaticEncodingSystem {
404    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
405        use self::TrichromaticEncodingSystem::*;
406        match *self {
407            YUV(system) => write!(f, "{}", system),
408            RGB => write!(f, "RGB"),
409            XYZ => write!(f, "XYZ"),
410        }
411    }
412}
413
414/// All supported color models.
415#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
416#[allow(clippy::upper_case_acronyms)]
417pub enum ColorModel {
418    /// An image represented by three channels or planes: Includes RGB, YUV, and XYZ.
419    Trichromatic(TrichromaticEncodingSystem),
420    /// The CMYK color model is a subtractive color model, based on the CMY color model,
421    /// used in color printing, and is also used to describe the printing process itself.
422    /// CMYK refers to the four ink plates used in some color printing: cyan, magenta, yellow, and key.
423    CMYK,
424    /// HSL and HSV are alternative representations of the RGB color model,
425    /// designed in the 1970s by computer graphics researchers to more closely align
426    /// with the way human vision perceives color-making attributes.
427    HSV,
428    /// The CIELAB color space expresses color as three values:
429    /// L* for perceptual lightness, and a* and b* for the four unique colors of human vision:
430    /// red, green, blue, and yellow.
431    LAB,
432}
433
434impl fmt::Display for ColorModel {
435    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
436        match *self {
437            ColorModel::Trichromatic(system) => write!(f, "{}", system),
438            ColorModel::CMYK => write!(f, "CMYK"),
439            ColorModel::HSV => write!(f, "HSV"),
440            ColorModel::LAB => write!(f, "LAB"),
441        }
442    }
443}
444
445impl ColorModel {
446    /// Returns the number of components of a color model.
447    pub fn get_default_components(self) -> usize {
448        match self {
449            ColorModel::CMYK => 4,
450            _ => 3,
451        }
452    }
453}
454
455/// Single colorspace component definition.
456///
457/// Defines how the components of a colorspace are subsampled and
458/// where and how they are stored.
459#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
460pub struct Chromaton {
461    /// Horizontal subsampling in power of two
462    /// (e.g. `0` = no subsampling, `1` = only every second value is stored).
463    pub h_ss: u8,
464    /// Vertical subsampling in power of two
465    /// (e.g. `0` = no subsampling, `1` = only every second value is stored).
466    pub v_ss: u8,
467    /// Tells if a component is packed.
468    pub packed: bool,
469    /// Bit depth of a component.
470    pub depth: u8,
471    /// Shift for packed components.
472    pub shift: u8,
473    /// Component offset for byte-packed components.
474    pub comp_offs: u8,
475    /// The distance to the next packed element in bytes.
476    pub next_elem: u8,
477}
478
479fn align(v: usize, a: usize) -> usize {
480    (v + a - 1) & !(a - 1)
481}
482
483impl Chromaton {
484    /// Constructs a new `Chromaton` instance.
485    pub const fn new(
486        h_ss: u8,
487        v_ss: u8,
488        packed: bool,
489        depth: u8,
490        shift: u8,
491        comp_offs: u8,
492        next_elem: u8,
493    ) -> Self {
494        Chromaton {
495            h_ss,
496            v_ss,
497            packed,
498            depth,
499            shift,
500            comp_offs,
501            next_elem,
502        }
503    }
504
505    /// Constructs a specific `Chromaton` instance for `yuv8`.
506    pub const fn yuv8(h_ss: u8, v_ss: u8, comp_offs: u8) -> Chromaton {
507        Chromaton::new(h_ss, v_ss, false, 8, 0, comp_offs, 1)
508    }
509
510    /// Constructs a specific `Chromaton` instance for `yuvhb`.
511    pub const fn yuvhb(h_ss: u8, v_ss: u8, depth: u8, comp_offs: u8) -> Chromaton {
512        Chromaton::new(h_ss, v_ss, false, depth, 0, comp_offs, 1)
513    }
514
515    /// Constructs a specific `Chromaton` instance for `packrgb`.
516    pub const fn packrgb(depth: u8, shift: u8, comp_offs: u8, next_elem: u8) -> Chromaton {
517        Chromaton::new(0, 0, true, depth, shift, comp_offs, next_elem)
518    }
519
520    /// Constructs a specific `Chromaton` instance for `pal8`.
521    pub const fn pal8(comp_offs: u8) -> Chromaton {
522        Chromaton::new(0, 0, true, 8, 0, comp_offs, 3)
523    }
524
525    /// Returns the subsampling of a component.
526    pub fn get_subsampling(self) -> (u8, u8) {
527        (self.h_ss, self.v_ss)
528    }
529
530    /// Tells whether a component is packed.
531    pub fn is_packed(self) -> bool {
532        self.packed
533    }
534
535    /// Returns the bit depth of a component.
536    pub fn get_depth(self) -> u8 {
537        self.depth
538    }
539
540    /// Returns the bit shift of a packed component.
541    pub fn get_shift(self) -> u8 {
542        self.shift
543    }
544
545    /// Returns the byte offset of a packed component.
546    pub fn get_offset(self) -> u8 {
547        self.comp_offs
548    }
549
550    /// Returns the byte offset to the next element of a packed component.
551    pub fn get_step(self) -> u8 {
552        self.next_elem
553    }
554
555    /// Calculates the width for a component from general image width.
556    pub fn get_width(self, width: usize) -> usize {
557        (width + ((1 << self.h_ss) - 1)) >> self.h_ss
558    }
559
560    /// Calculates the height for a component from general image height.
561    pub fn get_height(self, height: usize) -> usize {
562        (height + ((1 << self.v_ss) - 1)) >> self.v_ss
563    }
564
565    /// Calculates the minimal stride for a component from general image width.
566    pub fn get_linesize(self, width: usize, alignment: usize) -> usize {
567        let d = self.depth as usize;
568        align((self.get_width(width) * d + d - 1) >> 3, alignment)
569    }
570
571    /// Calculates the required image size in pixels for a component
572    /// from general image width.
573    pub fn get_data_size(self, width: usize, height: usize, align: usize) -> usize {
574        let nh = (height + ((1 << self.v_ss) - 1)) >> self.v_ss;
575        self.get_linesize(width, align) * nh
576    }
577}
578
579impl fmt::Display for Chromaton {
580    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
581        let pfmt = if self.packed {
582            let mask = ((1 << self.depth) - 1) << self.shift;
583            format!(
584                "packed(+{},{:X}, step {})",
585                self.comp_offs, mask, self.next_elem
586            )
587        } else {
588            format!("planar({},{})", self.comp_offs, self.next_elem)
589        };
590        write!(f, "({}x{}, {})", self.h_ss, self.v_ss, pfmt)
591    }
592}
593
594/// Image colorspace representation.
595///
596/// Includes both definitions for each component and some common definitions.
597///
598/// For example, the format can be paletted, so the components describe
599/// the palette storage format, while the actual data is 8-bit palette indices.
600#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
601pub struct Formaton {
602    /// Image color model.
603    pub model: ColorModel,
604    /// Image color primaries.
605    pub primaries: ColorPrimaries,
606    /// Image transfer characteristic.
607    pub xfer: TransferCharacteristic,
608    /// Image matrix coefficients.
609    pub matrix: MatrixCoefficients,
610    /// Image chroma location.
611    pub chroma_location: ChromaLocation,
612
613    /// Actual number of components present.
614    pub components: u8,
615    /// Format definition for each component.
616    pub comp_info: [Option<Chromaton>; 5],
617    /// Single pixel size for packed formats.
618    pub elem_size: u8,
619    /// Tells if data is stored as big-endian.
620    pub be: bool,
621    /// Tells if image has alpha component.
622    pub alpha: bool,
623    /// Tells if data is paletted.
624    pub palette: bool,
625}
626
627impl Formaton {
628    /// Constructs a new instance of `Formaton`.
629    pub fn new(
630        model: ColorModel,
631        components: &[Chromaton],
632        elem_size: u8,
633        be: bool,
634        alpha: bool,
635        palette: bool,
636    ) -> Self {
637        let mut c: [Option<Chromaton>; 5] = [None; 5];
638
639        if components.len() > 5 {
640            panic!("too many components");
641        }
642
643        for (i, v) in components.iter().enumerate() {
644            c[i] = Some(*v);
645        }
646
647        Formaton {
648            model,
649
650            primaries: ColorPrimaries::Unspecified,
651            xfer: TransferCharacteristic::Unspecified,
652            matrix: MatrixCoefficients::Unspecified,
653            chroma_location: ChromaLocation::Unspecified,
654
655            components: components.len() as u8,
656            comp_info: c,
657            elem_size,
658            be,
659            alpha,
660            palette,
661        }
662    }
663
664    /// Returns current color model.
665    pub fn get_model(&self) -> ColorModel {
666        self.model
667    }
668
669    /// Returns current image primaries.
670    pub fn get_primaries(&self) -> ColorPrimaries {
671        self.primaries
672    }
673
674    /// Returns the total amount of bits needed for components.
675    pub fn get_total_depth(&self) -> u8 {
676        let mut depth = 0;
677        for chromaton in self.comp_info.iter().flatten() {
678            depth += chromaton.depth;
679        }
680        depth
681    }
682
683    /// Sets current image primaries.
684    pub fn set_primaries(mut self, pc: ColorPrimaries) {
685        self.primaries = pc;
686    }
687
688    /// Sets current image primaries from `u32`.
689    pub fn set_primaries_from_u32(mut self, pc: u32) -> Option<ColorPrimaries> {
690        let parsed_pc = ColorPrimaries::from_u32(pc);
691        if let Some(pc) = parsed_pc {
692            self.primaries = pc
693        }
694        parsed_pc
695    }
696
697    /// Returns current image transfer characteristic.
698    pub fn get_xfer(&self) -> TransferCharacteristic {
699        self.xfer
700    }
701
702    /// Sets current image transfer characteristic.
703    pub fn set_xfer(mut self, pc: TransferCharacteristic) {
704        self.xfer = pc;
705    }
706
707    /// Sets current image transfer characteristic from `u32`.
708    pub fn set_xfer_from_u32(mut self, tc: u32) -> Option<TransferCharacteristic> {
709        let parsed_tc = TransferCharacteristic::from_u32(tc);
710        if let Some(tc) = parsed_tc {
711            self.xfer = tc
712        }
713        parsed_tc
714    }
715
716    /// Returns current image matrix coefficients.
717    pub fn get_matrix(&self) -> MatrixCoefficients {
718        self.matrix
719    }
720
721    /// Sets current image matrix coefficients.
722    pub fn set_matrix(mut self, mc: MatrixCoefficients) {
723        self.matrix = mc;
724    }
725
726    /// Sets current image matrix coefficients from `u32`.
727    pub fn set_matrix_from_u32(mut self, mc: u32) -> Option<MatrixCoefficients> {
728        let parsed_mc = MatrixCoefficients::from_u32(mc);
729        if let Some(mc) = parsed_mc {
730            self.matrix = mc
731        }
732        parsed_mc
733    }
734
735    /// Returns the number of components.
736    pub fn get_num_comp(&self) -> usize {
737        self.components as usize
738    }
739    /// Returns selected component information.
740    pub fn get_chromaton(&self, idx: usize) -> Option<Chromaton> {
741        if idx < self.comp_info.len() {
742            return self.comp_info[idx];
743        }
744        None
745    }
746
747    /// Reports whether the packing format is big-endian.
748    pub fn is_be(&self) -> bool {
749        self.be
750    }
751
752    /// Reports whether a colorspace has an alpha component.
753    pub fn has_alpha(&self) -> bool {
754        self.alpha
755    }
756
757    /// Reports whether this is a paletted format.
758    pub fn is_paletted(&self) -> bool {
759        self.palette
760    }
761
762    /// Returns single packed pixel size.
763    pub fn get_elem_size(&self) -> u8 {
764        self.elem_size
765    }
766
767    /// Returns an iterator over the format definition of each component.
768    pub fn iter(&self) -> slice::Iter<Option<Chromaton>> {
769        self.comp_info.iter()
770    }
771}
772
773impl<'a> Index<usize> for &'a Formaton {
774    type Output = Option<Chromaton>;
775
776    fn index(&self, index: usize) -> &Self::Output {
777        self.comp_info.index(index)
778    }
779}
780
781impl<'a> IntoIterator for &'a Formaton {
782    type Item = &'a Option<Chromaton>;
783    type IntoIter = slice::Iter<'a, Option<Chromaton>>;
784
785    fn into_iter(self) -> Self::IntoIter {
786        self.comp_info.iter()
787    }
788}
789
790impl fmt::Display for Formaton {
791    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
792        let end = if self.be { "BE" } else { "LE" };
793        let palstr = if self.palette { "palette " } else { "" };
794        let astr = if self.alpha { "alpha " } else { "" };
795        let mut str = format!(
796            "Formaton for {} ({}{}elem {} size {}): ",
797            self.model, palstr, astr, end, self.elem_size
798        );
799        for &i in self.into_iter() {
800            if let Some(chr) = i {
801                str = format!("{} {}", str, chr);
802            }
803        }
804        write!(f, "[{}]", str)
805    }
806}
807
808pub mod formats {
809    //!
810    //! Ready-to-use formaton
811    //!
812
813    use self::ColorModel::*;
814    use self::TrichromaticEncodingSystem::*;
815    use self::YUVRange::*;
816    use self::YUVSystem::*;
817    use crate::pixel::*;
818
819    /// Predefined format for planar 8-bit YUV with 4:4:4 subsampling.
820    pub const YUV444: &Formaton = &Formaton {
821        model: Trichromatic(YUV(YCbCr(Limited))),
822        primaries: ColorPrimaries::Unspecified,
823        xfer: TransferCharacteristic::Unspecified,
824        matrix: MatrixCoefficients::Unspecified,
825        chroma_location: ChromaLocation::Unspecified,
826        components: 3,
827        comp_info: [
828            Some(Chromaton::new(0, 0, false, 8, 0, 0, 1)),
829            Some(Chromaton::yuv8(0, 0, 1)),
830            Some(Chromaton::yuv8(0, 0, 2)),
831            None,
832            None,
833        ],
834        elem_size: 0,
835        be: false,
836        alpha: false,
837        palette: false,
838    };
839
840    /// Predefined format for planar 8-bit YUV with 4:2:2 subsampling.
841    pub const YUV422: &Formaton = &Formaton {
842        model: Trichromatic(YUV(YCbCr(Limited))),
843        primaries: ColorPrimaries::Unspecified,
844        xfer: TransferCharacteristic::Unspecified,
845        matrix: MatrixCoefficients::Unspecified,
846        chroma_location: ChromaLocation::Unspecified,
847        components: 3,
848        comp_info: [
849            Some(Chromaton::new(0, 0, false, 8, 0, 0, 1)),
850            Some(Chromaton::yuv8(0, 1, 1)),
851            Some(Chromaton::yuv8(0, 1, 2)),
852            None,
853            None,
854        ],
855        elem_size: 0,
856        be: false,
857        alpha: false,
858        palette: false,
859    };
860
861    /// Predefined format for planar 8-bit YUV with 4:2:0 subsampling.
862    pub const YUV420: &Formaton = &Formaton {
863        model: Trichromatic(YUV(YCbCr(Limited))),
864        primaries: ColorPrimaries::Unspecified,
865        xfer: TransferCharacteristic::Unspecified,
866        matrix: MatrixCoefficients::Unspecified,
867        chroma_location: ChromaLocation::Unspecified,
868        components: 3,
869        comp_info: [
870            Some(Chromaton::new(0, 0, false, 8, 0, 0, 1)),
871            Some(Chromaton::yuv8(1, 1, 1)),
872            Some(Chromaton::yuv8(1, 1, 2)),
873            None,
874            None,
875        ],
876        elem_size: 0,
877        be: false,
878        alpha: false,
879        palette: false,
880    };
881
882    /// Predefined format for planar 8-bit YUV with 4:1:1 subsampling.
883    pub const YUV411: &Formaton = &Formaton {
884        model: Trichromatic(YUV(YCbCr(Limited))),
885        primaries: ColorPrimaries::Unspecified,
886        xfer: TransferCharacteristic::Unspecified,
887        matrix: MatrixCoefficients::Unspecified,
888        chroma_location: ChromaLocation::Unspecified,
889        components: 3,
890        comp_info: [
891            Some(Chromaton::new(0, 0, false, 8, 0, 0, 1)),
892            Some(Chromaton::yuv8(2, 0, 1)),
893            Some(Chromaton::yuv8(2, 0, 2)),
894            None,
895            None,
896        ],
897        elem_size: 0,
898        be: false,
899        alpha: false,
900        palette: false,
901    };
902
903    /// Predefined format for planar 8-bit YUV with 4:1:0 subsampling.
904    pub const YUV410: &Formaton = &Formaton {
905        model: Trichromatic(YUV(YCbCr(Limited))),
906        primaries: ColorPrimaries::Unspecified,
907        xfer: TransferCharacteristic::Unspecified,
908        matrix: MatrixCoefficients::Unspecified,
909        chroma_location: ChromaLocation::Unspecified,
910        components: 3,
911        comp_info: [
912            Some(Chromaton::new(0, 0, false, 8, 0, 0, 1)),
913            Some(Chromaton::yuv8(2, 1, 1)),
914            Some(Chromaton::yuv8(2, 1, 2)),
915            None,
916            None,
917        ],
918        elem_size: 0,
919        be: false,
920        alpha: false,
921        palette: false,
922    };
923
924    /// Predefined format for planar 10-bit YUV with 4:4:4 subsampling.
925    pub const YUV444_10: &Formaton = &Formaton {
926        model: Trichromatic(YUV(YCbCr(Limited))),
927        primaries: ColorPrimaries::Unspecified,
928        xfer: TransferCharacteristic::Unspecified,
929        matrix: MatrixCoefficients::Unspecified,
930        chroma_location: ChromaLocation::Unspecified,
931        components: 3,
932        comp_info: [
933            Some(Chromaton::new(0, 0, false, 10, 0, 0, 1)),
934            Some(Chromaton::yuvhb(0, 0, 1, 10)),
935            Some(Chromaton::yuvhb(0, 0, 2, 10)),
936            None,
937            None,
938        ],
939        elem_size: 0,
940        be: false,
941        alpha: false,
942        palette: false,
943    };
944
945    /// Predefined format for planar 10-bit YUV with 4:2:2 subsampling.
946    pub const YUV422_10: &Formaton = &Formaton {
947        model: Trichromatic(YUV(YCbCr(Limited))),
948        primaries: ColorPrimaries::Unspecified,
949        xfer: TransferCharacteristic::Unspecified,
950        matrix: MatrixCoefficients::Unspecified,
951        chroma_location: ChromaLocation::Unspecified,
952        components: 3,
953        comp_info: [
954            Some(Chromaton::new(0, 0, false, 10, 0, 0, 1)),
955            Some(Chromaton::yuvhb(0, 1, 1, 10)),
956            Some(Chromaton::yuvhb(0, 1, 2, 10)),
957            None,
958            None,
959        ],
960        elem_size: 0,
961        be: false,
962        alpha: false,
963        palette: false,
964    };
965
966    /// Predefined format for planar 10-bit YUV with 4:2:0 subsampling.
967    pub const YUV420_10: &Formaton = &Formaton {
968        model: Trichromatic(YUV(YCbCr(Limited))),
969        primaries: ColorPrimaries::Unspecified,
970        xfer: TransferCharacteristic::Unspecified,
971        matrix: MatrixCoefficients::Unspecified,
972        chroma_location: ChromaLocation::Unspecified,
973        components: 3,
974        comp_info: [
975            Some(Chromaton::new(0, 0, false, 10, 0, 0, 1)),
976            Some(Chromaton::yuvhb(1, 1, 1, 10)),
977            Some(Chromaton::yuvhb(1, 1, 2, 10)),
978            None,
979            None,
980        ],
981        elem_size: 0,
982        be: false,
983        alpha: false,
984        palette: false,
985    };
986
987    /// Predefined format for planar 10-bit YUV with 4:1:1 subsampling.
988    pub const YUV411_10: &Formaton = &Formaton {
989        model: Trichromatic(YUV(YCbCr(Limited))),
990        primaries: ColorPrimaries::Unspecified,
991        xfer: TransferCharacteristic::Unspecified,
992        matrix: MatrixCoefficients::Unspecified,
993        chroma_location: ChromaLocation::Unspecified,
994        components: 3,
995        comp_info: [
996            Some(Chromaton::new(0, 0, false, 10, 0, 0, 1)),
997            Some(Chromaton::yuvhb(2, 0, 1, 10)),
998            Some(Chromaton::yuvhb(2, 0, 2, 10)),
999            None,
1000            None,
1001        ],
1002        elem_size: 0,
1003        be: false,
1004        alpha: false,
1005        palette: false,
1006    };
1007
1008    /// Predefined format for planar 10-bit YUV with 4:1:0 subsampling.
1009    pub const YUV410_10: &Formaton = &Formaton {
1010        model: Trichromatic(YUV(YCbCr(Limited))),
1011        primaries: ColorPrimaries::Unspecified,
1012        xfer: TransferCharacteristic::Unspecified,
1013        matrix: MatrixCoefficients::Unspecified,
1014        chroma_location: ChromaLocation::Unspecified,
1015        components: 3,
1016        comp_info: [
1017            Some(Chromaton::new(0, 0, false, 10, 0, 0, 1)),
1018            Some(Chromaton::yuvhb(2, 1, 1, 10)),
1019            Some(Chromaton::yuvhb(2, 1, 2, 10)),
1020            None,
1021            None,
1022        ],
1023        elem_size: 0,
1024        be: false,
1025        alpha: false,
1026        palette: false,
1027    };
1028
1029    /// Predefined format with RGB24 palette.
1030    pub const PAL8: &Formaton = &Formaton {
1031        model: Trichromatic(RGB),
1032        primaries: ColorPrimaries::Unspecified,
1033        xfer: TransferCharacteristic::Unspecified,
1034        matrix: MatrixCoefficients::Unspecified,
1035        chroma_location: ChromaLocation::Unspecified,
1036        components: 3,
1037        comp_info: [
1038            Some(Chromaton::pal8(0)),
1039            Some(Chromaton::pal8(1)),
1040            Some(Chromaton::pal8(2)),
1041            None,
1042            None,
1043        ],
1044        elem_size: 3,
1045        be: false,
1046        alpha: false,
1047        palette: true,
1048    };
1049
1050    /// Predefined format for RGB565 packed video.
1051    pub const RGB565: &Formaton = &Formaton {
1052        model: Trichromatic(RGB),
1053        primaries: ColorPrimaries::Unspecified,
1054        xfer: TransferCharacteristic::Unspecified,
1055        matrix: MatrixCoefficients::Unspecified,
1056        chroma_location: ChromaLocation::Unspecified,
1057        components: 3,
1058        comp_info: [
1059            Some(Chromaton::packrgb(5, 11, 0, 2)),
1060            Some(Chromaton::packrgb(6, 5, 0, 2)),
1061            Some(Chromaton::packrgb(5, 0, 0, 2)),
1062            None,
1063            None,
1064        ],
1065        elem_size: 2,
1066        be: false,
1067        alpha: false,
1068        palette: false,
1069    };
1070
1071    /// Predefined format for RGB24.
1072    pub const RGB24: &Formaton = &Formaton {
1073        model: Trichromatic(RGB),
1074        primaries: ColorPrimaries::Unspecified,
1075        xfer: TransferCharacteristic::Unspecified,
1076        matrix: MatrixCoefficients::Unspecified,
1077        chroma_location: ChromaLocation::Unspecified,
1078        components: 3,
1079        comp_info: [
1080            Some(Chromaton::packrgb(8, 0, 2, 3)),
1081            Some(Chromaton::packrgb(8, 0, 1, 3)),
1082            Some(Chromaton::packrgb(8, 0, 0, 3)),
1083            None,
1084            None,
1085        ],
1086        elem_size: 3,
1087        be: false,
1088        alpha: false,
1089        palette: false,
1090    };
1091
1092    /// Predefined format for RGBA.
1093    pub const RGBA: &Formaton = &Formaton {
1094        model: Trichromatic(RGB),
1095        primaries: ColorPrimaries::Unspecified,
1096        xfer: TransferCharacteristic::Unspecified,
1097        matrix: MatrixCoefficients::Unspecified,
1098        chroma_location: ChromaLocation::Unspecified,
1099        components: 4,
1100        comp_info: [
1101            Some(Chromaton::packrgb(8, 0, 3, 4)),
1102            Some(Chromaton::packrgb(8, 0, 2, 4)),
1103            Some(Chromaton::packrgb(8, 0, 1, 4)),
1104            Some(Chromaton::packrgb(8, 0, 0, 4)),
1105            None,
1106        ],
1107        elem_size: 4,
1108        be: false,
1109        alpha: true,
1110        palette: false,
1111    };
1112
1113    /// Predefined format for RGB48.
1114    pub const RGB48: &Formaton = &Formaton {
1115        model: Trichromatic(RGB),
1116        primaries: ColorPrimaries::Unspecified,
1117        xfer: TransferCharacteristic::Unspecified,
1118        matrix: MatrixCoefficients::Unspecified,
1119        chroma_location: ChromaLocation::Unspecified,
1120        components: 3,
1121        comp_info: [
1122            Some(Chromaton::packrgb(16, 0, 2, 6)),
1123            Some(Chromaton::packrgb(16, 0, 1, 6)),
1124            Some(Chromaton::packrgb(16, 0, 0, 6)),
1125            None,
1126            None,
1127        ],
1128        elem_size: 6,
1129        be: false,
1130        alpha: false,
1131        palette: false,
1132    };
1133
1134    /// Predefined format for RGBA64.
1135    pub const RGBA64: &Formaton = &Formaton {
1136        model: Trichromatic(RGB),
1137        primaries: ColorPrimaries::Unspecified,
1138        xfer: TransferCharacteristic::Unspecified,
1139        matrix: MatrixCoefficients::Unspecified,
1140        chroma_location: ChromaLocation::Unspecified,
1141        components: 4,
1142        comp_info: [
1143            Some(Chromaton::packrgb(16, 0, 3, 8)),
1144            Some(Chromaton::packrgb(16, 0, 2, 8)),
1145            Some(Chromaton::packrgb(16, 0, 1, 8)),
1146            Some(Chromaton::packrgb(16, 0, 0, 8)),
1147            None,
1148        ],
1149        elem_size: 8,
1150        be: false,
1151        alpha: true,
1152        palette: false,
1153    };
1154}
1155
1156#[cfg(test)]
1157mod test {
1158    mod formats {
1159        use super::super::*;
1160        #[test]
1161        fn fmt() {
1162            println!("formaton yuv- {}", formats::YUV420);
1163            println!("formaton pal- {}", formats::PAL8);
1164            println!("formaton rgb565- {}", formats::RGB565);
1165            println!("formaton rgba- {}", formats::RGBA);
1166            println!("formaton rgb48- {}", formats::RGB48);
1167            println!("formaton rgba64- {}", formats::RGBA64);
1168        }
1169
1170        #[test]
1171        fn comparison() {
1172            use std::sync::Arc;
1173            let rcf = Arc::new(*formats::YUV420);
1174            let cf = &formats::YUV420.clone();
1175
1176            if cf != formats::YUV420 {
1177                panic!("cf");
1178            }
1179
1180            if *rcf != *formats::YUV420 {
1181                panic!("rcf");
1182            }
1183        }
1184    }
1185}