Coverage Report

Created: 2025-11-09 06:56

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.33k
    pub(crate) fn decode_mcu_ycbcr_progressive(
51
3.33k
        &mut self, pixels: &mut [u8],
52
3.33k
    ) -> Result<(), DecodeErrors> {
53
3.33k
        setup_component_params(self)?;
54
55
        let mut mcu_height;
56
57
        // memory location for decoded pixels for components
58
3.32k
        let mut block: [Vec<i16>; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]];
59
        let mut mcu_width;
60
61
3.32k
        let mut seen_scans = 1;
62
63
3.32k
        if self.input_colorspace == ColorSpace::Luma && self.is_interleaved {
64
2
            warn!("Grayscale image with down-sampled component, resetting component details");
65
2
            self.reset_params();
66
3.32k
        }
67
68
3.32k
        if self.is_interleaved {
69
            // this helps us catch component errors.
70
0
            self.set_upsampling()?;
71
3.32k
        }
72
3.32k
        if self.is_interleaved {
73
0
            mcu_width = self.mcu_x;
74
0
            mcu_height = self.mcu_y;
75
3.32k
        } else {
76
3.32k
            mcu_width = (self.info.width as usize + 7) / 8;
77
3.32k
            mcu_height = (self.info.height as usize + 7) / 8;
78
3.32k
        }
79
3.32k
        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.32k
        }
97
98
3.32k
        mcu_width *= 64;
99
100
101
3.32k
        for i in 0..self.input_colorspace.num_components() {
102
3.32k
            let comp = &self.components[i];
103
3.32k
            let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height;
104
3.32k
105
3.32k
            block[i] = vec![0; len];
106
3.32k
        }
107
108
3.32k
        let mut stream = BitStream::new_progressive(
109
3.32k
            self.succ_high,
110
3.32k
            self.succ_low,
111
3.32k
            self.spec_start,
112
3.32k
            self.spec_end
113
        );
114
115
        // there are multiple scans in the stream, this should resolve the first scan
116
3.32k
        self.parse_entropy_coded_data(&mut stream, &mut block)?;
117
118
        // extract marker
119
3.15k
        let mut marker = stream
120
3.15k
            .marker
121
3.15k
            .take()
122
3.15k
            .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
94.2k
        'eoi: while marker != Marker::EOI {
130
94.1k
            match marker {
131
                Marker::SOS => {
132
24.5k
                    parse_sos(self)?;
133
134
24.4k
                    stream.update_progressive_params(
135
24.4k
                        self.succ_high,
136
24.4k
                        self.succ_low,
137
24.4k
                        self.spec_start,
138
24.4k
                        self.spec_end
139
                    );
140
                    // after every SOS, marker, parse data for that scan.
141
24.4k
                    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
23.9k
                    match get_marker(&mut self.stream, &mut stream) {
145
22.7k
                        Ok(marker_n) => {
146
22.7k
                            marker = marker_n;
147
22.7k
                            seen_scans += 1;
148
22.7k
                            if seen_scans > self.options.jpeg_get_max_scans() {
149
29
                                return Err(DecodeErrors::Format(format!(
150
29
                                    "Too many scans, exceeded limit of {}",
151
29
                                    self.options.jpeg_get_max_scans()
152
29
                                )));
153
22.7k
                            }
154
155
22.7k
                            stream.reset();
156
22.7k
                            continue 'eoi;
157
                        }
158
1.15k
                        Err(msg) => {
159
1.15k
                            if self.options.get_strict_mode() {
160
1.15k
                                return Err(msg);
161
0
                            }
162
0
                            error!("{:?}", msg);
163
0
                            break 'eoi;
164
                        }
165
                    }
166
                }
167
2.07k
                Marker::RST(_n) => {
168
2.07k
                    self.handle_rst(&mut stream)?;
169
                }
170
                _ => {
171
67.4k
                    self.parse_marker_inner(marker)?;
172
                }
173
            }
174
175
69.2k
            match get_marker(&mut self.stream, &mut stream) {
176
68.7k
                Ok(marker_n) => {
177
68.7k
                    marker = marker_n;
178
68.7k
                }
179
461
                Err(e) => {
180
461
                    if self.options.get_strict_mode() {
181
461
                        return Err(e);
182
0
                    }
183
0
                    error!("{}", e);
184
                }
185
            }
186
        }
187
188
149
        self.finish_progressive_decoding(&block, mcu_width, pixels)
189
3.33k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::decode_mcu_ycbcr_progressive
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Line
Count
Source
50
1.99k
    pub(crate) fn decode_mcu_ycbcr_progressive(
51
1.99k
        &mut self, pixels: &mut [u8],
52
1.99k
    ) -> Result<(), DecodeErrors> {
53
1.99k
        setup_component_params(self)?;
54
55
        let mut mcu_height;
56
57
        // memory location for decoded pixels for components
58
1.99k
        let mut block: [Vec<i16>; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]];
59
        let mut mcu_width;
60
61
1.99k
        let mut seen_scans = 1;
62
63
1.99k
        if self.input_colorspace == ColorSpace::Luma && self.is_interleaved {
64
1
            warn!("Grayscale image with down-sampled component, resetting component details");
65
1
            self.reset_params();
66
1.99k
        }
67
68
1.99k
        if self.is_interleaved {
69
            // this helps us catch component errors.
70
0
            self.set_upsampling()?;
71
1.99k
        }
72
1.99k
        if self.is_interleaved {
73
0
            mcu_width = self.mcu_x;
74
0
            mcu_height = self.mcu_y;
75
1.99k
        } else {
76
1.99k
            mcu_width = (self.info.width as usize + 7) / 8;
77
1.99k
            mcu_height = (self.info.height as usize + 7) / 8;
78
1.99k
        }
79
1.99k
        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
1.99k
        }
97
98
1.99k
        mcu_width *= 64;
99
100
101
1.99k
        for i in 0..self.input_colorspace.num_components() {
102
1.99k
            let comp = &self.components[i];
103
1.99k
            let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height;
104
1.99k
105
1.99k
            block[i] = vec![0; len];
106
1.99k
        }
