1 | use crate::decoder::{Decoder, MAX_COMPONENTS}; |
2 | use crate::error::{Error, Result}; |
3 | use crate::huffman::HuffmanDecoder; |
4 | use crate::marker::Marker; |
5 | use crate::parser::Predictor; |
6 | use crate::parser::{Component, FrameInfo, ScanInfo}; |
7 | use std::io::Read; |
8 | |
9 | impl<R: Read> Decoder<R> { |
10 | /// decode_scan_lossless |
11 | pub fn decode_scan_lossless( |
12 | &mut self, |
13 | frame: &FrameInfo, |
14 | scan: &ScanInfo, |
15 | ) -> Result<(Option<Marker>, Vec<Vec<u16>>)> { |
16 | let ncomp = scan.component_indices.len(); |
17 | let npixel = frame.image_size.height as usize * frame.image_size.width as usize; |
18 | assert!(ncomp <= MAX_COMPONENTS); |
19 | let mut results = vec![vec![0u16; npixel]; ncomp]; |
20 | |
21 | let components: Vec<Component> = scan |
22 | .component_indices |
23 | .iter() |
24 | .map(|&i| frame.components[i].clone()) |
25 | .collect(); |
26 | |
27 | // Verify that all required huffman tables has been set. |
28 | if scan |
29 | .dc_table_indices |
30 | .iter() |
31 | .any(|&i| self.dc_huffman_tables[i].is_none()) |
32 | { |
33 | return Err(Error::Format( |
34 | "scan makes use of unset dc huffman table" .to_owned(), |
35 | )); |
36 | } |
37 | |
38 | let mut huffman = HuffmanDecoder::new(); |
39 | let reader = &mut self.reader; |
40 | let mut mcus_left_until_restart = self.restart_interval; |
41 | let mut expected_rst_num = 0; |
42 | let mut ra = [0u16; MAX_COMPONENTS]; |
43 | let mut rb = [0u16; MAX_COMPONENTS]; |
44 | let mut rc = [0u16; MAX_COMPONENTS]; |
45 | |
46 | let width = frame.image_size.width as usize; |
47 | let height = frame.image_size.height as usize; |
48 | |
49 | let mut differences = vec![Vec::with_capacity(npixel); ncomp]; |
50 | for _mcu_y in 0..height { |
51 | for _mcu_x in 0..width { |
52 | if self.restart_interval > 0 { |
53 | if mcus_left_until_restart == 0 { |
54 | match huffman.take_marker(reader)? { |
55 | Some(Marker::RST(n)) => { |
56 | if n != expected_rst_num { |
57 | return Err(Error::Format(format!( |
58 | "found RST {} where RST {} was expected" , |
59 | n, expected_rst_num |
60 | ))); |
61 | } |
62 | |
63 | huffman.reset(); |
64 | |
65 | expected_rst_num = (expected_rst_num + 1) % 8; |
66 | mcus_left_until_restart = self.restart_interval; |
67 | } |
68 | Some(marker) => { |
69 | return Err(Error::Format(format!( |
70 | "found marker {:?} inside scan where RST {} was expected" , |
71 | marker, expected_rst_num |
72 | ))) |
73 | } |
74 | None => { |
75 | return Err(Error::Format(format!( |
76 | "no marker found where RST {} was expected" , |
77 | expected_rst_num |
78 | ))) |
79 | } |
80 | } |
81 | } |
82 | |
83 | mcus_left_until_restart -= 1; |
84 | } |
85 | |
86 | for (i, _component) in components.iter().enumerate() { |
87 | let dc_table = self.dc_huffman_tables[scan.dc_table_indices[i]] |
88 | .as_ref() |
89 | .unwrap(); |
90 | let value = huffman.decode(reader, dc_table)?; |
91 | let diff = match value { |
92 | 0 => 0, |
93 | 1..=15 => huffman.receive_extend(reader, value)? as i32, |
94 | 16 => 32768, |
95 | _ => { |
96 | // Section F.1.2.1.1 |
97 | // Table F.1 |
98 | return Err(Error::Format( |
99 | "invalid DC difference magnitude category" .to_owned(), |
100 | )); |
101 | } |
102 | }; |
103 | differences[i].push(diff); |
104 | } |
105 | } |
106 | } |
107 | |
108 | if scan.predictor_selection == Predictor::Ra { |
109 | for (i, _component) in components.iter().enumerate() { |
110 | // calculate the top left pixel |
111 | let diff = differences[i][0]; |
112 | let prediction = 1 << (frame.precision - scan.point_transform - 1) as i32; |
113 | let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 |
114 | let result = result << scan.point_transform; |
115 | results[i][0] = result; |
116 | |
117 | // calculate leftmost column, using top pixel as predictor |
118 | let mut previous = result; |
119 | for mcu_y in 1..height { |
120 | let diff = differences[i][mcu_y * width]; |
121 | let prediction = previous as i32; |
122 | let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 |
123 | let result = result << scan.point_transform; |
124 | results[i][mcu_y * width] = result; |
125 | previous = result; |
126 | } |
127 | |
128 | // calculate rows, using left pixel as predictor |
129 | for mcu_y in 0..height { |
130 | for mcu_x in 1..width { |
131 | let diff = differences[i][mcu_y * width + mcu_x]; |
132 | let prediction = results[i][mcu_y * width + mcu_x - 1] as i32; |
133 | let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 |
134 | let result = result << scan.point_transform; |
135 | results[i][mcu_y * width + mcu_x] = result; |
136 | } |
137 | } |
138 | } |
139 | } else { |
140 | for mcu_y in 0..height { |
141 | for mcu_x in 0..width { |
142 | for (i, _component) in components.iter().enumerate() { |
143 | let diff = differences[i][mcu_y * width + mcu_x]; |
144 | |
145 | // The following lines could be further optimized, e.g. moving the checks |
146 | // and updates of the previous values into the prediction function or |
147 | // iterating such that diagonals with mcu_x + mcu_y = const are computed at |
148 | // the same time to exploit independent predictions in this case |
149 | if mcu_x > 0 { |
150 | ra[i] = results[i][mcu_y * frame.image_size.width as usize + mcu_x - 1]; |
151 | } |
152 | if mcu_y > 0 { |
153 | rb[i] = |
154 | results[i][(mcu_y - 1) * frame.image_size.width as usize + mcu_x]; |
155 | if mcu_x > 0 { |
156 | rc[i] = results[i] |
157 | [(mcu_y - 1) * frame.image_size.width as usize + (mcu_x - 1)]; |
158 | } |
159 | } |
160 | let prediction = predict( |
161 | ra[i] as i32, |
162 | rb[i] as i32, |
163 | rc[i] as i32, |
164 | scan.predictor_selection, |
165 | scan.point_transform, |
166 | frame.precision, |
167 | mcu_x, |
168 | mcu_y, |
169 | self.restart_interval > 0 |
170 | && mcus_left_until_restart == self.restart_interval - 1, |
171 | ); |
172 | let result = ((prediction + diff) & 0xFFFF) as u16; // modulo 2^16 |
173 | results[i][mcu_y * width + mcu_x] = result << scan.point_transform; |
174 | } |
175 | } |
176 | } |
177 | } |
178 | |
179 | let mut marker = huffman.take_marker(&mut self.reader)?; |
180 | while let Some(Marker::RST(_)) = marker { |
181 | marker = self.read_marker().ok(); |
182 | } |
183 | Ok((marker, results)) |
184 | } |
185 | } |
186 | |
187 | /// H.1.2.1 |
188 | #[allow (clippy::too_many_arguments)] |
189 | fn predict( |
190 | ra: i32, |
191 | rb: i32, |
192 | rc: i32, |
193 | predictor: Predictor, |
194 | point_transform: u8, |
195 | input_precision: u8, |
196 | ix: usize, |
197 | iy: usize, |
198 | restart: bool, |
199 | ) -> i32 { |
200 | if (ix == 0 && iy == 0) || restart { |
201 | // start of first line or restart |
202 | if input_precision > 1 + point_transform { |
203 | 1 << (input_precision - point_transform - 1) |
204 | } else { |
205 | 0 |
206 | } |
207 | } else if iy == 0 { |
208 | // rest of first line |
209 | ra |
210 | } else if ix == 0 { |
211 | // start of other line |
212 | rb |
213 | } else { |
214 | // use predictor Table H.1 |
215 | match predictor { |
216 | Predictor::NoPrediction => 0, |
217 | Predictor::Ra => ra, |
218 | Predictor::Rb => rb, |
219 | Predictor::Rc => rc, |
220 | Predictor::RaRbRc1 => ra + rb - rc, |
221 | Predictor::RaRbRc2 => ra + ((rb - rc) >> 1), |
222 | Predictor::RaRbRc3 => rb + ((ra - rc) >> 1), |
223 | Predictor::RaRb => (ra + rb) / 2, |
224 | } |
225 | } |
226 | } |
227 | |
228 | pub fn compute_image_lossless(frame: &FrameInfo, mut data: Vec<Vec<u16>>) -> Result<Vec<u8>> { |
229 | if data.is_empty() || data.iter().any(Vec::is_empty) { |
230 | return Err(Error::Format("not all components have data" .to_owned())); |
231 | } |
232 | let output_size: Dimensions = frame.output_size; |
233 | let components: &Vec = &frame.components; |
234 | let ncomp: usize = components.len(); |
235 | |
236 | if ncomp == 1 { |
237 | let decoded: Vec = convert_to_u8(frame, data:data.remove(index:0)); |
238 | Ok(decoded) |
239 | } else { |
240 | let mut decoded: Vec<u16> = |
241 | vec![0u16; ncomp * output_size.width as usize * output_size.height as usize]; |
242 | for (x: usize, chunk: &mut [u16]) in decoded.chunks_mut(chunk_size:ncomp).enumerate() { |
243 | for (i: usize, (component_data: &Vec, _)) in data.iter().zip(components.iter()).enumerate() { |
244 | chunk[i] = component_data[x]; |
245 | } |
246 | } |
247 | let decoded: Vec = convert_to_u8(frame, data:decoded); |
248 | Ok(decoded) |
249 | } |
250 | } |
251 | |
252 | fn convert_to_u8(frame: &FrameInfo, data: Vec<u16>) -> Vec<u8> { |
253 | if frame.precision == 8 { |
254 | data.iter().map(|x: &u16| *x as u8).collect() |
255 | } else { |
256 | // we output native endian, which is the standard for image-rs |
257 | let ne_bytes: Vec<_> = data.iter().map(|x: &u16| x.to_ne_bytes()).collect(); |
258 | ne_bytes.concat() |
259 | } |
260 | } |
261 | |