Coverage Report

Created: 2026-01-17 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zune-jpeg-0.4.21/src/mcu_prog.rs
Line
Count
Source
1
/*
2
 * Copyright (c) 2023.
3
 *
4
 * This software is free software;
5
 *
6
 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7
 */
8
9
//!Routines for progressive decoding
10
/*
11
This file is needlessly complicated,
12
13
It is that way to ensure we don't burn memory anyhow
14
15
Memory is a scarce resource in some environments, I would like this to be viable
16
in such environments
17
18
Half of the complexity comes from the jpeg spec, because progressive decoding,
19
is one hell of a ride.
20
21
*/
22
use alloc::string::ToString;
23
use alloc::vec::Vec;
24
use alloc::{format, vec};
25
use core::cmp::min;
26
use zune_core::bytestream::{ZByteReader, ZReaderTrait};
27
use zune_core::colorspace::ColorSpace;
28
use zune_core::log::{debug, error, warn};
29
30
use crate::bitstream::BitStream;
31
use crate::components::{ComponentID, SampleRatios};
32
use crate::decoder::{JpegDecoder, MAX_COMPONENTS};
33
use crate::errors::DecodeErrors;
34
use crate::headers::{parse_sos};
35
use crate::marker::Marker;
36
use crate::mcu::DCT_BLOCK;
37
use crate::misc::{calculate_padded_width, setup_component_params};
38
39
impl<T: ZReaderTrait> JpegDecoder<T> {
40
    /// Decode a progressive image
41
    ///
42
    /// This routine decodes a progressive image, stopping if it finds any error.
43
    #[allow(
44
        clippy::needless_range_loop,
45
        clippy::cast_sign_loss,
46
        clippy::redundant_else,
47
        clippy::too_many_lines
48
    )]
49
    #[inline(never)]
50
3.74k
    pub(crate) fn decode_mcu_ycbcr_progressive(
51
3.74k
        &mut self, pixels: &mut [u8],
52
3.74k
    ) -> Result<(), DecodeErrors> {
53
3.74k
        setup_component_params(self)?;
54
55
        let mut mcu_height;
56
57
        // memory location for decoded pixels for components
58
3.73k
        let mut block: [Vec<i16>; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]];
59
        let mut mcu_width;
60
61
3.73k
        let mut seen_scans = 1;
62
63
3.73k
        if self.input_colorspace == ColorSpace::Luma && self.is_interleaved {
64
17
            warn!("Grayscale image with down-sampled component, resetting component details");
65
17
            self.reset_params();
66
3.72k
        }
67
68
3.73k
        if self.is_interleaved {
69
            // this helps us catch component errors.
70
0
            self.set_upsampling()?;
71
3.73k
        }
72
3.73k
        if self.is_interleaved {
73
0
            mcu_width = self.mcu_x;
74
0
            mcu_height = self.mcu_y;
75
3.73k
        } else {
76
3.73k
            mcu_width = (self.info.width as usize + 7) / 8;
77
3.73k
            mcu_height = (self.info.height as usize + 7) / 8;
78
3.73k
        }
79
3.73k
        if self.is_interleaved
80
0
            && self.input_colorspace.num_components() > 1
81
0
            && self.options.jpeg_get_out_colorspace().num_components() == 1
82
0
            && (self.sub_sample_ratio == SampleRatios::V
83
0
                || self.sub_sample_ratio == SampleRatios::HV)
84
0
        {
85
0
            // For a specific set of images, e.g interleaved,
86
0
            // when converting from YcbCr to grayscale, we need to
87
0
            // take into account mcu height since the MCU decoding needs to take
88
0
            // it into account for padding purposes and the post processor
89
0
            // parses two rows per mcu width.
90
0
            //
91
0
            // set coeff to be 2 to ensure that we increment two rows
92
0
            // for every mcu processed also
93
0
            mcu_height *= self.v_max;
94
0
            mcu_height /= self.h_max;
95
0
            self.coeff = 2;
96
3.73k
        }
97
98
3.73k
        mcu_width *= 64;
99
100
101
3.73k
        for i in 0..self.input_colorspace.num_components() {
102
3.73k
            let comp = &self.components[i];
103
3.73k
            let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height;
104
3.73k
105
3.73k
            block[i] = vec![0; len];
106
3.73k
        }
107
108
3.73k
        let mut stream = BitStream::new_progressive(
109
3.73k
            self.succ_high,
110
3.73k
            self.succ_low,
111
3.73k
            self.spec_start,
112
3.73k
            self.spec_end
113
        );
114
115
        // there are multiple scans in the stream, this should resolve the first scan
116
3.73k
        self.parse_entropy_coded_data(&mut stream, &mut block)?;
117
118
        // extract marker
119
3.56k
        let mut marker = stream
120
3.56k
            .marker
121
3.56k
            .take()
122
3.56k
            .ok_or(DecodeErrors::FormatStatic("Marker missing where expected"))?;
123
124
        // if marker is EOI, we are done, otherwise continue scanning.
125
        //
126
        // In case we have a premature image, we print a warning or return
127
        // an error, depending on the strictness of the decoder, so there
128
        // is that logic to handle too
129
136k
        'eoi: while marker != Marker::EOI {
130
136k
            match marker {
131
                Marker::SOS => {
132
20.0k
                    parse_sos(self)?;
133
134
19.9k
                    stream.update_progressive_params(
135
19.9k
                        self.succ_high,
136
19.9k
                        self.succ_low,
137
19.9k
                        self.spec_start,
138
19.9k
                        self.spec_end
139
                    );
140
                    // after every SOS, marker, parse data for that scan.
141
19.9k
                    self.parse_entropy_coded_data(&mut stream, &mut block)?;
142
                    // extract marker, might either indicate end of image or we continue
143
                    // scanning(hence the continue statement to determine).
144
19.3k
                    match get_marker(&mut self.stream, &mut stream) {
145
18.1k
                        Ok(marker_n) => {
146
18.1k
                            marker = marker_n;
147
18.1k
                            seen_scans += 1;
148
18.1k
                            if seen_scans > self.options.jpeg_get_max_scans() {
149
14
                                return Err(DecodeErrors::Format(format!(
150
14
                                    "Too many scans, exceeded limit of {}",
151
14
                                    self.options.jpeg_get_max_scans()
152
14
                                )));
153
18.1k
                            }
154
155
18.1k
                            stream.reset();
156
18.1k
                            continue 'eoi;
157
                        }
158
1.22k
                        Err(msg) => {
159
1.22k
                            if self.options.get_strict_mode() {
160
1.22k
                                return Err(msg);
161
0
                            }
162
0
                            error!("{:?}", msg);
163
0
                            break 'eoi;
164
                        }
165
                    }
166
                }
167
3.33k
                Marker::RST(_n) => {
168
3.33k
                    self.handle_rst(&mut stream)?;
169
                }
170
                _ => {
171
113k
                    self.parse_marker_inner(marker)?;
172
                }
173
            }