107
108
1.99k
        let mut stream = BitStream::new_progressive(
109
1.99k
            self.succ_high,
110
1.99k
            self.succ_low,
111
1.99k
            self.spec_start,
112
1.99k
            self.spec_end
113
        );
114
115
        // there are multiple scans in the stream, this should resolve the first scan
116
1.99k
        self.parse_entropy_coded_data(&mut stream, &mut block)?;
117
118
        // extract marker
119
1.87k
        let mut marker = stream
120
1.87k
            .marker
121
1.87k
            .take()
122
1.87k
            .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
74.5k
        'eoi: while marker != Marker::EOI {
130
74.4k
            match marker {
131
                Marker::SOS => {
132
12.6k
                    parse_sos(self)?;
133
134
12.6k
                    stream.update_progressive_params(
135
12.6k
                        self.succ_high,
136
12.6k
                        self.succ_low,
137
12.6k
                        self.spec_start,
138
12.6k
                        self.spec_end
139
                    );
140
                    // after every SOS, marker, parse data for that scan.
141
12.6k
                    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
12.3k
                    match get_marker(&mut self.stream, &mut stream) {
145
11.7k
                        Ok(marker_n) => {
146
11.7k
                            marker = marker_n;
147
11.7k
                            seen_scans += 1;
148
11.7k
                            if seen_scans > self.options.jpeg_get_max_scans() {
149
17
                                return Err(DecodeErrors::Format(format!(
150
17
                                    "Too many scans, exceeded limit of {}",
151
17
                                    self.options.jpeg_get_max_scans()
152
17
                                )));
153
11.7k
                            }
154
155
11.7k
                            stream.reset();
156
11.7k
                            continue 'eoi;
157
                        }
158
554
                        Err(msg) => {
159
554
                            if self.options.get_strict_mode() {
160
554
                                return Err(msg);
161
0
                            }
162
0
                            error!("{:?}", msg);
163
0
                            break 'eoi;
164
                        }
165
                    }
166
                }
167
1.13k
                Marker::RST(_n) => {
168
1.13k
                    self.handle_rst(&mut stream)?;
169
                }
170
                _ => {
171
60.6k
                    self.parse_marker_inner(marker)?;
172
                }
173
            }
174
175
61.5k
            match get_marker(&mut self.stream, &mut stream) {
176
61.2k
                Ok(marker_n) => {
177
61.2k
                    marker = marker_n;
178
61.2k
                }
179
333
                Err(e) => {
180
333
                    if self.options.get_strict_mode() {
181
333
                        return Err(e);
182
0
                    }
183
0
                    error!("{}", e);
184
                }
185
            }
186
        }
187
188
109
        self.finish_progressive_decoding(&block, mcu_width, pixels)
189
1.99k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::decode_mcu_ycbcr_progressive
Line
Count
Source
50
1.33k
    pub(crate) fn decode_mcu_ycbcr_progressive(
51
1.33k
        &mut self, pixels: &mut [u8],
52
1.33k
    ) -> Result<(), DecodeErrors> {
53
1.33k
        setup_component_params(self)?;
54
55
        let mut mcu_height;
56
57
        // memory location for decoded pixels for components
58
1.33k
        let mut block: [Vec<i16>; MAX_COMPONENTS] = [vec![], vec![], vec![], vec![]];
59
        let mut mcu_width;
60
61
1.33k
        let mut seen_scans = 1;
62
63
1.33k
        if self.input_colorspace == ColorSpace::Luma && self.is_interleaved {
64
1
            warn!("Grayscale image with down-sampled component, resetting component details");
65
1
            self.reset_params();
66
1.33k
        }
67
68
1.33k
        if self.is_interleaved {
69
            // this helps us catch component errors.
70
0
            self.set_upsampling()?;
71
1.33k
        }
72
1.33k
        if self.is_interleaved {
73
0
            mcu_width = self.mcu_x;
74
0
            mcu_height = self.mcu_y;
75
1.33k
        } else {
76
1.33k
            mcu_width = (self.info.width as usize + 7) / 8;
77
1.33k
            mcu_height = (self.info.height as usize + 7) / 8;
78
1.33k
        }
79
1.33k
        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
1.33k
        }
97
98
1.33k
        mcu_width *= 64;
99
100
101
1.33k
        for i in 0..self.input_colorspace.num_components() {
102
1.33k
            let comp = &self.components[i];
103
1.33k
            let len = mcu_width * comp.vertical_sample * comp.horizontal_sample * mcu_height;
104
1.33k
105
1.33k
            block[i] = vec![0; len];
106
1.33k
        }
107
108
1.33k
        let mut stream = BitStream::new_progressive(
109
1.33k
            self.succ_high,
110
1.33k
            self.succ_low,
111
1.33k
            self.spec_start,
112
1.33k
            self.spec_end
113
        );
114
115
        // there are multiple scans in the stream, this should resolve the first scan
116
1.33k
        self.parse_entropy_coded_data(&mut stream, &mut block)?;
117
118
        // extract marker
119
1.27k
        let mut marker = stream
120
1.27k
            .marker
121
1.27k
            .take()
122
1.27k
            .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
19.6k
        'eoi: while marker != Marker::EOI {
130
19.6k
            match marker {
131
                Marker::SOS => {
132
11.8k
                    parse_sos(self)?;
133
134
11.8k
                    stream.update_progressive_params(
135
11.8k
                        self.succ_high,
136
11.8k
                        self.succ_low,
137
11.8k
                        self.spec_start,
138
11.8k
                        self.spec_end
139
                    );
140
                    // after every SOS, marker, parse data for that scan.
141
11.8k
                    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
11.5k
                    match get_marker(&mut self.stream, &mut stream) {
145
10.9k
                        Ok(marker_n) => {
146
10.9k
                            marker = marker_n;
147
10.9k
                            seen_scans += 1;
148
10.9k
                            if seen_scans > self.options.jpeg_get_max_scans() {
149
12
                                return Err(DecodeErrors::Format(format!(
150
12
                                    "Too many scans, exceeded limit of {}",
151
12
                                    self.options.jpeg_get_max_scans()
152
12
                                )));
153
10.9k
                            }
154
155
10.9k
                            stream.reset();
156
10.9k
                            continue 'eoi;
157
                        }
158
605
                        Err(msg) => {
159
605
                            if self.options.get_strict_mode() {
160
605
                                return Err(msg);
161
0
                            }
162
0
                            error!("{:?}", msg);
163
0
                            break 'eoi;
164
                        }
165
                    }
166
                }
167
936
                Marker::RST(_n) => {
168
936
                    self.handle_rst(&mut stream)?;
169
                }
170
                _ => {
171
6.82k
                    self.parse_marker_inner(marker)?;
172
                }
173
            }
