1use crate::*;
2
3use super::{Btrt, Pasp, Visual};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7pub struct Uncv {
8 pub visual: Visual,
9 pub cmpd: Option<Cmpd>,
10 pub uncc: UncC,
11 pub btrt: Option<Btrt>,
12 pub ccst: Option<Ccst>,
13 pub pasp: Option<Pasp>,
14}
15
16impl Atom for Uncv {
17 const KIND: FourCC = FourCC::new(b"uncv");
18
19 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
20 let visual = Visual::decode(buf)?;
21
22 let mut ccst = None;
23 let mut cmpd = None;
24 let mut uncc = None;
25 let mut btrt = None;
26 let mut pasp = None;
27 while let Some(atom) = Any::decode_maybe(buf)? {
28 match atom {
29 Any::Cmpd(atom) => cmpd = atom.into(),
30 Any::UncC(atom) => uncc = atom.into(),
31 Any::Btrt(atom) => btrt = atom.into(),
32 Any::Ccst(atom) => ccst = atom.into(),
33 Any::Pasp(atom) => pasp = atom.into(),
34 _ => tracing::warn!("unknown atom: {:?}", atom),
35 }
36 }
37
38 Ok(Uncv {
39 visual,
40 cmpd,
41 uncc: uncc.ok_or(Error::MissingBox(UncC::KIND))?,
42 btrt,
43 ccst,
44 pasp,
45 })
46 }
47
48 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
49 self.visual.encode(buf)?;
50 if self.cmpd.is_some() {
51 self.cmpd.encode(buf)?;
52 }
53 self.uncc.encode(buf)?;
54 if self.btrt.is_some() {
55 self.btrt.encode(buf)?;
56 }
57 if self.ccst.is_some() {
58 self.ccst.encode(buf)?;
59 }
60 if self.pasp.is_some() {
61 self.pasp.encode(buf)?;
62 }
63
64 Ok(())
65 }
66}
67
68#[derive(Debug, Clone, PartialEq, Eq)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub struct Component {
71 pub component_type: u16,
72 pub component_type_uri: Option<String>,
73}
74
75#[derive(Debug, Clone, PartialEq, Eq, Default)]
76#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
77pub struct Cmpd {
78 pub components: Vec<Component>,
79}
80
81impl Atom for Cmpd {
82 const KIND: FourCC = FourCC::new(b"cmpd");
83
84 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
85 let component_count = u32::decode(buf)?;
86 let mut components: Vec<Component> = Vec::with_capacity(component_count as usize);
87 for _ in 0..component_count {
88 let component_type = u16::decode(buf)?;
89 if component_type >= 0x8000 {
90 let component_type_uri = String::decode(buf)?;
91 components.push(Component {
92 component_type,
93 component_type_uri: Some(component_type_uri),
94 });
95 } else {
96 components.push(Component {
97 component_type,
98 component_type_uri: None,
99 });
100 }
101 }
102 Ok(Cmpd { components })
103 }
104
105 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
106 let component_count: u32 = self.components.len() as u32;
107 component_count.encode(buf)?;
108 for component in &self.components {
109 component.component_type.encode(buf)?;
110 if component.component_type >= 0x8000 {
111 let component_type_uri = component
112 .component_type_uri
113 .as_ref()
114 .expect("Expected valid URI when component_type is >= 0x8000");
115 component_type_uri.as_str().encode(buf)?;
116 }
117 }
118 Ok(())
119 }
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
123#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
124pub struct UncompressedComponent {
125 pub component_index: u16,
126 pub component_bit_depth_minus_one: u8,
127 pub component_format: u8,
128 pub component_align_size: u8,
129}
130
131ext! {
132 name: UncC,
133 versions: [0, 1],
134 flags: {}
135}
136
137#[derive(Debug, Clone, PartialEq, Eq)]
138#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
139pub enum UncC {
140 V1 {
141 profile: FourCC,
142 },
143 V0 {
144 profile: FourCC,
145 components: Vec<UncompressedComponent>,
146 sampling_type: u8, interleave_type: u8, block_size: u8,
149 components_little_endian: bool,
150 block_pad_lsb: bool,
151 block_little_endian: bool,
152 block_reversed: bool,
153 pad_unknown: bool,
154 pixel_size: u32,
155 row_align_size: u32,
156 tile_align_size: u32,
157 num_tile_cols_minus_one: u32,
158 num_tile_rows_minus_one: u32,
159 },
160}
161
162impl AtomExt for UncC {
163 const KIND_EXT: FourCC = FourCC::new(b"uncC");
164
165 type Ext = UncCExt;
166
167 fn decode_body_ext<B: Buf>(buf: &mut B, ext: UncCExt) -> Result<Self> {
168 match ext.version {
169 UncCVersion::V1 => Ok(UncC::V1 {
170 profile: FourCC::decode(buf)?,
171 }),
172 UncCVersion::V0 => {
173 let profile = FourCC::decode(buf)?;
174 let component_count = u32::decode(buf)?;
175 let mut components = Vec::with_capacity(component_count as usize);
176 for _ in 0..component_count {
177 components.push(UncompressedComponent {
178 component_index: u16::decode(buf)?,
179 component_bit_depth_minus_one: u8::decode(buf)?,
180 component_format: u8::decode(buf)?,
181 component_align_size: u8::decode(buf)?,
182 });
183 }
184 let sampling_type = u8::decode(buf)?;
185 let interleave_type = u8::decode(buf)?;
186 let block_size = u8::decode(buf)?;
187 let flag_bits = u8::decode(buf)?;
188 let components_little_endian = flag_bits & 0x80 == 0x80;
189 let block_pad_lsb = flag_bits & 0x40 == 0x40;
190 let block_little_endian = flag_bits & 0x20 == 0x20;
191 let block_reversed = flag_bits & 0x10 == 0x10;
192 let pad_unknown = flag_bits & 0x08 == 0x08;
193 let pixel_size = u32::decode(buf)?;
194 let row_align_size = u32::decode(buf)?;
195 let tile_align_size = u32::decode(buf)?;
196 let num_tile_cols_minus_one = u32::decode(buf)?;
197 let num_tile_rows_minus_one = u32::decode(buf)?;
198 Ok(UncC::V0 {
199 profile,
200 components,
201 sampling_type,
202 interleave_type,
203 block_size,
204 components_little_endian,
205 block_pad_lsb,
206 block_little_endian,
207 block_reversed,
208 pad_unknown,
209 pixel_size,
210 row_align_size,
211 tile_align_size,
212 num_tile_cols_minus_one,
213 num_tile_rows_minus_one,
214 })
215 }
216 }
217 }
218
219 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<UncCExt> {
220 match self {
221 UncC::V1 { profile } => {
222 profile.encode(buf)?;
223 Ok(UncCExt {
224 version: UncCVersion::V1,
225 })
226 }
227 UncC::V0 {
228 profile,
229 components,
230 sampling_type,
231 interleave_type,
232 block_size,
233 components_little_endian,
234 block_pad_lsb,
235 block_little_endian,
236 block_reversed,
237 pad_unknown,
238 pixel_size,
239 row_align_size,
240 tile_align_size,
241 num_tile_cols_minus_one,
242 num_tile_rows_minus_one,
243 } => {
244 profile.encode(buf)?;
245 let component_count: u32 = components.len() as u32;
246 component_count.encode(buf)?;
247 for component in components {
248 component.component_index.encode(buf)?;
249 component.component_bit_depth_minus_one.encode(buf)?;
250 component.component_format.encode(buf)?;
251 component.component_align_size.encode(buf)?;
252 }
253 sampling_type.encode(buf)?;
254 interleave_type.encode(buf)?;
255 block_size.encode(buf)?;
256 let mut flags: u8 = 0x00;
257 if *components_little_endian {
258 flags |= 0x80u8;
259 }
260 if *block_pad_lsb {
261 flags |= 0x40u8;
262 }
263 if *block_little_endian {
264 flags |= 0x20u8;
265 }
266 if *block_reversed {
267 flags |= 0x10u8;
268 }
269 if *pad_unknown {
270 flags |= 0x08u8;
271 }
272 flags.encode(buf)?;
273 pixel_size.encode(buf)?;
274 row_align_size.encode(buf)?;
275 tile_align_size.encode(buf)?;
276 num_tile_cols_minus_one.encode(buf)?;
277 num_tile_rows_minus_one.encode(buf)?;
278 Ok(UncCExt {
279 version: UncCVersion::V0,
280 })
281 }
282 }
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use super::*;
289
290 const ENCODED_CMPD: &[u8] = &[
291 0x00, 0x00, 0x00, 0x12, 0x63, 0x6d, 0x70, 0x64, 0x00, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00,
292 0x05, 0x00, 0x06,
293 ];
294
295 const ENCODED_UNCC: &[u8] = &[
296 0x00, 0x00, 0x00, 0x3b, 0x75, 0x6e, 0x63, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x07, 0x00, 0x00,
298 0x00, 0x02, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 ];
301
302 #[test]
303 fn test_cmpd_decode() {
304 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_CMPD);
305
306 let cmpd = Cmpd::decode(buf).expect("failed to decode cmpd");
307
308 assert_eq!(
309 cmpd,
310 Cmpd {
311 components: vec![
312 Component {
313 component_type: 4,
314 component_type_uri: None
315 },
316 Component {
317 component_type: 5,
318 component_type_uri: None
319 },
320 Component {
321 component_type: 6,
322 component_type_uri: None
323 }
324 ]
325 },
326 );
327 }
328
329 #[test]
330 fn test_cmpd_encode() {
331 let cmpd = Cmpd {
332 components: vec![
333 Component {
334 component_type: 4,
335 component_type_uri: None,
336 },
337 Component {
338 component_type: 5,
339 component_type_uri: None,
340 },
341 Component {
342 component_type: 6,
343 component_type_uri: None,
344 },
345 ],
346 };
347
348 let mut buf = Vec::new();
349 cmpd.encode(&mut buf).unwrap();
350
351 assert_eq!(buf.as_slice(), ENCODED_CMPD);
352 }
353
354 #[test]
355 fn test_uncc_decode() {
356 let buf: &mut std::io::Cursor<&&[u8]> = &mut std::io::Cursor::new(&ENCODED_UNCC);
357
358 let uncc = UncC::decode(buf).expect("failed to decode uncC");
359
360 assert_eq!(
361 uncc,
362 UncC::V0 {
363 profile: FourCC::new(b"\0\0\0\0"),
364 components: vec![
365 UncompressedComponent {
366 component_index: 0,
367 component_bit_depth_minus_one: 7,
368 component_format: 0,
369 component_align_size: 0
370 },
371 UncompressedComponent {
372 component_index: 1,
373 component_bit_depth_minus_one: 7,
374 component_format: 0,
375 component_align_size: 0
376 },
377 UncompressedComponent {
378 component_index: 2,
379 component_bit_depth_minus_one: 7,
380 component_format: 0,
381 component_align_size: 0
382 },
383 ],
384 sampling_type: 0,
385 interleave_type: 1,
386 block_size: 0,
387 components_little_endian: false,
388 block_pad_lsb: false,
389 block_little_endian: false,
390 block_reversed: false,
391 pad_unknown: false,
392 pixel_size: 0,
393 row_align_size: 0,
394 tile_align_size: 0,
395 num_tile_cols_minus_one: 0,
396 num_tile_rows_minus_one: 0
397 }
398 );
399 }
400
401 #[test]
402 fn test_uncc_encode() {
403 let uncc = UncC::V0 {
404 profile: FourCC::new(b"\0\0\0\0"),
405 components: vec![
406 UncompressedComponent {
407 component_index: 0,
408 component_bit_depth_minus_one: 7,
409 component_format: 0,
410 component_align_size: 0,
411 },
412 UncompressedComponent {
413 component_index: 1,
414 component_bit_depth_minus_one: 7,
415 component_format: 0,
416 component_align_size: 0,
417 },
418 UncompressedComponent {
419 component_index: 2,
420 component_bit_depth_minus_one: 7,
421 component_format: 0,
422 component_align_size: 0,
423 },
424 ],
425 sampling_type: 0,
426 interleave_type: 1,
427 block_size: 0,
428 components_little_endian: false,
429 block_pad_lsb: false,
430 block_little_endian: false,
431 block_reversed: false,
432 pad_unknown: false,
433 pixel_size: 0,
434 row_align_size: 0,
435 tile_align_size: 0,
436 num_tile_cols_minus_one: 0,
437 num_tile_rows_minus_one: 0,
438 };
439
440 let mut buf = Vec::new();
441 uncc.encode(&mut buf).unwrap();
442
443 assert_eq!(buf.as_slice(), ENCODED_UNCC);
444 }
445}