174
175
116k
            match get_marker(&mut self.stream, &mut stream) {
176
115k
                Ok(marker_n) => {
177
115k
                    marker = marker_n;
178
115k
                }
179
598
                Err(e) => {
180
598
                    if self.options.get_strict_mode() {
181
598
                        return Err(e);
182
0
                    }
183
0
                    error!("{}", e);
184
                }
185
            }
186
        }
187
188
145
        self.finish_progressive_decoding(&block, mcu_width, pixels)
189
3.74k
    }
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Line
Count
Source
50
3.74k
    pub(crate) fn decode_mcu_ycbcr_progressive(
51
3.74k
        &mut self, pixels: &mut [u8],
52
3.74k
    ) -> Result<(), DecodeErrors> {
53
3.74k
        setup_component_params(self)?;
54
55
        let mut mcu_height;
56
57
        // memory location for decoded pixels for components
58
3.73k
        let mut block: [Vec<i16>; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]];
59
        let mut mcu_width;
60
61
3.73k
        let mut seen_scans = 1;
62
63
3.73k
        if self.input_colorspace == ColorSpace::Luma && self.is_interleaved {
64
17
            warn!("Grayscale image with down-sampled component, resetting component details");
65
17
            self.reset_params();
66
3.72k
        }
67
68
3.73k
        if self.is_interleaved {
69
            // this helps us catch component errors.
70
0
            self.set_upsampling()?;
71
3.73k
        }
72
3.73k
        if self.is_interleaved {
73
0
            mcu_width = self.mcu_x;
74
0
            mcu_height = self.mcu_y;
75
3.73k
        } else {
76
3.73k
            mcu_width = (self.info.width as usize + 7) / 8;
77
3.73k
            mcu_height = (self.info.height as usize + 7) / 8;
78
3.73k
        }
79
3.73k
        if self.is_interleaved
80
0
            && self.input_colorspace.num_components() > 1
81
0
            && self.options.jpeg_get_out_colorspace().num_components() == 1
82
0
            && (self.sub_sample_ratio == SampleRatios::V
83
0
                || self.sub_sample_ratio == SampleRatios::HV)
84
0
        {
85
0
            // For a specific set of images, e.g interleaved,
86
0
            // when converting from YcbCr to grayscale, we need to
87
0
            // take into account mcu height since the MCU decoding needs to take
88
0
            // it into account for padding purposes and the post processor
89
0
            // parses two rows per mcu width.
90
0
            //
91
0
            // set coeff to be 2 to ensure that we increment two rows
92
0
            // for every mcu processed also
93
0
            mcu_height *= self.v_max;
94
0
            mcu_height /= self.h_max;
95
0
            self.coeff = 2;
96
3.73k
        }
97
98
3.73k
        mcu_width *= 64;
99
100
101
3.73k
        for i in 0..self.input_colorspace.num_components() {
102
3.73k
            let comp = &self.components[i];
103
3.73k
            let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height;
104
3.73k
105
3.73k
            block[i] = vec![0; len];
106
3.73k
        }
107
108
3.73k
        let mut stream = BitStream::new_progressive(
109
3.73k
            self.succ_high,
110
3.73k
            self.succ_low,
111
3.73k
            self.spec_start,
112
3.73k
            self.spec_end
113
        );
114
115
        // there are multiple scans in the stream, this should resolve the first scan
116
3.73k
        self.parse_entropy_coded_data(&mut stream, &mut block)?;
117
118
        // extract marker
119
3.56k
        let mut marker = stream
120
3.56k
            .marker
121
3.56k
            .take()
122
3.56k
            .ok_or(DecodeErrors::FormatStatic("Marker missing where expected"))?;
123
124
        // if marker is EOI, we are done, otherwise continue scanning.
125
        //
126
        // In case we have a premature image, we print a warning or return
127
        // an error, depending on the strictness of the decoder, so there
128
        // is that logic to handle too
129
136k
        'eoi: while marker != Marker::EOI {
130
136k
            match marker {
131
                Marker::SOS => {
132
20.0k
                    parse_sos(self)?;
133
134
19.9k
                    stream.update_progressive_params(
135
19.9k
                        self.succ_high,
136
19.9k
                        self.succ_low,
137
19.9k
                        self.spec_start,
138
19.9k
                        self.spec_end
139
                    );
140
                    // after every SOS, marker, parse data for that scan.
141
19.9k
                    self.parse_entropy_coded_data(&mut stream, &mut block)?;
142
                    // extract marker, might either indicate end of image or we continue
143
                    // scanning(hence the continue statement to determine).
144
19.3k
                    match get_marker(&mut self.stream, &mut stream) {
145
18.1k
                        Ok(marker_n) => {
146
18.1k
                            marker = marker_n;
147
18.1k
                            seen_scans += 1;
148
18.1k
                            if seen_scans > self.options.jpeg_get_max_scans() {
149
14
                                return Err(DecodeErrors::Format(format!(
150
14
                                    "Too many scans, exceeded limit of {}",
151
14
                                    self.options.jpeg_get_max_scans()
152
14
                                )));
153
18.1k
                            }
154
155
18.1k
                            stream.reset();
156
18.1k
                            continue 'eoi;
157
                        }
158
1.22k
                        Err(msg) => {
159
1.22k
                            if self.options.get_strict_mode() {
160
1.22k
                                return Err(msg);
161
0
                            }
162
0
                            error!("{:?}", msg);
163
0
                            break 'eoi;
164
                        }
165
                    }
166
                }
167
3.33k
                Marker::RST(_n) => {
168
3.33k
                    self.handle_rst(&mut stream)?;
169
                }
170
                _ => {
171
113k
                    self.parse_marker_inner(marker)?;
172
                }
173
            }
