1use crate::codestream::ProgressionOrder;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct CodeBlockAddress {
13 pub layer: u16,
15 pub resolution: u8,
17 pub component: u16,
19 pub precinct: u32,
21}
22
23#[derive(Debug, Clone)]
28enum ProgressionState {
29 Lrcp {
30 layer: u16,
31 resolution: u8,
32 component: u16,
33 precinct: u32,
34 },
35 Rlcp {
36 resolution: u8,
37 layer: u16,
38 component: u16,
39 precinct: u32,
40 },
41 Rpcl {
42 resolution: u8,
43 precinct: u32,
44 component: u16,
45 layer: u16,
46 },
47 Pcrl {
48 precinct: u32,
49 component: u16,
50 resolution: u8,
51 layer: u16,
52 },
53 Cprl {
54 component: u16,
55 precinct: u32,
56 resolution: u8,
57 layer: u16,
58 },
59 Exhausted,
60}
61
62#[derive(Debug, Clone)]
68pub struct ProgressionIterator {
69 num_layers: u16,
70 num_resolutions: u8,
71 num_components: u16,
72 num_precincts: Vec<u32>,
74 state: ProgressionState,
75}
76
77impl ProgressionIterator {
78 pub fn new(
89 order: ProgressionOrder,
90 num_layers: u16,
91 num_resolutions: u8,
92 num_components: u16,
93 num_precincts: &[u32],
94 ) -> Self {
95 let resolved_precincts: Vec<u32> = if num_precincts.is_empty() {
97 vec![1; num_resolutions as usize]
98 } else {
99 let last = *num_precincts.last().unwrap_or(&1);
100 let mut v: Vec<u32> = num_precincts
101 .iter()
102 .take(num_resolutions as usize)
103 .copied()
104 .collect();
105 while v.len() < num_resolutions as usize {
106 v.push(last);
107 }
108 v
109 };
110
111 let state = if num_layers == 0 || num_resolutions == 0 || num_components == 0 {
112 ProgressionState::Exhausted
113 } else {
114 match order {
115 ProgressionOrder::Lrcp => ProgressionState::Lrcp {
116 layer: 0,
117 resolution: 0,
118 component: 0,
119 precinct: 0,
120 },
121 ProgressionOrder::Rlcp => ProgressionState::Rlcp {
122 resolution: 0,
123 layer: 0,
124 component: 0,
125 precinct: 0,
126 },
127 ProgressionOrder::Rpcl => ProgressionState::Rpcl {
128 resolution: 0,
129 precinct: 0,
130 component: 0,
131 layer: 0,
132 },
133 ProgressionOrder::Pcrl => ProgressionState::Pcrl {
134 precinct: 0,
135 component: 0,
136 resolution: 0,
137 layer: 0,
138 },
139 ProgressionOrder::Cprl => ProgressionState::Cprl {
140 component: 0,
141 precinct: 0,
142 resolution: 0,
143 layer: 0,
144 },
145 }
146 };
147
148 Self {
149 num_layers,
150 num_resolutions,
151 num_components,
152 num_precincts: resolved_precincts,
153 state,
154 }
155 }
156
157 pub fn total_packets(&self) -> u64 {
159 let precincts_total: u64 = self.num_precincts.iter().map(|&p| p as u64).sum();
160 precincts_total * self.num_layers as u64 * self.num_components as u64
161 }
162
163 fn precincts_for(&self, res: u8) -> u32 {
168 self.num_precincts
169 .get(res as usize)
170 .copied()
171 .unwrap_or(1)
172 .max(1)
173 }
174}
175
176impl Iterator for ProgressionIterator {
177 type Item = CodeBlockAddress;
178
179 fn next(&mut self) -> Option<Self::Item> {
180 match &self.state {
181 ProgressionState::Exhausted => None,
182
183 ProgressionState::Lrcp {
187 layer,
188 resolution,
189 component,
190 precinct,
191 } => {
192 let (l, r, c, p) = (*layer, *resolution, *component, *precinct);
193 let item = CodeBlockAddress {
194 layer: l,
195 resolution: r,
196 component: c,
197 precinct: p,
198 };
199
200 let max_p = self.precincts_for(r);
202 let next_p = p + 1;
203 let (nl, nr, nc, np) = if next_p < max_p {
204 (l, r, c, next_p)
205 } else {
206 let next_c = c + 1;
207 if next_c < self.num_components {
208 (l, r, next_c, 0)
209 } else {
210 let next_r = r + 1;
211 if next_r < self.num_resolutions {
212 (l, next_r, 0, 0)
213 } else {
214 let next_l = l + 1;
215 if next_l < self.num_layers {
216 (next_l, 0, 0, 0)
217 } else {
218 self.state = ProgressionState::Exhausted;
219 return Some(item);
220 }
221 }
222 }
223 };
224
225 self.state = ProgressionState::Lrcp {
226 layer: nl,
227 resolution: nr,
228 component: nc,
229 precinct: np,
230 };
231 Some(item)
232 }
233
234 ProgressionState::Rlcp {
238 resolution,
239 layer,
240 component,
241 precinct,
242 } => {
243 let (r, l, c, p) = (*resolution, *layer, *component, *precinct);
244 let item = CodeBlockAddress {
245 layer: l,
246 resolution: r,
247 component: c,
248 precinct: p,
249 };
250
251 let max_p = self.precincts_for(r);
252 let (nr, nl, nc, np) = if p + 1 < max_p {
253 (r, l, c, p + 1)
254 } else if c + 1 < self.num_components {
255 (r, l, c + 1, 0)
256 } else if l + 1 < self.num_layers {
257 (r, l + 1, 0, 0)
258 } else {
259 let next_r = r + 1;
260 if next_r < self.num_resolutions {
261 (next_r, 0, 0, 0)
262 } else {
263 self.state = ProgressionState::Exhausted;
264 return Some(item);
265 }
266 };
267
268 self.state = ProgressionState::Rlcp {
269 resolution: nr,
270 layer: nl,
271 component: nc,
272 precinct: np,
273 };
274 Some(item)
275 }
276
277 ProgressionState::Rpcl {
281 resolution,
282 precinct,
283 component,
284 layer,
285 } => {
286 let (r, p, c, l) = (*resolution, *precinct, *component, *layer);
287 let item = CodeBlockAddress {
288 layer: l,
289 resolution: r,
290 component: c,
291 precinct: p,
292 };
293
294 let max_p = self.precincts_for(r);
295 let (nr, np, nc, nl) = if l + 1 < self.num_layers {
296 (r, p, c, l + 1)
297 } else if c + 1 < self.num_components {
298 (r, p, c + 1, 0)
299 } else if p + 1 < max_p {
300 (r, p + 1, 0, 0)
301 } else {
302 let next_r = r + 1;
303 if next_r < self.num_resolutions {
304 (next_r, 0, 0, 0)
305 } else {
306 self.state = ProgressionState::Exhausted;
307 return Some(item);
308 }
309 };
310
311 self.state = ProgressionState::Rpcl {
312 resolution: nr,
313 precinct: np,
314 component: nc,
315 layer: nl,
316 };
317 Some(item)
318 }
319
320 ProgressionState::Pcrl {
324 precinct,
325 component,
326 resolution,
327 layer,
328 } => {
329 let (p, c, r, l) = (*precinct, *component, *resolution, *layer);
330 let item = CodeBlockAddress {
331 layer: l,
332 resolution: r,
333 component: c,
334 precinct: p,
335 };
336
337 let max_p = self.precincts_for(r);
338 let (np, nc, nr, nl) = if l + 1 < self.num_layers {
339 (p, c, r, l + 1)
340 } else if r + 1 < self.num_resolutions {
341 (p, c, r + 1, 0)
342 } else if c + 1 < self.num_components {
343 (p, c + 1, 0, 0)
344 } else if p + 1 < max_p {
345 (p + 1, 0, 0, 0)
346 } else {
347 self.state = ProgressionState::Exhausted;
348 return Some(item);
349 };
350
351 self.state = ProgressionState::Pcrl {
352 precinct: np,
353 component: nc,
354 resolution: nr,
355 layer: nl,
356 };
357 Some(item)
358 }
359
360 ProgressionState::Cprl {
364 component,
365 precinct,
366 resolution,
367 layer,
368 } => {
369 let (c, p, r, l) = (*component, *precinct, *resolution, *layer);
370 let item = CodeBlockAddress {
371 layer: l,
372 resolution: r,
373 component: c,
374 precinct: p,
375 };
376
377 let max_p = self.precincts_for(r);
378 let (nc, np, nr, nl) = if l + 1 < self.num_layers {
379 (c, p, r, l + 1)
380 } else if r + 1 < self.num_resolutions {
381 (c, p, r + 1, 0)
382 } else if p + 1 < max_p {
383 (c, p + 1, 0, 0)
384 } else {
385 let next_c = c + 1;
386 if next_c < self.num_components {
387 (next_c, 0, 0, 0)
388 } else {
389 self.state = ProgressionState::Exhausted;
390 return Some(item);
391 }
392 };
393
394 self.state = ProgressionState::Cprl {
395 component: nc,
396 precinct: np,
397 resolution: nr,
398 layer: nl,
399 };
400 Some(item)
401 }
402 }
403 }
404}
405
406#[cfg(test)]
407mod tests {
408 use super::*;
409 use crate::codestream::ProgressionOrder;
410
411 fn collect_all(iter: ProgressionIterator) -> Vec<CodeBlockAddress> {
412 iter.collect()
413 }
414
415 #[test]
416 fn test_lrcp_basic_order() {
417 let iter = ProgressionIterator::new(ProgressionOrder::Lrcp, 2, 2, 1, &[1, 1]);
419 let items = collect_all(iter);
420 assert_eq!(items.len(), 4);
422 assert_eq!(items[0].layer, 0);
423 assert_eq!(items[0].resolution, 0);
424 assert_eq!(items[1].layer, 0);
425 assert_eq!(items[1].resolution, 1);
426 assert_eq!(items[2].layer, 1);
427 assert_eq!(items[2].resolution, 0);
428 assert_eq!(items[3].layer, 1);
429 assert_eq!(items[3].resolution, 1);
430 }
431
432 #[test]
433 fn test_rlcp_basic_order() {
434 let iter = ProgressionIterator::new(ProgressionOrder::Rlcp, 2, 2, 1, &[1, 1]);
435 let items = collect_all(iter);
436 assert_eq!(items.len(), 4);
438 assert_eq!(items[0].resolution, 0);
439 assert_eq!(items[0].layer, 0);
440 assert_eq!(items[1].resolution, 0);
441 assert_eq!(items[1].layer, 1);
442 assert_eq!(items[2].resolution, 1);
443 assert_eq!(items[2].layer, 0);
444 }
445
446 #[test]
447 fn test_rpcl_basic_order() {
448 let iter = ProgressionIterator::new(ProgressionOrder::Rpcl, 1, 2, 2, &[1, 1]);
450 let items = collect_all(iter);
451 assert_eq!(items.len(), 4);
454 assert_eq!(items[0].resolution, 0);
455 assert_eq!(items[0].component, 0);
456 assert_eq!(items[1].resolution, 0);
457 assert_eq!(items[1].component, 1);
458 assert_eq!(items[2].resolution, 1);
459 assert_eq!(items[2].component, 0);
460 }
461
462 #[test]
463 fn test_pcrl_basic_order() {
464 let iter = ProgressionIterator::new(ProgressionOrder::Pcrl, 1, 1, 2, &[2]);
466 let items = collect_all(iter);
467 assert_eq!(items.len(), 4);
470 assert_eq!(items[0].precinct, 0);
471 assert_eq!(items[0].component, 0);
472 assert_eq!(items[1].precinct, 0);
473 assert_eq!(items[1].component, 1);
474 assert_eq!(items[2].precinct, 1);
475 assert_eq!(items[2].component, 0);
476 }
477
478 #[test]
479 fn test_cprl_basic_order() {
480 let iter = ProgressionIterator::new(ProgressionOrder::Cprl, 1, 2, 2, &[1, 1]);
482 let items = collect_all(iter);
483 assert_eq!(items.len(), 4);
486 assert_eq!(items[0].component, 0);
487 assert_eq!(items[0].resolution, 0);
488 assert_eq!(items[1].component, 0);
489 assert_eq!(items[1].resolution, 1);
490 assert_eq!(items[2].component, 1);
491 assert_eq!(items[2].resolution, 0);
492 }
493
494 #[test]
495 fn test_empty_iterator_zero_layers() {
496 let iter = ProgressionIterator::new(ProgressionOrder::Lrcp, 0, 3, 3, &[1, 1, 1]);
497 let items: Vec<_> = iter.collect();
498 assert!(items.is_empty());
499 }
500
501 #[test]
502 fn test_single_item_iterator() {
503 let iter = ProgressionIterator::new(ProgressionOrder::Lrcp, 1, 1, 1, &[1]);
504 let items: Vec<_> = iter.collect();
505 assert_eq!(items.len(), 1);
506 assert_eq!(items[0].layer, 0);
507 assert_eq!(items[0].resolution, 0);
508 assert_eq!(items[0].component, 0);
509 assert_eq!(items[0].precinct, 0);
510 }
511
512 #[test]
513 fn test_multiple_precincts_per_resolution() {
514 let iter = ProgressionIterator::new(ProgressionOrder::Lrcp, 1, 1, 1, &[3]);
516 let items: Vec<_> = iter.collect();
517 assert_eq!(items.len(), 3);
518 assert_eq!(items[0].precinct, 0);
519 assert_eq!(items[1].precinct, 1);
520 assert_eq!(items[2].precinct, 2);
521 }
522
523 #[test]
524 fn test_total_packets_count() {
525 let iter = ProgressionIterator::new(ProgressionOrder::Lrcp, 3, 2, 4, &[1, 1]);
528 assert_eq!(iter.total_packets(), 24);
529 }
530
531 #[test]
532 fn test_default_precincts_when_empty_slice() {
533 let iter = ProgressionIterator::new(ProgressionOrder::Lrcp, 1, 2, 1, &[]);
534 let items: Vec<_> = iter.collect();
535 assert_eq!(items.len(), 2);
537 }
538}