174
175
7.64k
            match get_marker(&mut self.stream, &mut stream) {
176
7.51k
                Ok(marker_n) => {
177
7.51k
                    marker = marker_n;
178
7.51k
                }
179
128
                Err(e) => {
180
128
                    if self.options.get_strict_mode() {
181
128
                        return Err(e);
182
0
                    }
183
0
                    error!("{}", e);
184
                }
185
            }
186
        }
187
188
40
        self.finish_progressive_decoding(&block, mcu_width, pixels)
189
1.33k
    }
190
191
    /// Reset progressive parameters
192
27.7k
    fn reset_prog_params(&mut self, stream: &mut BitStream) {
193
27.7k
        stream.reset();
194
27.7k
        self.components.iter_mut().for_each(|x| x.dc_pred = 0);
195
196
        // Also reset JPEG restart intervals
197
27.7k
        self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX };
198
27.7k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::reset_prog_params
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Line
Count
Source
192
14.6k
    fn reset_prog_params(&mut self, stream: &mut BitStream) {
193
14.6k
        stream.reset();
194
14.6k
        self.components.iter_mut().for_each(|x| x.dc_pred = 0);
195
196
        // Also reset JPEG restart intervals
197
14.6k
        self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX };
198
14.6k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_prog_params
Line
Count
Source
192
13.1k
    fn reset_prog_params(&mut self, stream: &mut BitStream) {
193
13.1k
        stream.reset();
194
13.1k
        self.components.iter_mut().for_each(|x| x.dc_pred = 0);
195
196
        // Also reset JPEG restart intervals
197
13.1k
        self.todo = if self.restart_interval != 0 { self.restart_interval } else { usize::MAX };
198
13.1k
    }
199
200
    #[allow(clippy::too_many_lines, clippy::cast_sign_loss)]
201
27.7k
    fn parse_entropy_coded_data(
202
27.7k
        &mut self, stream: &mut BitStream, buffer: &mut [Vec<i16>; MAX_COMPONENTS]
203
27.7k
    ) -> Result<(), DecodeErrors> {
204
27.7k
        self.reset_prog_params(stream);
205
206
27.7k
        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
27.7k
        }
