1use crate::{headers::extra_channels::ExtraChannel, image::DataTypeTag};
7
8#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9pub enum JxlColorType {
10 Grayscale,
11 GrayscaleAlpha,
12 Rgb,
13 Rgba,
14 Bgr,
15 Bgra,
16}
17
18impl JxlColorType {
19 pub fn has_alpha(&self) -> bool {
20 match self {
21 Self::Grayscale => false,
22 Self::GrayscaleAlpha => true,
23 Self::Rgb | Self::Bgr => false,
24 Self::Rgba | Self::Bgra => true,
25 }
26 }
27 pub fn samples_per_pixel(&self) -> usize {
28 match self {
29 Self::Grayscale => 1,
30 Self::GrayscaleAlpha => 2,
31 Self::Rgb | Self::Bgr => 3,
32 Self::Rgba | Self::Bgra => 4,
33 }
34 }
35 pub fn is_grayscale(&self) -> bool {
36 match self {
37 Self::Grayscale => true,
38 Self::GrayscaleAlpha => true,
39 Self::Rgb | Self::Bgr => false,
40 Self::Rgba | Self::Bgra => false,
41 }
42 }
43 pub fn add_alpha(&self) -> Self {
44 match self {
45 Self::Grayscale | Self::GrayscaleAlpha => Self::GrayscaleAlpha,
46 Self::Rgb | Self::Rgba => Self::Rgba,
47 Self::Bgr | Self::Bgra => Self::Bgra,
48 }
49 }
50}
51
52#[derive(Clone, Copy, Debug, PartialEq, Eq)]
59pub struct VardctQuantizer {
60 pub global_scale: u32,
63 pub quant_lf: u32,
66}
67
68impl VardctQuantizer {
69 pub fn inv_global_scale(&self) -> f32 {
73 crate::frame::quantizer::GLOBAL_SCALE_DENOM as f32 / self.global_scale as f32
74 }
75}
76
77#[derive(Clone, Copy, Debug, PartialEq, Eq)]
78pub enum Endianness {
79 LittleEndian,
80 BigEndian,
81}
82
83impl Endianness {
84 pub fn native() -> Self {
85 #[cfg(target_endian = "little")]
86 {
87 Endianness::LittleEndian
88 }
89 #[cfg(target_endian = "big")]
90 {
91 Endianness::BigEndian
92 }
93 }
94}
95
96#[derive(Clone, Copy, Debug, PartialEq, Eq)]
97pub enum JxlDataFormat {
98 U8 {
99 bit_depth: u8,
100 },
101 U16 {
102 endianness: Endianness,
103 bit_depth: u8,
104 },
105 F16 {
106 endianness: Endianness,
107 },
108 F32 {
109 endianness: Endianness,
110 },
111}
112
113impl JxlDataFormat {
114 pub fn bytes_per_sample(&self) -> usize {
115 match self {
116 Self::U8 { .. } => 1,
117 Self::U16 { .. } | Self::F16 { .. } => 2,
118 Self::F32 { .. } => 4,
119 }
120 }
121
122 pub fn f32() -> Self {
123 Self::F32 {
124 endianness: Endianness::native(),
125 }
126 }
127
128 pub(crate) fn data_type(&self) -> DataTypeTag {
129 match self {
130 JxlDataFormat::U8 { .. } => DataTypeTag::U8,
131 JxlDataFormat::U16 { .. } => DataTypeTag::U16,
132 JxlDataFormat::F16 { .. } => DataTypeTag::F16,
133 JxlDataFormat::F32 { .. } => DataTypeTag::F32,
134 }
135 }
136
137 pub(crate) fn opaque_alpha_bytes(&self) -> Vec<u8> {
139 match self {
140 JxlDataFormat::U8 { bit_depth } => {
141 let val = (1u16 << bit_depth) - 1;
142 vec![val as u8]
143 }
144 JxlDataFormat::U16 {
145 endianness,
146 bit_depth,
147 } => {
148 let val = (1u32 << bit_depth) - 1;
149 let val = val as u16;
150 if *endianness == Endianness::LittleEndian {
151 val.to_le_bytes().to_vec()
152 } else {
153 val.to_be_bytes().to_vec()
154 }
155 }
156 JxlDataFormat::F16 { endianness } => {
157 let val: u16 = 0x3C00;
159 if *endianness == Endianness::LittleEndian {
160 val.to_le_bytes().to_vec()
161 } else {
162 val.to_be_bytes().to_vec()
163 }
164 }
165 JxlDataFormat::F32 { endianness } => {
166 let val: f32 = 1.0;
167 if *endianness == Endianness::LittleEndian {
168 val.to_le_bytes().to_vec()
169 } else {
170 val.to_be_bytes().to_vec()
171 }
172 }
173 }
174 }
175}
176
177#[derive(Clone, Debug, PartialEq, Eq)]
178pub struct JxlPixelFormat {
179 pub color_type: JxlColorType,
180 pub color_data_format: Option<JxlDataFormat>,
182 pub extra_channel_format: Vec<Option<JxlDataFormat>>,
183}
184
185impl JxlPixelFormat {
186 pub fn rgba8(num_extra_channels: usize) -> Self {
188 Self {
189 color_type: JxlColorType::Rgba,
190 color_data_format: Some(JxlDataFormat::U8 { bit_depth: 8 }),
191 extra_channel_format: vec![
192 Some(JxlDataFormat::U8 { bit_depth: 8 });
193 num_extra_channels
194 ],
195 }
196 }
197
198 pub fn rgba16(num_extra_channels: usize) -> Self {
200 Self {
201 color_type: JxlColorType::Rgba,
202 color_data_format: Some(JxlDataFormat::U16 {
203 endianness: Endianness::native(),
204 bit_depth: 16,
205 }),
206 extra_channel_format: vec![
207 Some(JxlDataFormat::U16 {
208 endianness: Endianness::native(),
209 bit_depth: 16,
210 });
211 num_extra_channels
212 ],
213 }
214 }
215
216 pub fn rgba_f16(num_extra_channels: usize) -> Self {
218 Self {
219 color_type: JxlColorType::Rgba,
220 color_data_format: Some(JxlDataFormat::F16 {
221 endianness: Endianness::native(),
222 }),
223 extra_channel_format: vec![
224 Some(JxlDataFormat::F16 {
225 endianness: Endianness::native(),
226 });
227 num_extra_channels
228 ],
229 }
230 }
231
232 pub fn rgba_f32(num_extra_channels: usize) -> Self {
234 Self {
235 color_type: JxlColorType::Rgba,
236 color_data_format: Some(JxlDataFormat::F32 {
237 endianness: Endianness::native(),
238 }),
239 extra_channel_format: vec![
240 Some(JxlDataFormat::F32 {
241 endianness: Endianness::native(),
242 });
243 num_extra_channels
244 ],
245 }
246 }
247}
248
249#[derive(Clone, Debug, PartialEq, Eq)]
250pub enum JxlBitDepth {
251 Int {
252 bits_per_sample: u32,
253 },
254 Float {
255 bits_per_sample: u32,
256 exponent_bits_per_sample: u32,
257 },
258}
259
260impl JxlBitDepth {
261 pub fn bits_per_sample(&self) -> u32 {
262 match self {
263 JxlBitDepth::Int { bits_per_sample: b } => *b,
264 JxlBitDepth::Float {
265 bits_per_sample: b, ..
266 } => *b,
267 }
268 }
269}
270
271#[derive(Clone, Debug, PartialEq, Eq)]
272pub struct JxlExtraChannel {
273 pub ec_type: ExtraChannel,
274 pub alpha_associated: bool,
275 pub bits_per_sample: u32,
277 pub name: String,
279 pub dim_shift: u32,
281}
282
283#[derive(Clone, Debug, PartialEq, Eq)]
284pub struct JxlAnimation {
285 pub tps_numerator: u32,
286 pub tps_denominator: u32,
287 pub num_loops: u32,
288 pub have_timecodes: bool,
289}
290
291#[derive(Clone, Debug)]
292pub struct JxlFrameHeader {
293 pub name: String,
294 pub duration: Option<f64>,
295 pub size: (usize, usize),
297}