174
175
116k
            match get_marker(&mut self.stream, &mut stream) {
176
115k
                Ok(marker_n) => {
177
115k
                    marker = marker_n;
178
115k
                }
179
598
                Err(e) => {
180
598
                    if self.options.get_strict_mode() {
181
598
                        return Err(e);
182
0
                    }
183
0
                    error!("{}", e);
184
                }
185
            }
186
        }
187
188
145
        self.finish_progressive_decoding(&block, mcu_width, pixels)
189
3.74k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::decode_mcu_ycbcr_progressive
190
191
    /// Reset progressive parameters
192
23.6k
    fn reset_prog_params(&mut self, stream: &mut BitStream) {
193
23.6k
        stream.reset();
194
23.6k
        self.components.iter_mut().for_each(|x| x.dc_pred = 0);
195
196
        // Also reset JPEG restart intervals
197
23.6k
        self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX };
198
23.6k
    }
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Line
Count
Source
192
23.6k
    fn reset_prog_params(&mut self, stream: &mut BitStream) {
193
23.6k
        stream.reset();
194
23.6k
        self.components.iter_mut().for_each(|x| x.dc_pred = 0);
195
196
        // Also reset JPEG restart intervals
197
23.6k
        self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX };
198
23.6k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::reset_prog_params
199
200
    #[allow(clippy::too_many_lines, clippy::cast_sign_loss)]