213
27.7k
        if self.num_scans == 1 {
214
            // Safety checks
215
27.7k
            if self.spec_end != 0 && self.spec_start == 0 {
216
8
                return Err(DecodeErrors::FormatStatic(
217
8
                    "Can't merge DC and AC corrupt jpeg"
218
8
                ));
219
27.7k
            }
220
            // non interleaved data, process one block at a time in trivial scanline order
221
222
27.7k
            let k = self.z_order[0];
223
224
27.7k
            if k >= self.components.len() {
225
0
                return Err(DecodeErrors::Format(format!(
226
0
                    "Cannot find component {k}, corrupt image"
227
0
                )));
228
27.7k
            }
229
230
            let (mcu_width, mcu_height);
231
232
27.7k
            if self.components[k].component_id == ComponentID::Y
233
27.7k
                && (self.components[k].vertical_sample != 1
234
27.7k
                    || self.components[k].horizontal_sample != 1)
235
27.7k
                || !self.is_interleaved
236
27.7k
            {
237
27.7k
                // For Y channel  or non interleaved scans ,
238
27.7k
                // mcu's is the image dimensions divided by 8
239
27.7k
                mcu_width = ((self.info.width + 7) / 8) as usize;
240
27.7k
                mcu_height = ((self.info.height + 7) / 8) as usize;
241
27.7k
            } 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.41M
            for i in 0..mcu_height {
249
146M
                for j in 0..mcu_width {
250
146M
                    if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 {
251
103k
                        // handle EOB runs here.
252
103k
                        stream.eob_run -= 1;
253
103k
                    } else {
254
146M
                        let start = 64 * (j + i * (self.components[k].width_stride / 8));
255
256
146M
                        let data: &mut [i16; 64] = buffer
257
146M
                            .get_mut(k)
258
146M
                            .unwrap()
259
146M
                            .get_mut(start..start + 64)
260
146M
                            .unwrap()
261
146M
                            .try_into()
262
146M
                            .unwrap();
263
264
146M
                        if self.spec_start == 0 {
265
73.7M
                            let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1);
266
73.7M
                            let dc_table = self
267
73.7M
                                .dc_huffman_tables
268
73.7M
                                .get(pos)
269
73.7M
                                .ok_or(DecodeErrors::FormatStatic(
270
73.7M
                                    "No huffman table for DC component"
271
73.7M
                                ))?
272
73.7M
                                .as_ref()
273
73.7M
                                .ok_or(DecodeErrors::FormatStatic(
274
73.7M
                                    "Huffman table at index  {} not initialized"
275
73.7M
                                ))?;
276
277
73.7M
                            let dc_pred = &mut self.components[k].dc_pred;
278
279
73.7M
                            if self.succ_high == 0 {
280
                                // first scan for this mcu
281
49.6M
                                stream.decode_prog_dc_first(
282
49.6M
                                    &mut self.stream,
283
49.6M
                                    dc_table,
284
49.6M
                                    &mut data[0],
285
49.6M
                                    dc_pred
286
146
                                )?;
287
                            } else {
288
                                // refining scans for this MCU
289
24.0M
                                stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?;
290
                            }
291
                        } else {
292
73.0M
                            let pos = self.components[k].ac_huff_table;
293
73.0M
                            let ac_table = self
294
73.0M
                                .ac_huffman_tables
295
73.0M
                                .get(pos)
296
73.0M
                                .ok_or_else(|| {
297
2
                                    DecodeErrors::Format(format!(
298
2
                                        "No huffman table for component:{pos}"
299
2
                                    ))
300
2
                                })?
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#0}
Line
Count
Source
296
2
                                .ok_or_else(|| {
297
2
                                    DecodeErrors::Format(format!(
298
2
                                        "No huffman table for component:{pos}"
299
2
                                    ))
300
2
                                })?
301
73.0M
                                .as_ref()
302
73.0M
                                .ok_or_else(|| {
303
2
                                    DecodeErrors::Format(format!(
304
2
                                        "Huffman table at index  {pos} not initialized"
305
2
                                    ))
306
2
                                })?;
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#1}
Line
Count
Source
302
2
                                .ok_or_else(|| {
303
2
                                    DecodeErrors::Format(format!(
304
2
                                        "Huffman table at index  {pos} not initialized"
305
2
                                    ))
306
2
                                })?;
307
308
73.0M
                            if self.succ_high == 0 {
309
38.7M
                                debug_assert!(stream.eob_run == 0, "EOB run is not zero");
310
311
38.7M
                                stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?;
312
                            } else {
313
                                // refinement scan
314
34.2M
                                stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?;
315
                            }
316
                        }
317
                    }
318
319
                    // + EOB and investigate effect.
320
146M
                    self.todo -= 1;
321
322
146M
                    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}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#2}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::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}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data::{closure#3}
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::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
27.0k
        return Ok(());
416
27.7k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::parse_entropy_coded_data
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Line
Count
Source
201
14.6k
    fn parse_entropy_coded_data(
202
14.6k
        &mut self, stream: &mut BitStream, buffer: &mut [Vec<i16>; MAX_COMPONENTS]
203
14.6k
    ) -> Result<(), DecodeErrors> {
204
14.6k
        self.reset_prog_params(stream);
205
206
14.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
14.6k
        }
213
14.6k
        if self.num_scans == 1 {
214
            // Safety checks
215
14.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
14.6k
            }
220
            // non interleaved data, process one block at a time in trivial scanline order
221
222
14.6k
            let k = self.z_order[0];
223
224
14.6k
            if k >= self.components.len() {
225
0
                return Err(DecodeErrors::Format(format!(
226
0
                    "Cannot find component {k}, corrupt image"
227
0
                )));
228
14.6k
            }
229
230
            let (mcu_width, mcu_height);
231
232
14.6k
            if self.components[k].component_id == ComponentID::Y
233
14.6k
                && (self.components[k].vertical_sample != 1
234
14.6k
                    || self.components[k].horizontal_sample != 1)
235
14.6k
                || !self.is_interleaved
236
14.6k
            {
237
14.6k
                // For Y channel  or non interleaved scans ,
238
14.6k
                // mcu's is the image dimensions divided by 8
239
14.6k
                mcu_width = ((self.info.width + 7) / 8) as usize;
240
14.6k
                mcu_height = ((self.info.height + 7) / 8) as usize;
241
14.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
466k
            for i in 0..mcu_height {
249
127M
                for j in 0..mcu_width {
250
127M
                    if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 {
251
29.7k
                        // handle EOB runs here.
252
29.7k
                        stream.eob_run -= 1;
253
29.7k
                    } else {
254
127M
                        let start = 64 * (j + i * (self.components[k].width_stride / 8));
255
256
127M
                        let data: &mut [i16; 64] = buffer
257
127M
                            .get_mut(k)
258
127M
                            .unwrap()
259
127M
                            .get_mut(start..start + 64)
260
127M
                            .unwrap()
261
127M
                            .try_into()
262
127M
                            .unwrap();
263
264
127M
                        if self.spec_start == 0 {
265
65.5M
                            let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1);
266
65.5M
                            let dc_table = self
267
65.5M
                                .dc_huffman_tables
268
65.5M
                                .get(pos)
269
65.5M
                                .ok_or(DecodeErrors::FormatStatic(
270
65.5M
                                    "No huffman table for DC component"
271
65.5M
                                ))?
272
65.5M
                                .as_ref()
273
65.5M
                                .ok_or(DecodeErrors::FormatStatic(
274
65.5M
                                    "Huffman table at index  {} not initialized"
275
65.5M
                                ))?;
276
277
65.5M
                            let dc_pred = &mut self.components[k].dc_pred;
278
279
65.5M
                            if self.succ_high == 0 {
280
                                // first scan for this mcu
281
49.5M
                                stream.decode_prog_dc_first(
282
49.5M
                                    &mut self.stream,
283
49.5M
                                    dc_table,
284
49.5M
                                    &mut data[0],
285
49.5M
                                    dc_pred
286
74
                                )?;
287
                            } else {
288
                                // refining scans for this MCU
289
15.9M
                                stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?;
290
                            }
291
                        } else {
292
61.5M
                            let pos = self.components[k].ac_huff_table;
293
61.5M
                            let ac_table = self
294
61.5M
                                .ac_huffman_tables
295
61.5M
                                .get(pos)
296
61.5M
                                .ok_or_else(|| {
297
                                    DecodeErrors::Format(format!(
298
                                        "No huffman table for component:{pos}"
299
                                    ))
300
0
                                })?
301
61.5M
                                .as_ref()
302
61.5M
                                .ok_or_else(|| {
303
                                    DecodeErrors::Format(format!(
304
                                        "Huffman table at index  {pos} not initialized"
305
                                    ))
306
0
                                })?;
307
308
61.5M
                            if self.succ_high == 0 {
309
28.4M
                                debug_assert!(stream.eob_run == 0, "EOB run is not zero");
310
311
28.4M
                                stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?;
312
                            } else {
313
                                // refinement scan
314
33.1M
                                stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?;
315
                            }
316
                        }
317
                    }
318
319
                    // + EOB and investigate effect.
320
127M
                    self.todo -= 1;
321
322
127M
                    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
14.2k
        return Ok(());
416
14.6k
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::parse_entropy_coded_data
Line
Count
Source
201
13.1k
    fn parse_entropy_coded_data(
202
13.1k
        &mut self, stream: &mut BitStream, buffer: &mut [Vec<i16>; MAX_COMPONENTS]
203
13.1k
    ) -> Result<(), DecodeErrors> {
204
13.1k
        self.reset_prog_params(stream);
205
206
13.1k
        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
13.1k
        }
213
13.1k
        if self.num_scans == 1 {
214
            // Safety checks
215
13.1k
            if self.spec_end != 0 && self.spec_start == 0 {
216
2
                return Err(DecodeErrors::FormatStatic(
217
2
                    "Can't merge DC and AC corrupt jpeg"
218
2
                ));
219
13.1k
            }
220
            // non interleaved data, process one block at a time in trivial scanline order
221
222
13.1k
            let k = self.z_order[0];
223
224
13.1k
            if k >= self.components.len() {
225
0
                return Err(DecodeErrors::Format(format!(
226
0
                    "Cannot find component {k}, corrupt image"
227
0
                )));
228
13.1k
            }
229
230
            let (mcu_width, mcu_height);
231
232
13.1k
            if self.components[k].component_id == ComponentID::Y
233
13.1k
                && (self.components[k].vertical_sample != 1
234
13.1k
                    || self.components[k].horizontal_sample != 1)
235
13.1k
                || !self.is_interleaved
236
13.1k
            {
237
13.1k
                // For Y channel  or non interleaved scans ,
238
13.1k
                // mcu's is the image dimensions divided by 8
239
13.1k
                mcu_width = ((self.info.width + 7) / 8) as usize;
240
13.1k
                mcu_height = ((self.info.height + 7) / 8) as usize;
241
13.1k
            } 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
946k
            for i in 0..mcu_height {
249
19.6M
                for j in 0..mcu_width {
250
19.6M
                    if self.spec_start != 0 && self.succ_high == 0 && stream.eob_run > 0 {
251
73.2k
                        // handle EOB runs here.
252
73.2k
                        stream.eob_run -= 1;
253
73.2k
                    } else {
254
19.5M
                        let start = 64 * (j + i * (self.components[k].width_stride / 8));
255
256
19.5M
                        let data: &mut [i16; 64] = buffer
257
19.5M
                            .get_mut(k)
258
19.5M
                            .unwrap()
259
19.5M
                            .get_mut(start..start + 64)
260
19.5M
                            .unwrap()
261
19.5M
                            .try_into()
262
19.5M
                            .unwrap();
263
264
19.5M
                        if self.spec_start == 0 {
265
8.13M
                            let pos = self.components[k].dc_huff_table & (MAX_COMPONENTS - 1);
266
8.13M
                            let dc_table = self
267
8.13M
                                .dc_huffman_tables
268
8.13M
                                .get(pos)
269
8.13M
                                .ok_or(DecodeErrors::FormatStatic(
270
8.13M
                                    "No huffman table for DC component"
271
8.13M
                                ))?
272
8.13M
                                .as_ref()
273
8.13M
                                .ok_or(DecodeErrors::FormatStatic(
274
8.13M
                                    "Huffman table at index  {} not initialized"
275
8.13M
                                ))?;
276
277
8.13M
                            let dc_pred = &mut self.components[k].dc_pred;
278
279
8.13M
                            if self.succ_high == 0 {
280
                                // first scan for this mcu
281
38.6k
                                stream.decode_prog_dc_first(
282
38.6k
                                    &mut self.stream,
283
38.6k
                                    dc_table,
284
38.6k
                                    &mut data[0],
285
38.6k
                                    dc_pred
286
72
                                )?;
287
                            } else {
288
                                // refining scans for this MCU
289
8.09M
                                stream.decode_prog_dc_refine(&mut self.stream, &mut data[0])?;
290
                            }
291
                        } else {
292
11.4M
                            let pos = self.components[k].ac_huff_table;
293
11.4M
                            let ac_table = self
294
11.4M
                                .ac_huffman_tables
295
11.4M
                                .get(pos)
296
11.4M
                                .ok_or_else(|| {
297
                                    DecodeErrors::Format(format!(
298
                                        "No huffman table for component:{pos}"
299
                                    ))
300
2
                                })?
301
11.4M
                                .as_ref()
302
11.4M
                                .ok_or_else(|| {
303
                                    DecodeErrors::Format(format!(
304
                                        "Huffman table at index  {pos} not initialized"
305
                                    ))
306
2
                                })?;
307
308
11.4M
                            if self.succ_high == 0 {
309
10.3M
                                debug_assert!(stream.eob_run == 0, "EOB run is not zero");
310
311
10.3M
                                stream.decode_mcu_ac_first(&mut self.stream, ac_table, data)?;
312
                            } else {
313
                                // refinement scan
314
1.11M
                                stream.decode_mcu_ac_refine(&mut self.stream, ac_table, data)?;
315
                            }
316
                        }
317
                    }
318
319
                    // + EOB and investigate effect.
320
19.6M
                    self.todo -= 1;
321
322
19.6M
                    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
12.8k
        return Ok(());
416
13.1k
    }
417
418
146M
    pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> {
419
146M
        if self.todo == 0 {
420
26
            stream.refill(&mut self.stream)?;
421
146M
        }
422
423
146M
        if self.todo == 0
424
26
            && self.restart_interval != 0
425
26
            && stream.marker.is_none()
426
21
            && !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
21
            let _start = self.stream.get_position();
432
            // skip bytes until we find marker
433
21
            let marker = get_marker(&mut self.stream, stream)?;
434
6
            let _end = self.stream.get_position();
435
6
            stream.marker = Some(marker);
436
            // NB some warnings may be false positives.
437
6
            warn!(
438
                "{} Extraneous bytes before marker {:?}",
439
                _end - _start,
440
                marker
441
            );
442
146M
        }
443
146M
        if self.todo == 0 {
444
11
            self.handle_rst(stream)?
445
146M
        }
446
146M
        Ok(())
447
146M
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::handle_rst_main
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Line
Count
Source
418
127M
    pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> {
419
127M
        if self.todo == 0 {
420
8
            stream.refill(&mut self.stream)?;
421
127M
        }
422
423
127M
        if self.todo == 0
424
8
            && self.restart_interval != 0
425
8
            && stream.marker.is_none()
426
5
            && !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
            let _start = self.stream.get_position();
432
            // skip bytes until we find marker
433
5
            let marker = get_marker(&mut self.stream, stream)?;
434
1
            let _end = self.stream.get_position();
435
1
            stream.marker = Some(marker);
436
            // NB some warnings may be false positives.
437
1
            warn!(
438
                "{} Extraneous bytes before marker {:?}",
439
                _end - _start,
440
                marker
441
            );
442
127M
        }
443
127M
        if self.todo == 0 {
444
4
            self.handle_rst(stream)?
445
127M
        }
446
127M
        Ok(())
447
127M
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::handle_rst_main
Line
Count
Source
418
19.6M
    pub(crate) fn handle_rst_main(&mut self, stream: &mut BitStream) -> Result<(), DecodeErrors> {
419
19.6M
        if self.todo == 0 {
420
18
            stream.refill(&mut self.stream)?;
421
19.6M
        }
422
423
19.6M
        if self.todo == 0
424
18
            && self.restart_interval != 0
425
18
            && stream.marker.is_none()
426
16
            && !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
16
            let _start = self.stream.get_position();
432
            // skip bytes until we find marker
433
16
            let marker = get_marker(&mut self.stream, stream)?;
434
5
            let _end = self.stream.get_position();
435
5
            stream.marker = Some(marker);
436
            // NB some warnings may be false positives.
437
5
            warn!(
438
                "{} Extraneous bytes before marker {:?}",
439
                _end - _start,
440
                marker
441
            );
442
19.6M
        }
443
19.6M
        if self.todo == 0 {
444
7
            self.handle_rst(stream)?
445
19.6M
        }
446
19.6M
        Ok(())
447
19.6M
    }
448
    #[allow(clippy::too_many_lines)]
449
    #[allow(clippy::needless_range_loop, clippy::cast_sign_loss)]
450
149
    fn finish_progressive_decoding(
451
149
        &mut self, block: &[Vec<i16>; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8]
452
149
    ) -> 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
149
        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
149
            ((self.info.height + 7) / 8) as usize
478
        };
479
480
        // Size of our output image(width*height)
481
149
        let is_hv = usize::from(self.is_interleaved);
482
149
        let upsampler_scratch_size = is_hv * self.components[0].width_stride;
483
149
        let width = usize::from(self.info.width);
484
149
        let padded_width = calculate_padded_width(width, self.sub_sample_ratio);
485
486
        //let mut pixels = vec![0; capacity * out_colorspace_components];
487
149
        let mut upsampler_scratch_space = vec![0; upsampler_scratch_size];
488
149
        let mut tmp = [0_i32; DCT_BLOCK];
489
490
149
        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
149
            if min(
496
149
                self.options.jpeg_get_out_colorspace().num_components() - 1,
497
149
                pos,
498
149
            ) == pos
499
0
                || self.input_colorspace == ColorSpace::YCCK
500
0
                || self.input_colorspace == ColorSpace::CMYK
501
149
            {
502
149
                // allocate enough space to hold a whole MCU width
503
149
                // this means we should take into account sampling ratios
504
149
                // `*8` is because each MCU spans 8 widths.
505
149
                let len = comp.width_stride * comp.vertical_sample * 8;
506
149
507
149
                comp.needed = true;
508
149
                comp.raw_coeff = vec![0; len];
509
149
            } else {
510
0
                comp.needed = false;
511
0
            }
512
        }
513
514
149
        let mut pixels_written = 0;
515
516
        // dequantize, idct and color convert.
517
9.02k
        for i in 0..mcu_height {
518
9.02k
            'component: for (position, component) in &mut self.components.iter_mut().enumerate() {
519
9.02k
                if !component.needed {
520
0
                    continue 'component;
521
9.02k
                }
522
9.02k
                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
9.02k
                let step = block[position].len() / mcu_height;
532
                // where we will be reading our pixels from.
533
9.02k
                let start = i * step;
534
535
9.02k
                let slice = &block[position][start..start + step];
536
537
9.02k
                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
9.02k
                let mcu_x = component.width_stride / 8;
544
545
                // iterate per every vertical sample.
546
9.02k
                for k in 0..component.vertical_sample {
547
2.85M
                    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
2.85M
                        let width_stride = k * 8 * component.width_stride;
551
2.85M
                        let start = j * 64 + width_stride;
552
553
                        // See https://github.com/etemesi254/zune-image/issues/262 sample 3.
554
2.85M
                        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
182M
                        for ((x, out), qt_val) in qt_slice
559
2.85M
                            .iter()
560
2.85M
                            .zip(tmp.iter_mut())
561
2.85M
                            .zip(qt_table.iter())
562
182M
                        {
563
182M
                            *out = i32::from(*x) * qt_val;
564
182M
                        }
565
                        // determine where to write.
566
2.85M
                        let sl = &mut temp_channel[component.idct_pos..];
567
568
2.85M
                        component.idct_pos += 8;
569
                        // tmp now contains a dequantized block so idct it
570
2.85M
                        (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
9.02k
                    component.idct_pos += 7 * component.width_stride;
579
                }
580
9.02k
                component.idct_pos = 0;
581
            }
582
583
            // process that width up until it's impossible
584
9.02k
            self.post_process(
585
9.02k
                pixels,
586
9.02k
                i,
587
9.02k
                mcu_height,
588
9.02k
                width,
589
9.02k
                padded_width,
590
9.02k
                &mut pixels_written,
591
9.02k
                &mut upsampler_scratch_space
592
1
            )?;
593
        }
594
595
        debug!("Finished decoding image");
596
597
148
        return Ok(());
598
149
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::finish_progressive_decoding
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Line
Count
Source
450
109
    fn finish_progressive_decoding(
451
109
        &mut self, block: &[Vec<i16>; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8]
452
109
    ) -> 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
109
        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
109
            ((self.info.height + 7) / 8) as usize
478
        };
479
480
        // Size of our output image(width*height)
481
109
        let is_hv = usize::from(self.is_interleaved);
482
109
        let upsampler_scratch_size = is_hv * self.components[0].width_stride;
483
109
        let width = usize::from(self.info.width);
484
109
        let padded_width = calculate_padded_width(width, self.sub_sample_ratio);
485
486
        //let mut pixels = vec![0; capacity * out_colorspace_components];
487
109
        let mut upsampler_scratch_space = vec![0; upsampler_scratch_size];
488
109
        let mut tmp = [0_i32; DCT_BLOCK];
489
490
109
        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
109
            if min(
496
109
                self.options.jpeg_get_out_colorspace().num_components() - 1,
497
109
                pos,
498
109
            ) == pos
499
0
                || self.input_colorspace == ColorSpace::YCCK
500
0
                || self.input_colorspace == ColorSpace::CMYK
501
109
            {
502
109
                // allocate enough space to hold a whole MCU width
503
109
                // this means we should take into account sampling ratios
504
109
                // `*8` is because each MCU spans 8 widths.
505
109
                let len = comp.width_stride * comp.vertical_sample * 8;
506
109
507
109
                comp.needed = true;
508
109
                comp.raw_coeff = vec![0; len];
509
109
            } else {
510
0
                comp.needed = false;
511
0
            }
512
        }
