jpeg_decoder/decoder/
lossless.rs

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 = frame.output_size;
233    let components = &frame.components;
234    let ncomp = components.len();
235
236    if ncomp == 1 {
237        let decoded = convert_to_u8(frame, data.remove(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, chunk) in decoded.chunks_mut(ncomp).enumerate() {
243            for (i, (component_data, _)) in data.iter().zip(components.iter()).enumerate() {
244                chunk[i] = component_data[x];
245            }
246        }
247        let decoded = convert_to_u8(frame, 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| *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| x.to_ne_bytes()).collect();
258        ne_bytes.concat()
259    }
260}