201
23.6k
    fn parse_entropy_coded_data(
202
23.6k
        &mut self, stream: &mut BitStream, buffer: &mut [Vec<i16>; MAX_COMPONENTS]
203
23.6k
    ) -> Result<(), DecodeErrors> {
204
23.6k
        self.reset_prog_params(stream);
205
206
23.6k
        if usize::from(self.num_scans) > self.input_colorspace.num_components() {
207
0
            return Err(DecodeErrors::Format(format!(
208
0
                "Number of scans {} cannot be greater than number of components, {}",
209
0
                self.num_scans,
210
0
                self.input_colorspace.num_components()
211
0
            )));
212
23.6k
        }
213
23.6k
        if self.num_scans == 1 {
214
            // Safety checks
215
23.6k
            if self.spec_end != 0 && self.spec_start == 0 {
216
6
                return Err(DecodeErrors::FormatStatic(
217
6
                    "Can't merge DC and AC corrupt jpeg"
218
6
                ));
219
23.6k
            }
220
            // non interleaved data, process one block at a time in trivial scanline order
221
222
23.6k
            let k = self.z_order[0];
223
224
23.6k
            if k >= self.components.len() {
225
0
                return Err(DecodeErrors::Format(format!(
226
0
                    "Cannot find component {k}, corrupt image"
227
0
                )));
228
23.6k
            }
229
230
            let (mcu_width, mcu_height);
231
232
23.6k
            if self.components[k].component_id == ComponentID::Y
233
23.6k
                && (self.components[k].vertical_sample != 1
234
23.6k
                    || self.components[k].horizontal_sample != 1)
235
23.6k
                || !self.is_interleaved
236
23.6k
            {
237
23.6k
                // For Y channel  or non interleaved scans ,
238
23.6k
                // mcu's is the image dimensions divided by 8
239
23.6k
                mcu_width = ((self.info.width + 7) / 8) as usize;
240
23.6k
                mcu_height = ((self.info.height + 7) / 8) as usize;
241
23.6k
            } else {
242
0
                // For other channels, in an interleaved mcu, number of MCU's
243
0
                // are determined by some weird maths done in headers.rs->parse_sos()
244
0
                mcu_width = self.mcu_x;
245
0
                mcu_height = self.mcu_y;
246
0
            }
247
248
1.28M
            for i in 0..mcu_height {
249
204M
                for j in 0..mcu_width {
250
204M
                    if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 {
251
224k
                        // handle EOB runs here.
252
224k
                        stream.eob_run -= 1;
253
224k
                    } else {
254
203M
                        let start = 64 * (j + i * (self.components[k].width_stride / 8));
255
256
203M
                        let data: &mut [i16; 64] = buffer
257
203M
                            .get_mut(k)
258
203M
                            .unwrap()
259
203M
                            .get_mut(start..start + 64)
260
203M
                            .unwrap()
261
203M
                            .try_into()
262
203M
                            .unwrap();
263
264
203M
                        if self.spec_start == 0 {
265
133M
                            let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1);
266
133M
                            let dc_table = self
267
133M
                                .dc_huffman_tables
268
133M
                                .get(pos)
269
133M
                                .ok_or(DecodeErrors::FormatStatic(
270
133M
                                    "No huffman table for DC component"
271
133M
                                ))?
272
133M
                                .as_ref()
273
133M
                                .ok_or(DecodeErrors::FormatStatic(
274
133M
                                    "Huffman table at index  {} not initialized"
275
133M
                                ))?;
276
277
133M
                            let dc_pred = &mut self.components[k].dc_pred;
278
279
133M
                            if self.succ_high == 0 {
280
                                // first scan for this mcu
281
49.3M
                                stream.decode_prog_dc_first(
282
49.3M
                                    &mut self.stream,
283
49.3M
                                    dc_table,
284
49.3M
                                    &mut data[0],
285
49.3M
                                    dc_pred
286
124
                                )?;
287
                            } else {
288
                                // refining scans for this MCU
289
83.7M
                                stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?;
290
                            }
291
                        } else {
292
70.7M
                            let pos = self.components[k].ac_huff_table;
293
70.7M
                            let ac_table = self
294
70.7M
                                .ac_huffman_tables
295
70.7M
                                .get(pos)
296
70.7M
                                .ok_or_else(|| {
297
6
                                    DecodeErrors::Format(format!(
298
6
                                        "No huffman table for component:{pos}"
299
6
                                    ))
300
6
                                })?
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Line
Count
Source
296
6
                                .ok_or_else(|| {
297
6
                                    DecodeErrors::Format(format!(
298
6
                                        "No huffman table for component:{pos}"
299
6
                                    ))
300
6
                                })?
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data::{closure#0}
301
70.7M
                                .as_ref()
302
70.7M
                                .ok_or_else(|| {
303
4
                                    DecodeErrors::Format(format!(
304
4
                                        "Huffman table at index  {pos} not initialized"
305
4
                                    ))
306
4
                                })?;
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Line
Count
Source
302
4
                                .ok_or_else(|| {
303
4
                                    DecodeErrors::Format(format!(
304
4
                                        "Huffman table at index  {pos} not initialized"
305
4
                                    ))
306
4
                                })?;
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data::{closure#1}
307
308
70.7M
                            if self.succ_high == 0 {
309
36.2M
                                debug_assert!(stream.eob_run == 0, "EOB run is not zero");
310
311
36.2M
                                stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?;
312
                            } else {
313
                                // refinement scan
314
34.4M
                                stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?;
315
                            }
316
                        }
317
                    }
318
319
                    // + EOB and investigate effect.
320
204M
                    self.todo -= 1;
321
322
204M
                    self.handle_rst_main(stream)?;
323
                }
324
            }
325
        } else {
326
0
            if self.spec_end != 0 {
327
0
                return Err(DecodeErrors::HuffmanDecode(
328
0
                    "Can't merge dc and AC corrupt jpeg".to_string()
329
0
                ));
330
0
            }
331
            // process scan n elements in order
332
333
            // Do the error checking with allocs here.
334
            // Make the one in the inner loop free of allocations.
335
0
            for k in 0..self.num_scans {
336
0
                let n = self.z_order[k as usize];
337
338
0
                if n >= self.components.len() {
339
0
                    return Err(DecodeErrors::Format(format!(
340
0
                        "Cannot find component {n}, corrupt image"
341
0
                    )));
342
0
                }
343
344
0
                let component = &mut self.components[n];
345
0
                let _ = self
346
0
                    .dc_huffman_tables
347
0
                    .get(component.dc_huff_table)
348
0
                    .ok_or_else(|| {
349
0
                        DecodeErrors::Format(format!(
350
0
                            "No huffman table for component:{}",
351
0
                            component.dc_huff_table
352
0
                        ))
353
0
                    })?
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data::{closure#2}
354
0
                    .as_ref()
355
0
                    .ok_or_else(|| {
356
0
                        DecodeErrors::Format(format!(
357
0
                            "Huffman table at index  {} not initialized",
358
0
                            component.dc_huff_table
359
0
                        ))
360
0
                    })?;
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data::{closure#3}
361
            }
362
            // Interleaved scan
363
364
            // Components shall not be interleaved in progressive mode, except for
365
            // the DC coefficients in the first scan for each component of a progressive frame.
366
0
            for i in 0..self.mcu_y {
367
0
                for j in 0..self.mcu_x {
368
                    // process scan n elements in order
369
0
                    for k in 0..self.num_scans {
370
0
                        let n = self.z_order[k as usize];
371
0
                        let component = &mut self.components[n];
372
0
                        let huff_table = self
373
0
                            .dc_huffman_tables
374
0
                            .get(component.dc_huff_table)
375
0
                            .ok_or(DecodeErrors::FormatStatic("No huffman table for component"))?
376
0
                            .as_ref()
377
0
                            .ok_or(DecodeErrors::FormatStatic(
378
0
                                "Huffman table at index not initialized"
379
0
                            ))?;
380
381
0
                        for v_samp in 0..component.vertical_sample {
382
0
                            for h_samp in 0..component.horizontal_sample {
383
0
                                let x2 = j * component.horizontal_sample + h_samp;
384
0
                                let y2 = i * component.vertical_sample + v_samp;
385
0
                                let position = 64 * (x2 + y2 * component.width_stride / 8);
386
0
                                let buf_n = &mut buffer[n];
387
388
0
                                let Some(data) = &mut buf_n.get_mut(position) else {
389
                                    // TODO: (CAE), this is another weird sub-sampling bug, so on fix
390
                                    // remove this
391
0
                                    return Err(DecodeErrors::FormatStatic("Invalid image"));
392
                                };
393
394
0
                                if self.succ_high == 0 {
395
0
                                    stream.decode_prog_dc_first(
396
0
                                        &mut self.stream,
397
0
                                        huff_table,
398
0
                                        data,
399
0
                                        &mut component.dc_pred
400
0
                                    )?;
401
                                } else {
402
0
                                    stream.decode_prog_dc_refine(&mut self.stream, data)?;
403
                                }
404
                            }
405
                        }
406
                    }
407
                    // We want wrapping subtraction here because it means
408
                    // we get a higher number in the case this underflows
409
0
                    self.todo -= 1;
410
                    // after every scan that's a mcu, count down restart markers.
411
0
                    self.handle_rst_main(stream)?;
412
                }
413
            }
414
        }
415
22.9k
        return Ok(());
416
23.6k
    }
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Line
Count
Source
201
23.6k
    fn parse_entropy_coded_data(
202
23.6k
        &mut self, stream: &mut BitStream, buffer: &mut [Vec<i16>; MAX_COMPONENTS]
203
23.6k
    ) -> Result<(), DecodeErrors> {
204
23.6k
        self.reset_prog_params(stream);
205
206
23.6k
        if usize::from(self.num_scans) > self.input_colorspace.num_components() {
207
0
            return Err(DecodeErrors::Format(format!(
208
0
                "Number of scans {} cannot be greater than number of components, {}",
209
0
                self.num_scans,
210
0
                self.input_colorspace.num_components()
211
0
            )));
212
23.6k
        }
213
23.6k
        if self.num_scans == 1 {
214
            // Safety checks
215
23.6k
            if self.spec_end != 0 && self.spec_start == 0 {
216
6
                return Err(DecodeErrors::FormatStatic(
217
6
                    "Can't merge DC and AC corrupt jpeg"
218
6
                ));
219
23.6k
            }
220
            // non interleaved data, process one block at a time in trivial scanline order
221
222
23.6k
            let k = self.z_order[0];
223
224
23.6k
            if k >= self.components.len() {
225
0
                return Err(DecodeErrors::Format(format!(
226
0
                    "Cannot find component {k}, corrupt image"
227
0
                )));
228
23.6k
            }
229
230
            let (mcu_width, mcu_height);
231
232
23.6k
            if self.components[k].component_id == ComponentID::Y
233
23.6k
                && (self.components[k].vertical_sample != 1
234
23.6k
                    || self.components[k].horizontal_sample != 1)
235
23.6k
                || !self.is_interleaved
236
23.6k
            {
237
23.6k
                // For Y channel  or non interleaved scans ,
238
23.6k
                // mcu's is the image dimensions divided by 8
239
23.6k
                mcu_width = ((self.info.width + 7) / 8) as usize;
240
23.6k
                mcu_height = ((self.info.height + 7) / 8) as usize;
241
23.6k
            } else {
242
0
                // For other channels, in an interleaved mcu, number of MCU's
243
0
                // are determined by some weird maths done in headers.rs->parse_sos()
244
0
                mcu_width = self.mcu_x;
245
0
                mcu_height = self.mcu_y;
246
0
            }
247
248
1.28M
            for i in 0..mcu_height {
249
204M
                for j in 0..mcu_width {
250
204M
                    if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 {
251
224k
                        // handle EOB runs here.
252
224k
                        stream.eob_run -= 1;
253
224k
                    } else {
254
203M
                        let start = 64 * (j + i * (self.components[k].width_stride / 8));
255
256
203M
                        let data: &mut [i16; 64] = buffer
257
203M
                            .get_mut(k)
258
203M
                            .unwrap()
259
203M
                            .get_mut(start..start + 64)
260
203M
                            .unwrap()
261
203M
                            .try_into()
262
203M
                            .unwrap();
263
264
203M
                        if self.spec_start == 0 {
265
133M
                            let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1);
266
133M
                            let dc_table = self
267
133M
                                .dc_huffman_tables
268
133M
                                .get(pos)
269
133M
                                .ok_or(DecodeErrors::FormatStatic(
270
133M
                                    "No huffman table for DC component"
271
133M
                                ))?
272
133M
                                .as_ref()
273
133M
                                .ok_or(DecodeErrors::FormatStatic(
274
133M
                                    "Huffman table at index  {} not initialized"
275
133M
                                ))?;
276
277
133M
                            let dc_pred = &mut self.components[k].dc_pred;
278
279
133M
                            if self.succ_high == 0 {
280
                                // first scan for this mcu
281
49.3M
                                stream.decode_prog_dc_first(
282
49.3M
                                    &mut self.stream,
283
49.3M
                                    dc_table,
284
49.3M
                                    &mut data[0],
285
49.3M
                                    dc_pred
286
124
                                )?;
287
                            } else {
288
                                // refining scans for this MCU
289
83.7M
                                stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?;
290
                            }
291
                        } else {
292
70.7M
                            let pos = self.components[k].ac_huff_table;
293
70.7M
                            let ac_table = self
294
70.7M
                                .ac_huffman_tables
295
70.7M
                                .get(pos)
296
70.7M
                                .ok_or_else(|| {
297
                                    DecodeErrors::Format(format!(
298
                                        "No huffman table for component:{pos}"
299
                                    ))
300
6
                                })?
301
70.7M
                                .as_ref()
302
70.7M
                                .ok_or_else(|| {
303
                                    DecodeErrors::Format(format!(
304
                                        "Huffman table at index  {pos} not initialized"
305
                                    ))
306
4
                                })?;
307
308
70.7M
                            if self.succ_high == 0 {
309
36.2M
                                debug_assert!(stream.eob_run == 0, "EOB run is not zero");
310
311
36.2M
                                stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?;
312
                            } else {
313
                                // refinement scan
314
34.4M
                                stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?;
315
                            }
316
                        }
317
                    }
318
319
                    // + EOB and investigate effect.
320
204M
                    self.todo -= 1;
321
322
204M
                    self.handle_rst_main(stream)?;
323
                }
324
            }
325
        } else {
326
0
            if self.spec_end != 0 {
327
0
                return Err(DecodeErrors::HuffmanDecode(
328
0
                    "Can't merge dc and AC corrupt jpeg".to_string()
329
0
                ));
330
0
            }
331
            // process scan n elements in order
332
333
            // Do the error checking with allocs here.
334
            // Make the one in the inner loop free of allocations.
335
0
            for k in 0..self.num_scans {
336
0
                let n = self.z_order[k as usize];
337
338
0
                if n >= self.components.len() {
339
0
                    return Err(DecodeErrors::Format(format!(
340
0
                        "Cannot find component {n}, corrupt image"
341
0
                    )));
342
0
                }
343
344
0
                let component = &mut self.components[n];
345
0
                let _ = self
346
0
                    .dc_huffman_tables
347
0
                    .get(component.dc_huff_table)
348
0
                    .ok_or_else(|| {
349
                        DecodeErrors::Format(format!(
350
                            "No huffman table for component:{}",
351
                            component.dc_huff_table
352
                        ))
353
0
                    })?
354
0
                    .as_ref()
355
0
                    .ok_or_else(|| {
356
                        DecodeErrors::Format(format!(
357
                            "Huffman table at index  {} not initialized",
358
                            component.dc_huff_table
359
                        ))
360
0
                    })?;
361
            }
362
            // Interleaved scan
363
364
            // Components shall not be interleaved in progressive mode, except for
365
            // the DC coefficients in the first scan for each component of a progressive frame.
366
0
            for i in 0..self.mcu_y {
367
0
                for j in 0..self.mcu_x {
368
                    // process scan n elements in order
369
0
                    for k in 0..self.num_scans {
370
0
                        let n = self.z_order[k as usize];
371
0
                        let component = &mut self.components[n];
372
0
                        let huff_table = self
373
0
                            .dc_huffman_tables
374
0
                            .get(component.dc_huff_table)
375
0
                            .ok_or(DecodeErrors::FormatStatic("No huffman table for component"))?
376
0
                            .as_ref()
377
0
                            .ok_or(DecodeErrors::FormatStatic(
378
0
                                "Huffman table at index not initialized"
379
0
                            ))?;
380
381
0
                        for v_samp in 0..component.vertical_sample {
382
0
                            for h_samp in 0..component.horizontal_sample {
383
0
                                let x2 = j * component.horizontal_sample + h_samp;
384
0
                                let y2 = i * component.vertical_sample + v_samp;
385
0
                                let position = 64 * (x2 + y2 * component.width_stride / 8);
386
0
                                let buf_n = &mut buffer[n];
387
388
0
                                let Some(data) = &mut buf_n.get_mut(position) else {
389
                                    // TODO: (CAE), this is another weird sub-sampling bug, so on fix
390
                                    // remove this
391
0
                                    return Err(DecodeErrors::FormatStatic("Invalid image"));
392
                                };
393
394
0
                                if self.succ_high == 0 {
395
0
                                    stream.decode_prog_dc_first(
396
0
                                        &mut self.stream,
397
0
                                        huff_table,
398
0
                                        data,
399
0
                                        &mut component.dc_pred
400
0
                                    )?;
401
                                } else {
402
0
                                    stream.decode_prog_dc_refine(&mut self.stream, data)?;
403
                                }
404
                            }
405
                        }
406
                    }
407
                    // We want wrapping subtraction here because it means
408
                    // we get a higher number in the case this underflows
409
0
                    self.todo -= 1;
410
                    // after every scan that's a mcu, count down restart markers.
411
0
                    self.handle_rst_main(stream)?;
412
                }
413
            }
414
        }
415
22.9k
        return Ok(());
416
23.6k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data
417
418
204M
    pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> {
419
204M
        if self.todo == 0 {
420
454k
            stream.refill(&mut self.stream)?;
421
204M
        }
422
423
204M
        if self.todo == 0
424
454k
            && self.restart_interval != 0
425
454k
            && stream.marker.is_none()
426
325k
            && !stream.seen_eoi
427
        {
428
            // if no marker and we are to reset RST, look for the marker, this matches
429
            // libjpeg-turbo behaviour and allows us to decode images in
430
            // https://github.com/etemesi254/zune-image/issues/261
431
5.82k
            let _start = self.stream.get_position();
432
            // skip bytes until we find marker
433
5.82k
            let marker = get_marker(&mut self.stream, stream)?;
434
5.70k
            let _end = self.stream.get_position();
435
5.70k
            stream.marker = Some(marker);
436
            // NB some warnings may be false positives.
437
5.70k
            warn!(
438
                "{} Extraneous bytes before marker {:?}",
439
                _end - _start,
440
                marker
441
            );
442
204M
        }
443
204M
        if self.todo == 0 {
444
454k
            self.handle_rst(stream)?
445
204M
        }
446
204M
        Ok(())
447
204M
    }
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Line
Count
Source
418
204M
    pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> {
419
204M
        if self.todo == 0 {
420
454k
            stream.refill(&mut self.stream)?;
421
204M
        }
422
423
204M
        if self.todo == 0
424
454k
            && self.restart_interval != 0
425
454k
            && stream.marker.is_none()
426
325k
            && !stream.seen_eoi
427
        {
428
            // if no marker and we are to reset RST, look for the marker, this matches
429
            // libjpeg-turbo behaviour and allows us to decode images in
430
            // https://github.com/etemesi254/zune-image/issues/261
431
5.82k
            let _start = self.stream.get_position();
432
            // skip bytes until we find marker
433
5.82k
            let marker = get_marker(&mut self.stream, stream)?;
434
5.70k
            let _end = self.stream.get_position();
435
5.70k
            stream.marker = Some(marker);
436
            // NB some warnings may be false positives.
437
5.70k
            warn!(
438
                "{} Extraneous bytes before marker {:?}",
439
                _end - _start,
440
                marker
441
            );
442
204M
        }
443
204M
        if self.todo == 0 {
444
454k
            self.handle_rst(stream)?
445
204M
        }
446
204M
        Ok(())
447
204M
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::handle_rst_main
448
    #[allow(clippy::too_many_lines)]
449
    #[allow(clippy::needless_range_loop, clippy::cast_sign_loss)]
450
145
    fn finish_progressive_decoding(
451
145
        &mut self, block: &[Vec<i16>; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8]
452
145
    ) -> Result<(), DecodeErrors> {
453
        // This function is complicated because we need to replicate
454
        // the function in mcu.rs
455
        //
456
        // The advantage is that we do very little allocation and very lot
457
        // channel reusing.
458
        // The trick is to notice that we repeat the same procedure per MCU
459
        // width.
460
        //
461
        // So we can set it up that we only allocate temporary storage large enough
462
        // to store a single mcu width, then reuse it per invocation.
463
        //
464
        // This is advantageous to us.
465
        //
466
        // Remember we need to have the whole MCU buffer so we store 3 unprocessed
467
        // channels in memory, and then we allocate the whole output buffer in memory, both of
468
        // which are huge.
469
        //
470
        //
471
472
145
        let mcu_height = if self.is_interleaved {
473
0
            self.mcu_y
474
        } else {
475
            // For non-interleaved images( (1*1) subsampling)
476
            // number of MCU's are the widths (+7 to account for paddings) divided by 8.
477
145
            ((self.info.height + 7) / 8) as usize
478
        };
479
480
        // Size of our output image(width*height)
481
145
        let is_hv = usize::from(self.is_interleaved);
482
145
        let upsampler_scratch_size = is_hv * self.components[0].width_stride;
483
145
        let width = usize::from(self.info.width);
484
145
        let padded_width = calculate_padded_width(width, self.sub_sample_ratio);
485
486
        //let mut pixels = vec![0; capacity * out_colorspace_components];
487
145
        let mut upsampler_scratch_space = vec![0; upsampler_scratch_size];
488
145
        let mut tmp = [0_i32; DCT_BLOCK];
489
490
145
        for (pos, comp) in self.components.iter_mut().enumerate() {
491
            // Allocate only needed components.
492
            //
493
            // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed
494
            // components.
495
145
            if min(
496
145
                self.options.jpeg_get_out_colorspace().num_components() - 1,
497
145
                pos,
498
145
            ) == pos
499
0
                || self.input_colorspace == ColorSpace::YCCK
500
0
                || self.input_colorspace == ColorSpace::CMYK
501
145
            {
502
145
                // allocate enough space to hold a whole MCU width
503
145
                // this means we should take into account sampling ratios
504
145
                // `*8` is because each MCU spans 8 widths.
505
145
                let len = comp.width_stride * comp.vertical_sample * 8;
506
145
507
145
                comp.needed = true;
508
145
                comp.raw_coeff = vec![0; len];
509
145
            } else {
510
0
                comp.needed = false;
511
0
            }
512
        }
513
514
145
        let mut pixels_written = 0;
515
516
        // dequantize, idct and color convert.
517
11.3k
        for i in 0..mcu_height {
518
11.3k
            'component: for (position, component) in &mut self.components.iter_mut().enumerate() {
519
11.3k
                if !component.needed {
520
0
                    continue 'component;
521
11.3k
                }
522
11.3k
                let qt_table = &component.quantization_table;
523
524
                // step is the number of pixels this iteration wil be handling
525
                // Given by the number of mcu's height and the length of the component block
526
                // Since the component block contains the whole channel as raw pixels
527
                // we this evenly divides the pixels into MCU blocks
528
                //
529
                // For interleaved images, this gives us the exact pixels comprising a whole MCU
530
                // block
531
11.3k
                let step = block[position].len() / mcu_height;
532
                // where we will be reading our pixels from.
533
11.3k
                let start = i * step;
534
535
11.3k
                let slice = &block[position][start..start + step];
536
537
11.3k
                let temp_channel = &mut component.raw_coeff;
538
539
                // The next logical step is to iterate width wise.
540
                // To figure out how many pixels we iterate by we use effective pixels
541
                // Given to us by component.x
542
                // iterate per effective pixels.
543
11.3k
                let mcu_x = component.width_stride / 8;
544
545
                // iterate per every vertical sample.
546
11.3k
                for k in 0..component.vertical_sample {
547
6.02M
                    for j in 0..mcu_x {
548
                        // after writing a single stride, we need to skip 8 rows.
549
                        // This does the row calculation
550
6.02M
                        let width_stride = k * 8 * component.width_stride;
551
6.02M
                        let start = j * 64 + width_stride;
552
553
                        // See https://github.com/etemesi254/zune-image/issues/262 sample 3.
554
6.02M
                        let Some(qt_slice) = slice.get(start..start + 64) else {
555
0
                            return Err(DecodeErrors::FormatStatic("Invalid slice , would panic, invalid image"))
556
                        };
557
                        // dequantize
558
385M
                        for ((x, out), qt_val) in qt_slice
559
6.02M
                            .iter()
560
6.02M
                            .zip(tmp.iter_mut())
561
6.02M
                            .zip(qt_table.iter())
562
385M
                        {
563
385M
                            *out = i32::from(*x) * qt_val;
564
385M
                        }
565
                        // determine where to write.
566
6.02M
                        let sl = &mut temp_channel[component.idct_pos..];
567
568
6.02M
                        component.idct_pos += 8;
569
                        // tmp now contains a dequantized block so idct it
570
6.02M
                        (self.idct_func)(&mut tmp, sl, component.width_stride);
571
                    }
572
                    // after every write of 8, skip 7 since idct write stride wise 8 times.
573
                    //
574
                    // Remember each MCU is 8x8 block, so each idct will write 8 strides into
575
                    // sl
576
                    //
577
                    // and component.idct_pos is one stride long
578
11.3k
                    component.idct_pos += 7 * component.width_stride;
579
                }
580
11.3k
                component.idct_pos = 0;
581
            }
582
583
            // process that width up until it's impossible
584
11.3k
            self.post_process(
585
11.3k
                pixels,
586
11.3k
                i,
587
11.3k
                mcu_height,
588
11.3k
                width,
589
11.3k
                padded_width,
590
11.3k
                &mut pixels_written,
591
11.3k
                &mut upsampler_scratch_space
592
1
            )?;
593
        }
594
595
        debug!("Finished decoding image");
596
597
144
        return Ok(());
598
145
    }
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Line
Count
Source
450
145
    fn finish_progressive_decoding(
451
145
        &mut self, block: &[Vec<i16>; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8]
452
145
    ) -> Result<(), DecodeErrors> {
453
        // This function is complicated because we need to replicate
454
        // the function in mcu.rs
455
        //
456
        // The advantage is that we do very little allocation and very lot
457
        // channel reusing.
458
        // The trick is to notice that we repeat the same procedure per MCU
459
        // width.
460
        //
461
        // So we can set it up that we only allocate temporary storage large enough
462
        // to store a single mcu width, then reuse it per invocation.
463
        //
464
        // This is advantageous to us.
465
        //
466
        // Remember we need to have the whole MCU buffer so we store 3 unprocessed
467
        // channels in memory, and then we allocate the whole output buffer in memory, both of
468
        // which are huge.
469
        //
470
        //
471
472
145
        let mcu_height = if self.is_interleaved {
473
0
            self.mcu_y
474
        } else {
475
            // For non-interleaved images( (1*1) subsampling)
476
            // number of MCU's are the widths (+7 to account for paddings) divided by 8.
477
145
            ((self.info.height + 7) / 8) as usize
478
        };
479
480
        // Size of our output image(width*height)
481
145
        let is_hv = usize::from(self.is_interleaved);
482
145
        let upsampler_scratch_size = is_hv * self.components[0].width_stride;
483
145
        let width = usize::from(self.info.width);
484
145
        let padded_width = calculate_padded_width(width, self.sub_sample_ratio);
485
486
        //let mut pixels = vec![0; capacity * out_colorspace_components];
487
145
        let mut upsampler_scratch_space = vec![0; upsampler_scratch_size];
488
145
        let mut tmp = [0_i32; DCT_BLOCK];
489
490
145
        for (pos, comp) in self.components.iter_mut().enumerate() {
491
            // Allocate only needed components.
492
            //
493
            // For special colorspaces i.e YCCK and CMYK, just allocate all of the needed
494
            // components.
495
145
            if min(
496
145
                self.options.jpeg_get_out_colorspace().num_components() - 1,
497
145
                pos,
498
145
            ) == pos
499
0
                || self.input_colorspace == ColorSpace::YCCK
500
0
                || self.input_colorspace == ColorSpace::CMYK
501
145
            {
502
145
                // allocate enough space to hold a whole MCU width
503
145
                // this means we should take into account sampling ratios
504
145
                // `*8` is because each MCU spans 8 widths.
505
145
                let len = comp.width_stride * comp.vertical_sample * 8;
506
145
507
145
                comp.needed = true;
508
145
                comp.raw_coeff = vec![0; len];
509
145
            } else {
510
0
                comp.needed = false;
511
0
            }
512
        }
513
514
145
        let mut pixels_written = 0;
515
516
        // dequantize, idct and color convert.
517
11.3k
        for i in 0..mcu_height {
518
11.3k
            'component: for (position, component) in &mut self.components.iter_mut().enumerate() {
519
11.3k
                if !component.needed {
520
0
                    continue 'component;
521
11.3k
                }
522
11.3k
                let qt_table = &component.quantization_table;
523
524
                // step is the number of pixels this iteration wil be handling
525
                // Given by the number of mcu's height and the length of the component block
526
                // Since the component block contains the whole channel as raw pixels
527
                // we this evenly divides the pixels into MCU blocks
528
                //
529
                // For interleaved images, this gives us the exact pixels comprising a whole MCU
530
                // block
531
11.3k
                let step = block[position].len() / mcu_height;
532
                // where we will be reading our pixels from.
533
11.3k
                let start = i * step;
534
535
11.3k
                let slice = &block[position][start..start + step];
536
537
11.3k
                let temp_channel = &mut component.raw_coeff;
538
539
                // The next logical step is to iterate width wise.
540
                // To figure out how many pixels we iterate by we use effective pixels
541
                // Given to us by component.x
542
                // iterate per effective pixels.
543
11.3k
                let mcu_x = component.width_stride / 8;
544
545
                // iterate per every vertical sample.
546
11.3k
                for k in 0..component.vertical_sample {
547
6.02M
                    for j in 0..mcu_x {
548
                        // after writing a single stride, we need to skip 8 rows.
549
                        // This does the row calculation
550
6.02M
                        let width_stride = k * 8 * component.width_stride;
551
6.02M
                        let start = j * 64 + width_stride;
552
553
                        // See https://github.com/etemesi254/zune-image/issues/262 sample 3.
554
6.02M
                        let Some(qt_slice) = slice.get(start..start + 64) else {
555
0
                            return Err(DecodeErrors::FormatStatic("Invalid slice , would panic, invalid image"))
556
                        };
557
                        // dequantize
558
385M
                        for ((x, out), qt_val) in qt_slice
559
6.02M
                            .iter()
560
6.02M
                            .zip(tmp.iter_mut())
561
6.02M
                            .zip(qt_table.iter())
562
385M
                        {
563
385M
                            *out = i32::from(*x) * qt_val;
564
385M
                        }
565
                        // determine where to write.
566
6.02M
                        let sl = &mut temp_channel[component.idct_pos..];
567
568
6.02M
                        component.idct_pos += 8;
569
                        // tmp now contains a dequantized block so idct it
570
6.02M
                        (self.idct_func)(&mut tmp, sl, component.width_stride);
571
                    }
572
                    // after every write of 8, skip 7 since idct write stride wise 8 times.
573
                    //
574
                    // Remember each MCU is 8x8 block, so each idct will write 8 strides into
575
                    // sl
576
                    //
577
                    // and component.idct_pos is one stride long
578
11.3k
                    component.idct_pos += 7 * component.width_stride;
579
                }
580
11.3k
                component.idct_pos = 0;
581
            }
582
583
            // process that width up until it's impossible
584
11.3k
            self.post_process(
585
11.3k
                pixels,
586
11.3k
                i,
587
11.3k
                mcu_height,
588
11.3k
                width,
589
11.3k
                padded_width,
590
11.3k
                &mut pixels_written,
591
11.3k
                &mut upsampler_scratch_space
592
1
            )?;
593
        }
594
595
        debug!("Finished decoding image");
596
597
144
        return Ok(());
598
145
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::finish_progressive_decoding
599
38
    pub(crate) fn reset_params(&mut self) {
600
        /*
601
        Apparently, grayscale images which can be down sampled exists, which is weird in the sense
602
        that it has one component Y, which is not usually down sampled.
603
604
        This means some calculations will be wrong, so for that we explicitly reset params
605
        for such occurrences, warn and reset the image info to appear as if it were
606
        a non-sampled image to ensure decoding works
607
        */
608
38
        self.h_max = 1;
609
38
        self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma);
610
38
        self.v_max = 1;
611
38
        self.sub_sample_ratio = SampleRatios::None;
612
38
        self.is_interleaved = false;
613
38
        self.components[0].vertical_sample = 1;
614
38
        self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8;
615
38
        self.components[0].horizontal_sample = 1;
616
38
    }
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Line
Count
Source
599
38
    pub(crate) fn reset_params(&mut self) {
600
        /*
601
        Apparently, grayscale images which can be down sampled exists, which is weird in the sense
602
        that it has one component Y, which is not usually down sampled.
603
604
        This means some calculations will be wrong, so for that we explicitly reset params
605
        for such occurrences, warn and reset the image info to appear as if it were
606
        a non-sampled image to ensure decoding works
607
        */
608
38
        self.h_max = 1;
609
38
        self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma);
610
38
        self.v_max = 1;
611
38
        self.sub_sample_ratio = SampleRatios::None;
612
38
        self.is_interleaved = false;
613
38
        self.components[0].vertical_sample = 1;
614
38
        self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8;
615
38
        self.components[0].horizontal_sample = 1;
616
38
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::reset_params
617
}
618
619
///Get a marker from the bit-stream.
620
///
621
/// This reads until it gets a marker or end of file is encountered
622
141k
pub fn get_marker<T>(
623
141k
    reader: &mut ZByteReader<T>, stream: &mut BitStream
624
141k
) -> Result<Marker, DecodeErrors>
625
141k
where
626
141k
    T: ZReaderTrait
627
{
628
141k
    if let Some(marker) = stream.marker {
629
17.4k
        stream.marker = None;
630
17.4k
        return Ok(marker);
631
124k
    }
632
633
    // read until we get a marker
634
635
11.3M
    while !reader.eof() {
636
11.3M
        let marker = reader.get_u8_err()?;
637
638
11.3M
        if marker == 255 {
639
141k
            let mut r = reader.get_u8_err()?;
640
            // 0xFF 0XFF(some images may be like that)
641
258k
            while r == 0xFF {
642
116k
                r = reader.get_u8_err()?;
643
            }
644
645
141k
            if r != 0 {
646
122k
                return Marker::from_u8(r)
647
122k
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Line
Count
Source
647
339
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<_>::{closure#0}
648
19.4k
            }
649
11.2M
        }
650
    }
651
2.23k
    return Err(DecodeErrors::ExhaustedData);
652
141k
}
zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Line
Count
Source
622
141k
pub fn get_marker<T>(
623
141k
    reader: &mut ZByteReader<T>, stream: &mut BitStream
624
141k
) -> Result<Marker, DecodeErrors>
625
141k
where
626
141k
    T: ZReaderTrait
627
{
628
141k
    if let Some(marker) = stream.marker {
629
17.4k
        stream.marker = None;
630
17.4k
        return Ok(marker);
631
124k
    }
632
633
    // read until we get a marker
634
635
11.3M
    while !reader.eof() {
636
11.3M
        let marker = reader.get_u8_err()?;
637
638
11.3M
        if marker == 255 {
639
141k
            let mut r = reader.get_u8_err()?;
640
            // 0xFF 0XFF(some images may be like that)
641
258k
            while r == 0xFF {
642
116k
                r = reader.get_u8_err()?;
643
            }
644
645
141k
            if r != 0 {
646
122k
                return Marker::from_u8(r)
647
122k
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
648
19.4k
            }
649
11.2M
        }
650
    }
651
2.23k
    return Err(DecodeErrors::ExhaustedData);
652
141k
}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<_>