513
514
109
        let mut pixels_written = 0;
515
516
        // dequantize, idct and color convert.
517
6.68k
        for i in 0..mcu_height {
518
6.68k
            'component: for (position, component) in &mut self.components.iter_mut().enumerate() {
519
6.68k
                if !component.needed {
520
0
                    continue 'component;
521
6.68k
                }
522
6.68k
                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
6.68k
                let step = block[position].len() / mcu_height;
532
                // where we will be reading our pixels from.
533
6.68k
                let start = i * step;
534
535
6.68k
                let slice = &block[position][start..start + step];
536
537
6.68k
                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
6.68k
                let mcu_x = component.width_stride / 8;
544
545
                // iterate per every vertical sample.
546
6.68k
                for k in 0..component.vertical_sample {
547
2.79M
                    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
2.79M
                        let width_stride = k * 8 * component.width_stride;
551
2.79M
                        let start = j * 64 + width_stride;
552
553
                        // See https://github.com/etemesi254/zune-image/issues/262 sample 3.
554
2.79M
                        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
179M
                        for ((x, out), qt_val) in qt_slice
559
2.79M
                            .iter()
560
2.79M
                            .zip(tmp.iter_mut())
561
2.79M
                            .zip(qt_table.iter())
562
179M
                        {
563
179M
                            *out = i32::from(*x) * qt_val;
564
179M
                        }
565
                        // determine where to write.
566
2.79M
                        let sl = &mut temp_channel[component.idct_pos..];
567
568
2.79M
                        component.idct_pos += 8;
569
                        // tmp now contains a dequantized block so idct it
570
2.79M
                        (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
6.68k
                    component.idct_pos += 7 * component.width_stride;
579
                }
580
6.68k
                component.idct_pos = 0;
581
            }
582
583
            // process that width up until it's impossible
584
6.68k
            self.post_process(
585
6.68k
                pixels,
586
6.68k
                i,
587
6.68k
                mcu_height,
588
6.68k
                width,
589
6.68k
                padded_width,
590
6.68k
                &mut pixels_written,
591
6.68k
                &mut upsampler_scratch_space
592
0
            )?;
593
        }
