1use std::ops::Range;
2
3use crate::adam7::{Adam7Info, Adam7Iterator};
4
5/// Describes which interlacing algorithm applies to a decoded row.
6///
7/// PNG (2003) specifies two interlace modes, but reserves future extensions.
8///
9/// See also [Reader.next_interlaced_row](crate::Reader::next_interlaced_row).
10#[derive(Clone, Copy, Debug)]
11pub enum InterlaceInfo {
12 /// The `null` method means no interlacing.
13 Null(NullInfo),
14 /// [The `Adam7` algorithm](https://en.wikipedia.org/wiki/Adam7_algorithm) derives its name
15 /// from doing 7 passes over the image, only decoding a subset of all pixels in each pass.
16 /// The following table shows pictorially what parts of each 8x8 area of the image is found in
17 /// each pass:
18 ///
19 /// ```txt
20 /// 1 6 4 6 2 6 4 6
21 /// 7 7 7 7 7 7 7 7
22 /// 5 6 5 6 5 6 5 6
23 /// 7 7 7 7 7 7 7 7
24 /// 3 6 4 6 3 6 4 6
25 /// 7 7 7 7 7 7 7 7
26 /// 5 6 5 6 5 6 5 6
27 /// 7 7 7 7 7 7 7 7
28 /// ```
29 Adam7(Adam7Info),
30}
31
32#[derive(Clone, Copy, Debug)]
33pub struct NullInfo {
34 line: u32,
35}
36
37impl InterlaceInfo {
38 pub(crate) fn line_number(&self) -> u32 {
39 match self {
40 InterlaceInfo::Null(NullInfo { line: &u32 }) => *line,
41 InterlaceInfo::Adam7(Adam7Info { line: &u32, .. }) => *line,
42 }
43 }
44
45 pub(crate) fn get_adam7_info(&self) -> Option<&Adam7Info> {
46 match self {
47 InterlaceInfo::Null(_) => None,
48 InterlaceInfo::Adam7(adam7info: &Adam7Info) => Some(adam7info),
49 }
50 }
51}
52
53pub(crate) struct InterlaceInfoIter(IterImpl);
54
55impl InterlaceInfoIter {
56 pub fn empty() -> Self {
57 Self(IterImpl::None(0..0))
58 }
59
60 pub fn new(width: u32, height: u32, interlaced: bool) -> Self {
61 if interlaced {
62 Self(IterImpl::Adam7(Adam7Iterator::new(width, height)))
63 } else {
64 Self(IterImpl::None(0..height))
65 }
66 }
67}
68
69impl Iterator for InterlaceInfoIter {
70 type Item = InterlaceInfo;
71
72 fn next(&mut self) -> Option<InterlaceInfo> {
73 match self.0 {
74 IterImpl::Adam7(ref mut adam7: &mut Adam7Iterator) => Some(InterlaceInfo::Adam7(adam7.next()?)),
75 IterImpl::None(ref mut height: &mut Range) => Some(InterlaceInfo::Null(NullInfo {
76 line: height.next()?,
77 })),
78 }
79 }
80}
81
82enum IterImpl {
83 None(Range<u32>),
84 Adam7(Adam7Iterator),
85}
86
87#[cfg(test)]
88mod test {
89 use super::*;
90
91 #[test]
92 fn null() {
93 assert_eq!(
94 InterlaceInfoIter::new(8, 8, false)
95 .map(|info| info.line_number())
96 .collect::<Vec<_>>(),
97 vec![0, 1, 2, 3, 4, 5, 6, 7],
98 );
99 }
100
101 #[test]
102 fn adam7() {
103 assert_eq!(
104 InterlaceInfoIter::new(8, 8, true)
105 .map(|info| info.line_number())
106 .collect::<Vec<_>>(),
107 vec![
108 0, // pass 1
109 0, // pass 2
110 0, // pass 3
111 0, 1, // pass 4
112 0, 1, // pass 5
113 0, 1, 2, 3, // pass 6
114 0, 1, 2, 3, // pass 7
115 ],
116 );
117 }
118
119 #[test]
120 fn empty() {
121 assert_eq!(
122 InterlaceInfoIter::empty()
123 .map(|info| info.line_number())
124 .collect::<Vec<_>>(),
125 vec![],
126 );
127 }
128}
129

Provided by KDAB

Privacy Policy