zenjxl_decoder/headers/
extra_channels.rs1use crate::{
7 bit_reader::BitReader,
8 error::Error,
9 headers::{bit_depth::BitDepth, encodings::*},
10};
11use jxl_macros::UnconditionalCoder;
12use num_derive::FromPrimitive;
13
14#[allow(clippy::upper_case_acronyms)]
15#[derive(UnconditionalCoder, Copy, Clone, PartialEq, Debug, FromPrimitive, Eq)]
16pub enum ExtraChannel {
17 Alpha,
18 Depth,
19 SpotColor,
20 SelectionMask,
21 Black,
22 CFA,
23 Thermal,
24 Reserved0,
25 Reserved1,
26 Reserved2,
27 Reserved3,
28 Reserved4,
29 Reserved5,
30 Reserved6,
31 Reserved7,
32 Unknown,
33 Optional,
34}
35
36#[allow(dead_code)]
38#[derive(UnconditionalCoder, Debug, Clone)]
39#[validate]
40pub struct ExtraChannelInfo {
41 #[all_default]
42 all_default: bool,
43 #[default(ExtraChannel::Alpha)]
44 pub ec_type: ExtraChannel,
45 #[default(BitDepth::default(&field_nonserialized))]
46 bit_depth: BitDepth,
47 #[coder(u2S(0, 3, 4, Bits(3) + 1))]
48 #[default(0)]
49 dim_shift: u32,
50 name: String,
51 #[condition(ec_type == ExtraChannel::Alpha)]
53 #[default(false)]
54 alpha_associated: bool,
55 #[condition(ec_type == ExtraChannel::SpotColor)]
56 pub spot_color: Option<[f32; 4]>,
57 #[condition(ec_type == ExtraChannel::CFA)]
58 #[coder(u2S(1, Bits(2), Bits(4) + 3, Bits(8) + 19))]
59 cfa_channel: Option<u32>,
60}
61
62impl ExtraChannelInfo {
63 #[cfg(test)]
64 #[allow(clippy::too_many_arguments)]
65 pub fn new(
66 all_default: bool,
67 ec_type: ExtraChannel,
68 bit_depth: BitDepth,
69 dim_shift: u32,
70 name: String,
71 alpha_associated: bool,
72 spot_color: Option<[f32; 4]>,
73 cfa_channel: Option<u32>,
74 ) -> ExtraChannelInfo {
75 ExtraChannelInfo {
76 all_default,
77 ec_type,
78 bit_depth,
79 dim_shift,
80 name,
81 alpha_associated,
82 spot_color,
83 cfa_channel,
84 }
85 }
86 pub fn dim_shift(&self) -> u32 {
87 self.dim_shift
88 }
89 pub fn alpha_associated(&self) -> bool {
90 self.alpha_associated
91 }
92 pub fn bit_depth(&self) -> BitDepth {
93 self.bit_depth
94 }
95 pub fn name(&self) -> &str {
97 &self.name
98 }
99 fn check(&self, _: &Empty) -> Result<(), Error> {
100 if self.dim_shift > 3 {
101 Err(Error::DimShiftTooLarge(self.dim_shift))
102 } else {
103 Ok(())
104 }
105 }
106}