594
595
        debug!("Finished decoding image");
596
597
109
        return Ok(());
598
109
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::finish_progressive_decoding
Line
Count
Source
450
40
    fn finish_progressive_decoding(
451
40
        &mut self, block: &[Vec<i16>; MAX_COMPONENTS], _mcu_width: usize, pixels: &mut [u8]
452
40
    ) -> 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
40
        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
40
            ((self.info.height + 7) / 8) as usize
478
        };
479
480
        // Size of our output image(width*height)
481
40
        let is_hv = usize::from(self.is_interleaved);
482
40
        let upsampler_scratch_size = is_hv * self.components[0].width_stride;
483
40
        let width = usize::from(self.info.width);
484
40
        let padded_width = calculate_padded_width(width, self.sub_sample_ratio);
485
486
        //let mut pixels = vec![0; capacity * out_colorspace_components];
487
40
        let mut upsampler_scratch_space = vec![0; upsampler_scratch_size];
488
40
        let mut tmp = [0_i32; DCT_BLOCK];
489
490
40
        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
40
            if min(
496
40
                self.options.jpeg_get_out_colorspace().num_components() - 1,
497
40
                pos,
498
40
            ) == pos
499
0
                || self.input_colorspace == ColorSpace::YCCK
500
0
                || self.input_colorspace == ColorSpace::CMYK
