1use crate::decoder::{Decoder, MAX_COMPONENTS};
2use crate::error::{Error, Result};
3use crate::huffman::HuffmanDecoder;
4use crate::marker::Marker;
5use crate::parser::Predictor;
6use crate::parser::{Component, FrameInfo, ScanInfo};
7use std::io::Read;
8
9impl<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)]
189fn 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
228pub 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
252fn 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