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