501
40
            {
502
40
                // allocate enough space to hold a whole MCU width
503
40
                // this means we should take into account sampling ratios
504
40
                // `*8` is because each MCU spans 8 widths.
505
40
                let len = comp.width_stride * comp.vertical_sample * 8;
506
40
507
40
                comp.needed = true;
508
40
                comp.raw_coeff = vec![0; len];
509
40
            } else {
510
0
                comp.needed = false;
511
0
            }
512
        }
513
514
40
        let mut pixels_written = 0;
515
516
        // dequantize, idct and color convert.
517
2.34k
        for i in 0..mcu_height {
518
2.34k
            'component: for (position, component) in &mut self.components.iter_mut().enumerate() {
519
2.34k
                if !component.needed {
520
0
                    continue 'component;
521
2.34k
                }
522
2.34k
                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
2.34k
                let step = block[position].len() / mcu_height;
532
                // where we will be reading our pixels from.
533
2.34k
                let start = i * step;
534
535
2.34k
                let slice = &block[position][start..start + step];
536
537
2.34k
                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
2.34k
                let mcu_x = component.width_stride / 8;
544
545
                // iterate per every vertical sample.
546
2.34k
                for k in 0..component.vertical_sample {
547
57.8k
                    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
57.8k
                        let width_stride = k * 8 * component.width_stride;
551
57.8k
                        let start = j * 64 + width_stride;
552
553
                        // See https://github.com/etemesi254/zune-image/issues/262 sample 3.
554
57.8k
                        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
3.70M
                        for ((x, out), qt_val) in qt_slice
559
57.8k
                            .iter()
560
57.8k
                            .zip(tmp.iter_mut())
561
57.8k
                            .zip(qt_table.iter())
562
3.70M
                        {
563
3.70M
                            *out = i32::from(*x) * qt_val;
564
3.70M
                        }
565
                        // determine where to write.
566
57.8k
                        let sl = &mut temp_channel[component.idct_pos..];
567
568
57.8k
                        component.idct_pos += 8;
569
                        // tmp now contains a dequantized block so idct it
570
57.8k
                        (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
2.34k
                    component.idct_pos += 7 * component.width_stride;
579
                }
580
2.34k
                component.idct_pos = 0;
581
            }
582
583
            // process that width up until it's impossible
584
2.34k
            self.post_process(
585
2.34k
                pixels,
586
2.34k
                i,
587
2.34k
                mcu_height,
588
2.34k
                width,
589
2.34k
                padded_width,
590
2.34k
                &mut pixels_written,
591
2.34k
                &mut upsampler_scratch_space
592
1
            )?;
593
        }
594
595
        debug!("Finished decoding image");
596
597
39
        return Ok(());
598
40
    }
599
17
    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
17
        self.h_max = 1;
609
17
        self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma);
610
17
        self.v_max = 1;
611
17
        self.sub_sample_ratio = SampleRatios::None;
612
17
        self.is_interleaved = false;
613
17
        self.components[0].vertical_sample = 1;
614
17
        self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8;
615
17
        self.components[0].horizontal_sample = 1;
616
17
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<_>>::reset_params
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Line
Count
Source
599
4
    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
4
        self.h_max = 1;
609
4
        self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma);
610
4
        self.v_max = 1;
611
4
        self.sub_sample_ratio = SampleRatios::None;
612
4
        self.is_interleaved = false;
613
4
        self.components[0].vertical_sample = 1;
614
4
        self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8;
615
4
        self.components[0].horizontal_sample = 1;
616
4
    }
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Unexecuted instantiation: <zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
<zune_jpeg::decoder::JpegDecoder<alloc::vec::Vec<u8>>>::reset_params
Line
Count
Source
599
13
    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
13
        self.h_max = 1;
609
13
        self.options = self.options.jpeg_set_out_colorspace(ColorSpace::Luma);
610
13
        self.v_max = 1;
611
13
        self.sub_sample_ratio = SampleRatios::None;
612
13
        self.is_interleaved = false;
613
13
        self.components[0].vertical_sample = 1;
614
13
        self.components[0].width_stride = (((self.info.width as usize) + 7) / 8) * 8;
615
13
        self.components[0].horizontal_sample = 1;
616
13
    }
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
93.7k
pub fn get_marker<T>(
623
93.7k
    reader: &mut ZByteReader<T>, stream: &mut BitStream
624
93.7k
) -> Result<Marker, DecodeErrors>
625
93.7k
where
626
93.7k
    T: ZReaderTrait
627
{
628
93.7k
    if let Some(marker) = stream.marker {
629
21.2k
        stream.marker = None;
630
21.2k
        return Ok(marker);
631
72.5k
    }
632
633
    // read until we get a marker
634
635
5.69M
    while !reader.eof() {
636
5.69M
        let marker = reader.get_u8_err()?;
637
638
5.69M
        if marker == 255 {
639
85.3k
            let mut r = reader.get_u8_err()?;
640
            // 0xFF 0XFF(some images may be like that)
641
216k
            while r == 0xFF {
642
131k
                r = reader.get_u8_err()?;
643
            }
644
645
85.3k
            if r != 0 {
646
70.5k
                return Marker::from_u8(r)
647
70.5k
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<_>::{closure#0}
zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Line
Count
Source
647
200
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>::{closure#0}
Line
Count
Source
647
114
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
648
14.7k
            }
649
5.61M
        }
650
    }
651
1.86k
    return Err(DecodeErrors::ExhaustedData);
652
93.7k
}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<_>
zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Line
Count
Source
622
74.2k
pub fn get_marker<T>(
623
74.2k
    reader: &mut ZByteReader<T>, stream: &mut BitStream
624
74.2k
) -> Result<Marker, DecodeErrors>
625
74.2k
where
626
74.2k
    T: ZReaderTrait
627
{
628
74.2k
    if let Some(marker) = stream.marker {
629
10.8k
        stream.marker = None;
630
10.8k
        return Ok(marker);
631
63.3k
    }
632
633
    // read until we get a marker
634
635
5.47M
    while !reader.eof() {
636
5.47M
        let marker = reader.get_u8_err()?;
637
638
5.47M
        if marker == 255 {
639
72.0k
            let mut r = reader.get_u8_err()?;
640
            // 0xFF 0XFF(some images may be like that)
641
198k
            while r == 0xFF {
642
126k
                r = reader.get_u8_err()?;
643
            }
644
645
72.0k
            if r != 0 {
646
62.4k
                return Marker::from_u8(r)
647
62.4k
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
648
9.67k
            }
649
5.40M
        }
650
    }
651
944
    return Err(DecodeErrors::ExhaustedData);
652
74.2k
}
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Unexecuted instantiation: zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
zune_jpeg::mcu_prog::get_marker::<alloc::vec::Vec<u8>>
Line
Count
Source
622
19.5k
pub fn get_marker<T>(
623
19.5k
    reader: &mut ZByteReader<T>, stream: &mut BitStream
624
19.5k
) -> Result<Marker, DecodeErrors>
625
19.5k
where
626
19.5k
    T: ZReaderTrait
627
{
628
19.5k
    if let Some(marker) = stream.marker {
629
10.4k
        stream.marker = None;
630
10.4k
        return Ok(marker);
631
9.13k
    }
632
633
    // read until we get a marker
634
635
222k
    while !reader.eof() {
636
221k
        let marker = reader.get_u8_err()?;
637
638
221k
        if marker == 255 {
639
13.2k
            let mut r = reader.get_u8_err()?;
640
            // 0xFF 0XFF(some images may be like that)
641
18.6k
            while r == 0xFF {
642
5.38k
                r = reader.get_u8_err()?;
643
            }
644
645
13.2k
            if r != 0 {
646
8.17k
                return Marker::from_u8(r)
647
8.17k
                    .ok_or_else(|| DecodeErrors::Format(format!("Unknown marker 0xFF{r:X}")));
648
5.07k
            }
649
208k
        }
650
    }
651
925
    return Err(DecodeErrors::ExhaustedData);
652
19.5k
}