Coverage Report

Created: 2025-07-12 07:18

/rust/registry/src/index.crates.io-6f17d22bba15001f/zune-jpeg-0.4.19/src/bitstream.rs
Line
Count
Source (jump to first uncovered line)
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
#![allow(
10
    clippy::if_not_else,
11
    clippy::similar_names,
12
    clippy::inline_always,
13
    clippy::doc_markdown,
14
    clippy::cast_sign_loss,
15
    clippy::cast_possible_truncation
16
)]
17
18
//! This file exposes a single struct that can decode a huffman encoded
19
//! Bitstream in a JPEG file
20
//!
21
//! This code is optimized for speed.
22
//! It's meant to be super duper super fast, because everyone else depends on this being fast.
23
//! It's (annoyingly) serial hence we cant use parallel bitstreams(it's variable length coding.)
24
//!
25
//! Furthermore, on the case of refills, we have to do bytewise processing because the standard decided
26
//! that we want to support markers in the middle of streams(seriously few people use RST markers).
27
//!
28
//! So we pull in all optimization steps:
29
//! - use `inline[always]`? ✅ ,
30
//! - pre-execute most common cases ✅,
31
//! - add random comments ✅
32
//! -  fast paths ✅.
33
//!
34
//! Speed-wise: It is probably the fastest JPEG BitStream decoder to ever sail the seven seas because of
35
//! a couple of optimization tricks.
36
//! 1. Fast refills from libjpeg-turbo
37
//! 2. As few as possible branches in decoder fast paths.
38
//! 3. Accelerated AC table decoding borrowed from stb_image.h written by Fabian Gissen (@ rygorous),
39
//! improved by me to handle more cases.
40
//! 4. Safe and extensible routines(e.g. cool ways to eliminate bounds check)
41
//! 5. No unsafe here
42
//!
43
//! Readability comes as a second priority(I tried with variable names this time, and we are wayy better than libjpeg).
44
//!
45
//! Anyway if you are reading this it means your cool and I hope you get whatever part of the code you are looking for
46
//! (or learn something cool)
47
//!
48
//! Knock yourself out.
49
use alloc::string::ToString;
50
use core::cmp::min;
51
use alloc::format;
52
53
use zune_core::bytestream::{ZByteReader, ZReaderTrait};
54
55
use crate::errors::DecodeErrors;
56
use crate::huffman::{HuffmanTable, HUFF_LOOKAHEAD};
57
use crate::marker::Marker;
58
use crate::mcu::DCT_BLOCK;
59
use crate::misc::UN_ZIGZAG;
60
61
macro_rules! decode_huff {
62
    ($stream:tt,$symbol:tt,$table:tt) => {
63
        let mut code_length = $symbol >> HUFF_LOOKAHEAD;
64
65
        ($symbol) &= (1 << HUFF_LOOKAHEAD) - 1;
66
67
        if code_length > i32::from(HUFF_LOOKAHEAD)
68
        {
69
            // if the symbol cannot be resolved in the first HUFF_LOOKAHEAD bits,
70
            // we know it lies somewhere between HUFF_LOOKAHEAD and 16 bits since jpeg imposes 16 bit
71
            // limit, we can therefore look 16 bits ahead and try to resolve the symbol
72
            // starting from 1+HUFF_LOOKAHEAD bits.
73
            $symbol = ($stream).peek_bits::<16>() as i32;
74
            // (Credits to Sean T. Barrett stb library for this optimization)
75
            // maxcode is pre-shifted 16 bytes long so that it has (16-code_length)
76
            // zeroes at the end hence we do not need to shift in the inner loop.
77
            while code_length < 17{
78
                if $symbol < $table.maxcode[code_length as usize]  {
79
                    break;
80
                }
81
                code_length += 1;
82
            }
83
84
            if code_length == 17{
85
                // symbol could not be decoded.
86
                //
87
                // We may think, lets fake zeroes, noo
88
                // panic, because Huffman codes are sensitive, probably everything
89
                // after this will be corrupt, so no need to continue.
90
                // panic!("Bad Huffman code length");
91
                return Err(DecodeErrors::Format(format!("Bad Huffman Code 0x{:X}, corrupt JPEG",$symbol)))
92
            }
93
94
            $symbol >>= (16-code_length);
95
            ($symbol) = i32::from(
96
                ($table).values
97
                    [(($symbol + ($table).offset[code_length as usize]) & 0xFF) as usize],
98
            );
99
        }
100
        // drop bits read
101
        ($stream).drop_bits(code_length as u8);
102
    };
103
}
104
105
/// A `BitStream` struct, a bit by bit reader with super powers
106
///
107
pub(crate) struct BitStream {
108
    /// A MSB type buffer that is used for some certain operations
109
    pub buffer: u64,
110
    /// A TOP  aligned MSB type buffer that is used to accelerate some operations like
111
    /// peek_bits and get_bits.
112
    ///
113
    /// By top aligned, I mean the top bit (63) represents the top bit in the buffer.
114
    aligned_buffer: u64,
115
    /// Tell us the bits left the two buffer
116
    pub(crate) bits_left: u8,
117
    /// Did we find a marker(RST/EOF) during decoding?
118
    pub marker: Option<Marker>,
119
120
    /// Progressive decoding
121
    pub successive_high: u8,
122
    pub successive_low: u8,
123
    spec_start: u8,
124
    spec_end: u8,
125
    pub eob_run: i32,
126
    pub overread_by: usize,
127
    /// True if we have seen end of image marker.
128
    /// Don't read anything after that.
129
    pub seen_eoi: bool,
130
}
131
132
impl BitStream {
133
    /// Create a new BitStream
134
908
    pub(crate) const fn new() -> BitStream {
135
908
        BitStream {
136
908
            buffer: 0,
137
908
            aligned_buffer: 0,
138
908
            bits_left: 0,
139
908
            marker: None,
140
908
            successive_high: 0,
141
908
            successive_low: 0,
142
908
            spec_start: 0,
143
908
            spec_end: 0,
144
908
            eob_run: 0,
145
908
            overread_by: 0,
146
908
            seen_eoi: false,
147
908
        }
148
908
    }
149
150
    /// Create a new Bitstream for progressive decoding
151
    #[allow(clippy::redundant_field_names)]
152
2.64k
    pub(crate) fn new_progressive(ah: u8, al: u8, spec_start: u8, spec_end: u8) -> BitStream {
153
2.64k
        BitStream {
154
2.64k
            buffer: 0,
155
2.64k
            aligned_buffer: 0,
156
2.64k
            bits_left: 0,
157
2.64k
            marker: None,
158
2.64k
            successive_high: ah,
159
2.64k
            successive_low: al,
160
2.64k
            spec_start: spec_start,
161
2.64k
            spec_end: spec_end,
162
2.64k
            eob_run: 0,
163
2.64k
            overread_by: 0,
164
2.64k
            seen_eoi: false,
165
2.64k
        }
166
2.64k
    }
167
168
    /// Refill the bit buffer by (a maximum of) 32 bits
169
    ///
170
    /// # Arguments
171
    ///  - `reader`:`&mut BufReader<R>`: A mutable reference to an underlying
172
    ///    File/Memory buffer containing a valid JPEG stream
173
    ///
174
    /// This function will only refill if `self.count` is less than 32
175
    #[inline(always)] // to many call sites? ( perf improvement by 4%)
176
2.20G
    pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors>
177
2.20G
    where
178
2.20G
        T: ZReaderTrait
179
2.20G
    {
180
        /// Macro version of a single byte refill.
181
        /// Arguments
182
        /// buffer-> our io buffer, because rust macros cannot get values from
183
        /// the surrounding environment bits_left-> number of bits left
184
        /// to full refill
185
        macro_rules! refill {
186
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
187
                // read a byte from the stream
188
                $byte = u64::from(reader.get_u8());
189
                self.overread_by += usize::from(reader.eof());
190
                // append to the buffer
191
                // JPEG is a MSB type buffer so that means we append this
192
                // to the lower end (0..8) of the buffer and push the rest bits above..
193
                $buffer = ($buffer << 8) | $byte;
194
                // Increment bits left
195
                $bits_left += 8;
196
                // Check for special case  of OxFF, to see if it's a stream or a marker
197
                if $byte == 0xff {
198
                    // read next byte
199
                    let mut next_byte = u64::from(reader.get_u8());
200
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
201
                    if next_byte != 0x00 {
202
                        // skip that byte we read
203
                        while next_byte == 0xFF {
204
                            next_byte = u64::from(reader.get_u8());
205
                        }
206
207
                        if next_byte != 0x00 {
208
                            // Undo the byte append and return
209
                            $buffer >>= 8;
210
                            $bits_left -= 8;
211
212
                            if $bits_left != 0 {
213
                                self.aligned_buffer = $buffer << (64 - $bits_left);
214
                            }
215
216
                            self.marker = Marker::from_u8(next_byte as u8);
217
                            if next_byte == 0xD9 {
218
                                // special handling for eoi, fill some bytes,even if its zero,
219
                                // removes some panics
220
                                self.buffer <<= 8;
221
                                self.bits_left += 8;
222
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
223
224
                            }
225
226
                            return Ok(false);
227
                        }
228
                    }
229
                }
230
            };
231
        }
232
233
234
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
235
2.20G
        if self.bits_left < 32 {
236
340M
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
237
                // found a marker, or we are in EOI
238
                // also we are in over-reading mode, where we fill it with zeroes
239
240
                // fill with zeroes
241
325M
                self.buffer <<= 32;
242
325M
                self.bits_left += 32;
243
325M
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
244
325M
                return Ok(true);
245
15.3M
            }
246
247
248
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
249
            // as it is the common case
250
            //
251
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
252
            // guaranteed not to advance in case of failure (is this true), so
253
            // we revert the read later on (if we have 255), if this fails, we use the normal
254
            // byte at a time read
255
256
15.3M
            if let Ok(bytes) = reader.get_fixed_bytes_or_err::<4>() {
257
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
258
                // create buffer
259
15.3M
                let msb_buf = u32::from_be_bytes(bytes);
260
15.3M
                // check if we have 0xff
261
15.3M
                if !has_byte(msb_buf, 255) {
262
13.9M
                    self.bits_left += 32;
263
13.9M
                    self.buffer <<= 32;
264
13.9M
                    self.buffer |= u64::from(msb_buf);
265
13.9M
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
266
13.9M
                    return Ok(true);
267
1.37M
                }
268
1.37M
269
1.37M
                reader.rewind(4);
270
1.55k
            }
271
            // This serves two reasons,
272
            // 1: Make clippy shut up
273
            // 2: Favour register reuse
274
            let mut byte;
275
            // 4 refills, if all succeed the stream should contain enough bits to decode a
276
            // value
277
1.37M
            refill!(self.buffer, byte, self.bits_left);
278
1.28M
            refill!(self.buffer, byte, self.bits_left);
279
1.02M
            refill!(self.buffer, byte, self.bits_left);
280
980k
            refill!(self.buffer, byte, self.bits_left);
281
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
282
917k
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
283
1.85G
        }
284
1.86G
        return Ok(true);
285
2.20G
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<_>
<zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Line
Count
Source
176
602k
    pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors>
177
602k
    where
178
602k
        T: ZReaderTrait
179
602k
    {
180
        /// Macro version of a single byte refill.
181
        /// Arguments
182
        /// buffer-> our io buffer, because rust macros cannot get values from
183
        /// the surrounding environment bits_left-> number of bits left
184
        /// to full refill
185
        macro_rules! refill {
186
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
187
                // read a byte from the stream
188
                $byte = u64::from(reader.get_u8());
189
                self.overread_by += usize::from(reader.eof());
190
                // append to the buffer
191
                // JPEG is a MSB type buffer so that means we append this
192
                // to the lower end (0..8) of the buffer and push the rest bits above..
193
                $buffer = ($buffer << 8) | $byte;
194
                // Increment bits left
195
                $bits_left += 8;
196
                // Check for special case  of OxFF, to see if it's a stream or a marker
197
                if $byte == 0xff {
198
                    // read next byte
199
                    let mut next_byte = u64::from(reader.get_u8());
200
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
201
                    if next_byte != 0x00 {
202
                        // skip that byte we read
203
                        while next_byte == 0xFF {
204
                            next_byte = u64::from(reader.get_u8());
205
                        }
206
207
                        if next_byte != 0x00 {
208
                            // Undo the byte append and return
209
                            $buffer >>= 8;
210
                            $bits_left -= 8;
211
212
                            if $bits_left != 0 {
213
                                self.aligned_buffer = $buffer << (64 - $bits_left);
214
                            }
215
216
                            self.marker = Marker::from_u8(next_byte as u8);
217
                            if next_byte == 0xD9 {
218
                                // special handling for eoi, fill some bytes,even if its zero,
219
                                // removes some panics
220
                                self.buffer <<= 8;
221
                                self.bits_left += 8;
222
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
223
224
                            }
225
226
                            return Ok(false);
227
                        }
228
                    }
229
                }
230
            };
231
        }
232
233
234
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
235
602k
        if self.bits_left < 32 {
236
58.2k
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
237
                // found a marker, or we are in EOI
238
                // also we are in over-reading mode, where we fill it with zeroes
239
240
                // fill with zeroes
241
56.5k
                self.buffer <<= 32;
242
56.5k
                self.bits_left += 32;
243
56.5k
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
244
56.5k
                return Ok(true);
245
1.75k
            }
246
247
248
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
249
            // as it is the common case
250
            //
251
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
252
            // guaranteed not to advance in case of failure (is this true), so
253
            // we revert the read later on (if we have 255), if this fails, we use the normal
254
            // byte at a time read
255
256
1.75k
            if let Ok(bytes) = reader.get_fixed_bytes_or_err::<4>() {
257
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
258
                // create buffer
259
1.73k
                let msb_buf = u32::from_be_bytes(bytes);
260
1.73k
                // check if we have 0xff
261
1.73k
                if !has_byte(msb_buf, 255) {
262
1.67k
                    self.bits_left += 32;
263
1.67k
                    self.buffer <<= 32;
264
1.67k
                    self.buffer |= u64::from(msb_buf);
265
1.67k
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
266
1.67k
                    return Ok(true);
267
62
                }
268
62
269
62
                reader.rewind(4);
270
13
            }
271
            // This serves two reasons,
272
            // 1: Make clippy shut up
273
            // 2: Favour register reuse
274
            let mut byte;
275
            // 4 refills, if all succeed the stream should contain enough bits to decode a
276
            // value
277
75
            refill!(self.buffer, byte, self.bits_left);
278
70
            refill!(self.buffer, byte, self.bits_left);
279
66
            refill!(self.buffer, byte, self.bits_left);
280
53
            refill!(self.buffer, byte, self.bits_left);
281
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
282
52
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
283
543k
        }
284
544k
        return Ok(true);
285
602k
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Line
Count
Source
176
693M
    pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors>
177
693M
    where
178
693M
        T: ZReaderTrait
179
693M
    {
180
        /// Macro version of a single byte refill.
181
        /// Arguments
182
        /// buffer-> our io buffer, because rust macros cannot get values from
183
        /// the surrounding environment bits_left-> number of bits left
184
        /// to full refill
185
        macro_rules! refill {
186
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
187
                // read a byte from the stream
188
                $byte = u64::from(reader.get_u8());
189
                self.overread_by += usize::from(reader.eof());
190
                // append to the buffer
191
                // JPEG is a MSB type buffer so that means we append this
192
                // to the lower end (0..8) of the buffer and push the rest bits above..
193
                $buffer = ($buffer << 8) | $byte;
194
                // Increment bits left
195
                $bits_left += 8;
196
                // Check for special case  of OxFF, to see if it's a stream or a marker
197
                if $byte == 0xff {
198
                    // read next byte
199
                    let mut next_byte = u64::from(reader.get_u8());
200
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
201
                    if next_byte != 0x00 {
202
                        // skip that byte we read
203
                        while next_byte == 0xFF {
204
                            next_byte = u64::from(reader.get_u8());
205
                        }
206
207
                        if next_byte != 0x00 {
208
                            // Undo the byte append and return
209
                            $buffer >>= 8;
210
                            $bits_left -= 8;
211
212
                            if $bits_left != 0 {
213
                                self.aligned_buffer = $buffer << (64 - $bits_left);
214
                            }
215
216
                            self.marker = Marker::from_u8(next_byte as u8);
217
                            if next_byte == 0xD9 {
218
                                // special handling for eoi, fill some bytes,even if its zero,
219
                                // removes some panics
220
                                self.buffer <<= 8;
221
                                self.bits_left += 8;
222
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
223
224
                            }
225
226
                            return Ok(false);
227
                        }
228
                    }
229
                }
230
            };
231
        }
232
233
234
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
235
693M
        if self.bits_left < 32 {
236
96.3M
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
237
                // found a marker, or we are in EOI
238
                // also we are in over-reading mode, where we fill it with zeroes
239
240
                // fill with zeroes
241
83.7M
                self.buffer <<= 32;
242
83.7M
                self.bits_left += 32;
243
83.7M
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
244
83.7M
                return Ok(true);
245
12.6M
            }
246
247
248
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
249
            // as it is the common case
250
            //
251
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
252
            // guaranteed not to advance in case of failure (is this true), so
253
            // we revert the read later on (if we have 255), if this fails, we use the normal
254
            // byte at a time read
255
256
12.6M
            if let Ok(bytes) = reader.get_fixed_bytes_or_err::<4>() {
257
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
258
                // create buffer
259
12.6M
                let msb_buf = u32::from_be_bytes(bytes);
260
12.6M
                // check if we have 0xff
261
12.6M
                if !has_byte(msb_buf, 255) {
262
11.5M
                    self.bits_left += 32;
263
11.5M
                    self.buffer <<= 32;
264
11.5M
                    self.buffer |= u64::from(msb_buf);
265
11.5M
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
266
11.5M
                    return Ok(true);
267
1.10M
                }
268
1.10M
269
1.10M
                reader.rewind(4);
270
533
            }
271
            // This serves two reasons,
272
            // 1: Make clippy shut up
273
            // 2: Favour register reuse
274
            let mut byte;
275
            // 4 refills, if all succeed the stream should contain enough bits to decode a
276
            // value
277
1.10M
            refill!(self.buffer, byte, self.bits_left);
278
1.05M
            refill!(self.buffer, byte, self.bits_left);
279
816k
            refill!(self.buffer, byte, self.bits_left);
280
780k
            refill!(self.buffer, byte, self.bits_left);
281
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
282
737k
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
283
597M
        }
284
598M
        return Ok(true);
285
693M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
<zune_jpeg::bitstream::BitStream>::refill::<alloc::vec::Vec<u8>>
Line
Count
Source
176
165k
    pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors>
177
165k
    where
178
165k
        T: ZReaderTrait
179
165k
    {
180
        /// Macro version of a single byte refill.
181
        /// Arguments
182
        /// buffer-> our io buffer, because rust macros cannot get values from
183
        /// the surrounding environment bits_left-> number of bits left
184
        /// to full refill
185
        macro_rules! refill {
186
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
187
                // read a byte from the stream
188
                $byte = u64::from(reader.get_u8());
189
                self.overread_by += usize::from(reader.eof());
190
                // append to the buffer
191
                // JPEG is a MSB type buffer so that means we append this
192
                // to the lower end (0..8) of the buffer and push the rest bits above..
193
                $buffer = ($buffer << 8) | $byte;
194
                // Increment bits left
195
                $bits_left += 8;
196
                // Check for special case  of OxFF, to see if it's a stream or a marker
197
                if $byte == 0xff {
198
                    // read next byte
199
                    let mut next_byte = u64::from(reader.get_u8());
200
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
201
                    if next_byte != 0x00 {
202
                        // skip that byte we read
203
                        while next_byte == 0xFF {
204
                            next_byte = u64::from(reader.get_u8());
205
                        }
206
207
                        if next_byte != 0x00 {
208
                            // Undo the byte append and return
209
                            $buffer >>= 8;
210
                            $bits_left -= 8;
211
212
                            if $bits_left != 0 {
213
                                self.aligned_buffer = $buffer << (64 - $bits_left);
214
                            }
215
216
                            self.marker = Marker::from_u8(next_byte as u8);
217
                            if next_byte == 0xD9 {
218
                                // special handling for eoi, fill some bytes,even if its zero,
219
                                // removes some panics
220
                                self.buffer <<= 8;
221
                                self.bits_left += 8;
222
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
223
224
                            }
225
226
                            return Ok(false);
227
                        }
228
                    }
229
                }
230
            };
231
        }
232
233
234
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
235
165k
        if self.bits_left < 32 {
236
20.9k
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
237
                // found a marker, or we are in EOI
238
                // also we are in over-reading mode, where we fill it with zeroes
239
240
                // fill with zeroes
241
20.1k
                self.buffer <<= 32;
242
20.1k
                self.bits_left += 32;
243
20.1k
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
244
20.1k
                return Ok(true);
245
867
            }
246
247
248
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
249
            // as it is the common case
250
            //
251
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
252
            // guaranteed not to advance in case of failure (is this true), so
253
            // we revert the read later on (if we have 255), if this fails, we use the normal
254
            // byte at a time read
255
256
867
            if let Ok(bytes) = reader.get_fixed_bytes_or_err::<4>() {
257
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
258
                // create buffer
259
866
                let msb_buf = u32::from_be_bytes(bytes);
260
866
                // check if we have 0xff
261
866
                if !has_byte(msb_buf, 255) {
262
862
                    self.bits_left += 32;
263
862
                    self.buffer <<= 32;
264
862
                    self.buffer |= u64::from(msb_buf);
265
862
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
266
862
                    return Ok(true);
267
4
                }
268
4
269
4
                reader.rewind(4);
270
1
            }
271
            // This serves two reasons,
272
            // 1: Make clippy shut up
273
            // 2: Favour register reuse
274
            let mut byte;
275
            // 4 refills, if all succeed the stream should contain enough bits to decode a
276
            // value
277
5
            refill!(self.buffer, byte, self.bits_left);
278
5
            refill!(self.buffer, byte, self.bits_left);
279
4
            refill!(self.buffer, byte, self.bits_left);
280
1
            refill!(self.buffer, byte, self.bits_left);
281
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
282
1
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
283
144k
        }
284
144k
        return Ok(true);
285
165k
    }
<zune_jpeg::bitstream::BitStream>::refill::<&[u8]>
Line
Count
Source
176
1.50G
    pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors>
177
1.50G
    where
178
1.50G
        T: ZReaderTrait
179
1.50G
    {
180
        /// Macro version of a single byte refill.
181
        /// Arguments
182
        /// buffer-> our io buffer, because rust macros cannot get values from
183
        /// the surrounding environment bits_left-> number of bits left
184
        /// to full refill
185
        macro_rules! refill {
186
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
187
                // read a byte from the stream
188
                $byte = u64::from(reader.get_u8());
189
                self.overread_by += usize::from(reader.eof());
190
                // append to the buffer
191
                // JPEG is a MSB type buffer so that means we append this
192
                // to the lower end (0..8) of the buffer and push the rest bits above..
193
                $buffer = ($buffer << 8) | $byte;
194
                // Increment bits left
195
                $bits_left += 8;
196
                // Check for special case  of OxFF, to see if it's a stream or a marker
197
                if $byte == 0xff {
198
                    // read next byte
199
                    let mut next_byte = u64::from(reader.get_u8());
200
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
201
                    if next_byte != 0x00 {
202
                        // skip that byte we read
203
                        while next_byte == 0xFF {
204
                            next_byte = u64::from(reader.get_u8());
205
                        }
206
207
                        if next_byte != 0x00 {
208
                            // Undo the byte append and return
209
                            $buffer >>= 8;
210
                            $bits_left -= 8;
211
212
                            if $bits_left != 0 {
213
                                self.aligned_buffer = $buffer << (64 - $bits_left);
214
                            }
215
216
                            self.marker = Marker::from_u8(next_byte as u8);
217
                            if next_byte == 0xD9 {
218
                                // special handling for eoi, fill some bytes,even if its zero,
219
                                // removes some panics
220
                                self.buffer <<= 8;
221
                                self.bits_left += 8;
222
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
223
224
                            }
225
226
                            return Ok(false);
227
                        }
228
                    }
229
                }
230
            };
231
        }
232
233
234
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
235
1.50G
        if self.bits_left < 32 {
236
244M
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
237
                // found a marker, or we are in EOI
238
                // also we are in over-reading mode, where we fill it with zeroes
239
240
                // fill with zeroes
241
241M
                self.buffer <<= 32;
242
241M
                self.bits_left += 32;
243
241M
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
244
241M
                return Ok(true);
245
2.71M
            }
246
247
248
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
249
            // as it is the common case
250
            //
251
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
252
            // guaranteed not to advance in case of failure (is this true), so
253
            // we revert the read later on (if we have 255), if this fails, we use the normal
254
            // byte at a time read
255
256
2.71M
            if let Ok(bytes) = reader.get_fixed_bytes_or_err::<4>() {
257
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
258
                // create buffer
259
2.71M
                let msb_buf = u32::from_be_bytes(bytes);
260
2.71M
                // check if we have 0xff
261
2.71M
                if !has_byte(msb_buf, 255) {
262
2.43M
                    self.bits_left += 32;
263
2.43M
                    self.buffer <<= 32;
264
2.43M
                    self.buffer |= u64::from(msb_buf);
265
2.43M
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
266
2.43M
                    return Ok(true);
267
275k
                }
268
275k
269
275k
                reader.rewind(4);
270
1.00k
            }
271
            // This serves two reasons,
272
            // 1: Make clippy shut up
273
            // 2: Favour register reuse
274
            let mut byte;
275
            // 4 refills, if all succeed the stream should contain enough bits to decode a
276
            // value
277
276k
            refill!(self.buffer, byte, self.bits_left);
278
231k
            refill!(self.buffer, byte, self.bits_left);
279
213k
            refill!(self.buffer, byte, self.bits_left);
280
199k
            refill!(self.buffer, byte, self.bits_left);
281
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
282
179k
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
283
1.26G
        }
284
1.26G
        return Ok(true);
285
1.50G
    }
286
    /// Decode the DC coefficient in a MCU block.
287
    ///
288
    /// The decoded coefficient is written to `dc_prediction`
289
    ///
290
    #[allow(
291
        clippy::cast_possible_truncation,
292
        clippy::cast_sign_loss,
293
        clippy::unwrap_used
294
    )]
295
    #[inline(always)]
296
163M
    fn decode_dc<T>(
297
163M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
298
163M
    ) -> Result<bool, DecodeErrors>
299
163M
    where
300
163M
        T: ZReaderTrait
301
163M
    {
302
163M
        let (mut symbol, r);
303
163M
304
163M
        if self.bits_left < 32 {
305
24.6M
            self.refill(reader)?;
306
138M
        };
307
        // look a head HUFF_LOOKAHEAD bits into the bitstream
308
163M
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
309
163M
        symbol = dc_table.lookup[symbol as usize];
310
163M
311
163M
        decode_huff!(self, symbol, dc_table);
312
313
163M
        if symbol != 0 {
314
62.8M
            r = self.get_bits(symbol as u8);
315
62.8M
            symbol = huff_extend(r, symbol);
316
100M
        }
317
        // Update DC prediction
318
163M
        *dc_prediction = dc_prediction.wrapping_add(symbol);
319
163M
320
163M
        return Ok(true);
321
163M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<_>
<zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Line
Count
Source
296
10.4k
    fn decode_dc<T>(
297
10.4k
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
298
10.4k
    ) -> Result<bool, DecodeErrors>
299
10.4k
    where
300
10.4k
        T: ZReaderTrait
301
10.4k
    {
302
10.4k
        let (mut symbol, r);
303
10.4k
304
10.4k
        if self.bits_left < 32 {
305
1.05k
            self.refill(reader)?;
306
9.44k
        };
307
        // look a head HUFF_LOOKAHEAD bits into the bitstream
308
10.4k
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
309
10.4k
        symbol = dc_table.lookup[symbol as usize];
310
10.4k
311
10.4k
        decode_huff!(self, symbol, dc_table);
312
313
10.4k
        if symbol != 0 {
314
9.53k
            r = self.get_bits(symbol as u8);
315
9.53k
            symbol = huff_extend(r, symbol);
316
9.53k
        }
317
        // Update DC prediction
318
10.4k
        *dc_prediction = dc_prediction.wrapping_add(symbol);
319
10.4k
320
10.4k
        return Ok(true);
321
10.4k
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Line
Count
Source
296
72.2M
    fn decode_dc<T>(
297
72.2M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
298
72.2M
    ) -> Result<bool, DecodeErrors>
299
72.2M
    where
300
72.2M
        T: ZReaderTrait
301
72.2M
    {
302
72.2M
        let (mut symbol, r);
303
72.2M
304
72.2M
        if self.bits_left < 32 {
305
5.77M
            self.refill(reader)?;
306
66.4M
        };
307
        // look a head HUFF_LOOKAHEAD bits into the bitstream
308
72.2M
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
309
72.2M
        symbol = dc_table.lookup[symbol as usize];
310
72.2M
311
72.2M
        decode_huff!(self, symbol, dc_table);
312
313
72.2M
        if symbol != 0 {
314
5.56M
            r = self.get_bits(symbol as u8);
315
5.56M
            symbol = huff_extend(r, symbol);
316
66.6M
        }
317
        // Update DC prediction
318
72.2M
        *dc_prediction = dc_prediction.wrapping_add(symbol);
319
72.2M
320
72.2M
        return Ok(true);
321
72.2M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
<zune_jpeg::bitstream::BitStream>::decode_dc::<alloc::vec::Vec<u8>>
Line
Count
Source
296
4.20k
    fn decode_dc<T>(
297
4.20k
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
298
4.20k
    ) -> Result<bool, DecodeErrors>
299
4.20k
    where
300
4.20k
        T: ZReaderTrait
301
4.20k
    {
302
4.20k
        let (mut symbol, r);
303
4.20k
304
4.20k
        if self.bits_left < 32 {
305
544
            self.refill(reader)?;
306
3.66k
        };
307
        // look a head HUFF_LOOKAHEAD bits into the bitstream
308
4.20k
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
309
4.20k
        symbol = dc_table.lookup[symbol as usize];
310
4.20k
311
4.20k
        decode_huff!(self, symbol, dc_table);
312
313
4.20k
        if symbol != 0 {
314
63
            r = self.get_bits(symbol as u8);
315
63
            symbol = huff_extend(r, symbol);
316
4.14k
        }
317
        // Update DC prediction
318
4.20k
        *dc_prediction = dc_prediction.wrapping_add(symbol);
319
4.20k
320
4.20k
        return Ok(true);
321
4.20k
    }
<zune_jpeg::bitstream::BitStream>::decode_dc::<&[u8]>
Line
Count
Source
296
90.8M
    fn decode_dc<T>(
297
90.8M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
298
90.8M
    ) -> Result<bool, DecodeErrors>
299
90.8M
    where
300
90.8M
        T: ZReaderTrait
301
90.8M
    {
302
90.8M
        let (mut symbol, r);
303
90.8M
304
90.8M
        if self.bits_left < 32 {
305
18.8M
            self.refill(reader)?;
306
72.0M
        };
307
        // look a head HUFF_LOOKAHEAD bits into the bitstream
308
90.8M
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
309
90.8M
        symbol = dc_table.lookup[symbol as usize];
310
90.8M
311
90.8M
        decode_huff!(self, symbol, dc_table);
312
313
90.8M
        if symbol != 0 {
314
57.2M
            r = self.get_bits(symbol as u8);
315
57.2M
            symbol = huff_extend(r, symbol);
316
57.2M
        }
317
        // Update DC prediction
318
90.8M
        *dc_prediction = dc_prediction.wrapping_add(symbol);
319
90.8M
320
90.8M
        return Ok(true);
321
90.8M
    }
322
323
    /// Decode a Minimum Code Unit(MCU) as quickly as possible
324
    ///
325
    /// # Arguments
326
    /// - reader: The bitstream from where we read more bits.
327
    /// - dc_table: The Huffman table used to decode the DC coefficient
328
    /// - ac_table: The Huffman table used to decode AC values
329
    /// - block: A memory region where we will write out the decoded values
330
    /// - DC prediction: Last DC value for this component
331
    ///
332
    #[allow(
333
        clippy::many_single_char_names,
334
        clippy::cast_possible_truncation,
335
        clippy::cast_sign_loss
336
    )]
337
    #[inline(never)]
338
53.4M
    pub fn decode_mcu_block<T>(
339
53.4M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
340
53.4M
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
341
53.4M
    ) -> Result<(), DecodeErrors>
342
53.4M
    where
343
53.4M
        T: ZReaderTrait
344
53.4M
    {
345
53.4M
        // Get fast AC table as a reference before we enter the hot path
346
53.4M
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
347
53.4M
348
53.4M
        let (mut symbol, mut r, mut fast_ac);
349
53.4M
        // Decode AC coefficients
350
53.4M
        let mut pos: usize = 1;
351
53.4M
352
53.4M
        // decode DC, dc prediction will contain the value
353
53.4M
        self.decode_dc(reader, dc_table, dc_prediction)?;
354
355
        // set dc to be the dc prediction.
356
53.4M
        block[0] = *dc_prediction * qt_table[0];
357
358
1.19G
        while pos < 64 {
359
1.18G
            self.refill(reader)?;
360
1.18G
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
361
1.18G
            fast_ac = ac_lookup[symbol as usize];
362
1.18G
            symbol = ac_table.lookup[symbol as usize];
363
1.18G
364
1.18G
            if fast_ac != 0 {
365
1.12G
                //  FAST AC path
366
1.12G
                pos += ((fast_ac >> 4) & 15) as usize; // run
367
1.12G
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
368
1.12G
369
1.12G
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
370
1.12G
                self.drop_bits((fast_ac & 15) as u8);
371
1.12G
                pos += 1;
372
1.12G
            } else {
373
55.7M
                decode_huff!(self, symbol, ac_table);
374
375
55.7M
                r = symbol >> 4;
376
55.7M
                symbol &= 15;
377
55.7M
378
55.7M
                if symbol != 0 {
379
20.6M
                    pos += r as usize;
380
20.6M
                    r = self.get_bits(symbol as u8);
381
20.6M
                    symbol = huff_extend(r, symbol);
382
20.6M
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
383
20.6M
384
20.6M
                    block[t_pos] = symbol * qt_table[t_pos];
385
20.6M
386
20.6M
                    pos += 1;
387
35.1M
                } else if r != 15 {
388
35.0M
                    return Ok(());
389
74.2k
                } else {
390
74.2k
                    pos += 16;
391
74.2k
                }
392
            }
393
        }
394
18.3M
        return Ok(());
395
53.4M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<_>
<zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Line
Count
Source
338
10.4k
    pub fn decode_mcu_block<T>(
339
10.4k
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
340
10.4k
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
341
10.4k
    ) -> Result<(), DecodeErrors>
342
10.4k
    where
343
10.4k
        T: ZReaderTrait
344
10.4k
    {
345
10.4k
        // Get fast AC table as a reference before we enter the hot path
346
10.4k
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
347
10.4k
348
10.4k
        let (mut symbol, mut r, mut fast_ac);
349
10.4k
        // Decode AC coefficients
350
10.4k
        let mut pos: usize = 1;
351
10.4k
352
10.4k
        // decode DC, dc prediction will contain the value
353
10.4k
        self.decode_dc(reader, dc_table, dc_prediction)?;
354
355
        // set dc to be the dc prediction.
356
10.4k
        block[0] = *dc_prediction * qt_table[0];
357
358
610k
        while pos < 64 {
359
601k
            self.refill(reader)?;
360
601k
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
361
601k
            fast_ac = ac_lookup[symbol as usize];
362
601k
            symbol = ac_table.lookup[symbol as usize];
363
601k
364
601k
            if fast_ac != 0 {
365
599k
                //  FAST AC path
366
599k
                pos += ((fast_ac >> 4) & 15) as usize; // run
367
599k
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
368
599k
369
599k
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
370
599k
                self.drop_bits((fast_ac & 15) as u8);
371
599k
                pos += 1;
372
599k
            } else {
373
1.50k
                decode_huff!(self, symbol, ac_table);
374
375
1.50k
                r = symbol >> 4;
376
1.50k
                symbol &= 15;
377
1.50k
378
1.50k
                if symbol != 0 {
379
467
                    pos += r as usize;
380
467
                    r = self.get_bits(symbol as u8);
381
467
                    symbol = huff_extend(r, symbol);
382
467
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
383
467
384
467
                    block[t_pos] = symbol * qt_table[t_pos];
385
467
386
467
                    pos += 1;
387
1.04k
                } else if r != 15 {
388
1.03k
                    return Ok(());
389
9
                } else {
390
9
                    pos += 16;
391
9
                }
392
            }
393
        }
394
9.46k
        return Ok(());
395
10.4k
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Line
Count
Source
338
31.2M
    pub fn decode_mcu_block<T>(
339
31.2M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
340
31.2M
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
341
31.2M
    ) -> Result<(), DecodeErrors>
342
31.2M
    where
343
31.2M
        T: ZReaderTrait
344
31.2M
    {
345
31.2M
        // Get fast AC table as a reference before we enter the hot path
346
31.2M
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
347
31.2M
348
31.2M
        let (mut symbol, mut r, mut fast_ac);
349
31.2M
        // Decode AC coefficients
350
31.2M
        let mut pos: usize = 1;
351
31.2M
352
31.2M
        // decode DC, dc prediction will contain the value
353
31.2M
        self.decode_dc(reader, dc_table, dc_prediction)?;
354
355
        // set dc to be the dc prediction.
356
31.2M
        block[0] = *dc_prediction * qt_table[0];
357
358
334M
        while pos < 64 {
359
330M
            self.refill(reader)?;
360
330M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
361
330M
            fast_ac = ac_lookup[symbol as usize];
362
330M
            symbol = ac_table.lookup[symbol as usize];
363
330M
364
330M
            if fast_ac != 0 {
365
301M
                //  FAST AC path
366
301M
                pos += ((fast_ac >> 4) & 15) as usize; // run
367
301M
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
368
301M
369
301M
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
370
301M
                self.drop_bits((fast_ac & 15) as u8);
371
301M
                pos += 1;
372
301M
            } else {
373
28.8M
                decode_huff!(self, symbol, ac_table);
374
375
28.8M
                r = symbol >> 4;
376
28.8M
                symbol &= 15;
377
28.8M
378
28.8M
                if symbol != 0 {
379
2.11M
                    pos += r as usize;
380
2.11M
                    r = self.get_bits(symbol as u8);
381
2.11M
                    symbol = huff_extend(r, symbol);
382
2.11M
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
383
2.11M
384
2.11M
                    block[t_pos] = symbol * qt_table[t_pos];
385
2.11M
386
2.11M
                    pos += 1;
387
26.7M
                } else if r != 15 {
388
26.7M
                    return Ok(());
389
32.9k
                } else {
390
32.9k
                    pos += 16;
391
32.9k
                }
392
            }
393
        }
394
4.52M
        return Ok(());
395
31.2M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
<zune_jpeg::bitstream::BitStream>::decode_mcu_block::<alloc::vec::Vec<u8>>
Line
Count
Source
338
4.20k
    pub fn decode_mcu_block<T>(
339
4.20k
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
340
4.20k
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
341
4.20k
    ) -> Result<(), DecodeErrors>
342
4.20k
    where
343
4.20k
        T: ZReaderTrait
344
4.20k
    {
345
4.20k
        // Get fast AC table as a reference before we enter the hot path
346
4.20k
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
347
4.20k
348
4.20k
        let (mut symbol, mut r, mut fast_ac);
349
4.20k
        // Decode AC coefficients
350
4.20k
        let mut pos: usize = 1;
351
4.20k
352
4.20k
        // decode DC, dc prediction will contain the value
353
4.20k
        self.decode_dc(reader, dc_table, dc_prediction)?;
354
355
        // set dc to be the dc prediction.
356
4.20k
        block[0] = *dc_prediction * qt_table[0];
357
358
167k
        while pos < 64 {
359
164k
            self.refill(reader)?;
360
164k
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
361
164k
            fast_ac = ac_lookup[symbol as usize];
362
164k
            symbol = ac_table.lookup[symbol as usize];
363
164k
364
164k
            if fast_ac != 0 {
365
163k
                //  FAST AC path
366
163k
                pos += ((fast_ac >> 4) & 15) as usize; // run
367
163k
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
368
163k
369
163k
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
370
163k
                self.drop_bits((fast_ac & 15) as u8);
371
163k
                pos += 1;
372
163k
            } else {
373
1.63k
                decode_huff!(self, symbol, ac_table);
374
375
1.63k
                r = symbol >> 4;
376
1.63k
                symbol &= 15;
377
1.63k
378
1.63k
                if symbol != 0 {
379
8
                    pos += r as usize;
380
8
                    r = self.get_bits(symbol as u8);
381
8
                    symbol = huff_extend(r, symbol);
382
8
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
383
8
384
8
                    block[t_pos] = symbol * qt_table[t_pos];
385
8
386
8
                    pos += 1;
387
1.62k
                } else if r != 15 {
388
1.62k
                    return Ok(());
389
0
                } else {
390
0
                    pos += 16;
391
0
                }
392
            }
393
        }
394
2.58k
        return Ok(());
395
4.20k
    }
<zune_jpeg::bitstream::BitStream>::decode_mcu_block::<&[u8]>
Line
Count
Source
338
22.1M
    pub fn decode_mcu_block<T>(
339
22.1M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
340
22.1M
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
341
22.1M
    ) -> Result<(), DecodeErrors>
342
22.1M
    where
343
22.1M
        T: ZReaderTrait
344
22.1M
    {
345
22.1M
        // Get fast AC table as a reference before we enter the hot path
346
22.1M
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
347
22.1M
348
22.1M
        let (mut symbol, mut r, mut fast_ac);
349
22.1M
        // Decode AC coefficients
350
22.1M
        let mut pos: usize = 1;
351
22.1M
352
22.1M
        // decode DC, dc prediction will contain the value
353
22.1M
        self.decode_dc(reader, dc_table, dc_prediction)?;
354
355
        // set dc to be the dc prediction.
356
22.1M
        block[0] = *dc_prediction * qt_table[0];
357
358
864M
        while pos < 64 {
359
850M
            self.refill(reader)?;
360
850M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
361
850M
            fast_ac = ac_lookup[symbol as usize];
362
850M
            symbol = ac_table.lookup[symbol as usize];
363
850M
364
850M
            if fast_ac != 0 {
365
823M
                //  FAST AC path
366
823M
                pos += ((fast_ac >> 4) & 15) as usize; // run
367
823M
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
368
823M
369
823M
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
370
823M
                self.drop_bits((fast_ac & 15) as u8);
371
823M
                pos += 1;
372
823M
            } else {
373
26.8M
                decode_huff!(self, symbol, ac_table);
374
375
26.8M
                r = symbol >> 4;
376
26.8M
                symbol &= 15;
377
26.8M
378
26.8M
                if symbol != 0 {
379
18.4M
                    pos += r as usize;
380
18.4M
                    r = self.get_bits(symbol as u8);
381
18.4M
                    symbol = huff_extend(r, symbol);
382
18.4M
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
383
18.4M
384
18.4M
                    block[t_pos] = symbol * qt_table[t_pos];
385
18.4M
386
18.4M
                    pos += 1;
387
18.4M
                } else if r != 15 {
388
8.34M
                    return Ok(());
389
41.2k
                } else {
390
41.2k
                    pos += 16;
391
41.2k
                }
392
            }
393
        }
394
13.8M
        return Ok(());
395
22.1M
    }
396
397
    /// Peek `look_ahead` bits ahead without discarding them from the buffer
398
    #[inline(always)]
399
    #[allow(clippy::cast_possible_truncation)]
400
2.26G
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
2.26G
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
2.26G
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<_>
<zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Line
Count
Source
400
105
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
105
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
105
    }
<zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Line
Count
Source
400
611k
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
611k
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
611k
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
<zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Line
Count
Source
400
324k
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
324k
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
324k
    }
<zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Line
Count
Source
400
742M
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
742M
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
742M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9>
<zune_jpeg::bitstream::BitStream>::peek_bits::<16>
Line
Count
Source
400
190k
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
190k
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
190k
    }
<zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Line
Count
Source
400
1.52G
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
401
1.52G
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
402
1.52G
    }
403
404
    /// Discard the next `N` bits without checking
405
    #[inline]
406
4.09G
    fn drop_bits(&mut self, n: u8) {
407
4.09G
        debug_assert!(self.bits_left >= n);
408
        //self.bits_left -= n;
409
4.09G
        self.bits_left = self.bits_left.saturating_sub(n);
410
4.09G
        self.aligned_buffer <<= n;
411
4.09G
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
<zune_jpeg::bitstream::BitStream>::drop_bits
Line
Count
Source
406
1.82G
    fn drop_bits(&mut self, n: u8) {
407
1.82G
        debug_assert!(self.bits_left >= n);
408
        //self.bits_left -= n;
409
1.82G
        self.bits_left = self.bits_left.saturating_sub(n);
410
1.82G
        self.aligned_buffer <<= n;
411
1.82G
    }
<zune_jpeg::bitstream::BitStream>::drop_bits
Line
Count
Source
406
611k
    fn drop_bits(&mut self, n: u8) {
407
611k
        debug_assert!(self.bits_left >= n);
408
        //self.bits_left -= n;
409
611k
        self.bits_left = self.bits_left.saturating_sub(n);
410
611k
        self.aligned_buffer <<= n;
411
611k
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
<zune_jpeg::bitstream::BitStream>::drop_bits
Line
Count
Source
406
742M
    fn drop_bits(&mut self, n: u8) {
407
742M
        debug_assert!(self.bits_left >= n);
408
        //self.bits_left -= n;
409
742M
        self.bits_left = self.bits_left.saturating_sub(n);
410
742M
        self.aligned_buffer <<= n;
411
742M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
<zune_jpeg::bitstream::BitStream>::drop_bits
Line
Count
Source
406
1.52G
    fn drop_bits(&mut self, n: u8) {
407
1.52G
        debug_assert!(self.bits_left >= n);
408
        //self.bits_left -= n;
409
1.52G
        self.bits_left = self.bits_left.saturating_sub(n);
410
1.52G
        self.aligned_buffer <<= n;
411
1.52G
    }
412
413
    /// Read `n_bits` from the buffer  and discard them
414
    #[inline(always)]
415
    #[allow(clippy::cast_possible_truncation)]
416
323M
    fn get_bits(&mut self, n_bits: u8) -> i32 {
417
323M
        let mask = (1_u64 << n_bits) - 1;
418
323M
419
323M
        self.aligned_buffer = self.aligned_buffer.rotate_left(u32::from(n_bits));
420
323M
        let bits = (self.aligned_buffer & mask) as i32;
421
323M
        self.bits_left = self.bits_left.wrapping_sub(n_bits);
422
323M
        bits
423
323M
    }
424
425
    /// Decode a DC block
426
    #[allow(clippy::cast_possible_truncation)]
427
    #[inline]
428
109M
    pub(crate) fn decode_prog_dc_first<T>(
429
109M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, block: &mut i16,
430
109M
        dc_prediction: &mut i32
431
109M
    ) -> Result<(), DecodeErrors>
432
109M
    where
433
109M
        T: ZReaderTrait
434
109M
    {
435
109M
        self.decode_dc(reader, dc_table, dc_prediction)?;
436
109M
        *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low);
437
109M
        return Ok(());
438
109M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Line
Count
Source
428
40.9M
    pub(crate) fn decode_prog_dc_first<T>(
429
40.9M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, block: &mut i16,
430
40.9M
        dc_prediction: &mut i32
431
40.9M
    ) -> Result<(), DecodeErrors>
432
40.9M
    where
433
40.9M
        T: ZReaderTrait
434
40.9M
    {
435
40.9M
        self.decode_dc(reader, dc_table, dc_prediction)?;
436
40.9M
        *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low);
437
40.9M
        return Ok(());
438
40.9M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<&[u8]>
Line
Count
Source
428
68.6M
    pub(crate) fn decode_prog_dc_first<T>(
429
68.6M
        &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, block: &mut i16,
430
68.6M
        dc_prediction: &mut i32
431
68.6M
    ) -> Result<(), DecodeErrors>
432
68.6M
    where
433
68.6M
        T: ZReaderTrait
434
68.6M
    {
435
68.6M
        self.decode_dc(reader, dc_table, dc_prediction)?;
436
68.6M
        *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low);
437
68.6M
        return Ok(());
438
68.6M
    }
439
    #[inline]
440
238M
    pub(crate) fn decode_prog_dc_refine<T>(
441
238M
        &mut self, reader: &mut ZByteReader<T>, block: &mut i16
442
238M
    ) -> Result<(), DecodeErrors>
443
238M
    where
444
238M
        T: ZReaderTrait
445
238M
    {
446
238M
        // refinement scan
447
238M
        if self.bits_left < 1 {
448
7.45M
            self.refill(reader)?;
449
230M
        }
450
451
238M
        if self.get_bit() == 1 {
452
8.42M
            *block = block.wrapping_add(1 << self.successive_low);
453
229M
        }
454
455
238M
        Ok(())
456
238M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Line
Count
Source
440
30.1M
    pub(crate) fn decode_prog_dc_refine<T>(
441
30.1M
        &mut self, reader: &mut ZByteReader<T>, block: &mut i16
442
30.1M
    ) -> Result<(), DecodeErrors>
443
30.1M
    where
444
30.1M
        T: ZReaderTrait
445
30.1M
    {
446
30.1M
        // refinement scan
447
30.1M
        if self.bits_left < 1 {
448
950k
            self.refill(reader)?;
449
29.2M
        }
450
451
30.1M
        if self.get_bit() == 1 {
452
3.48M
            *block = block.wrapping_add(1 << self.successive_low);
453
26.6M
        }
454
455
30.1M
        Ok(())
456
30.1M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<&[u8]>
Line
Count
Source
440
207M
    pub(crate) fn decode_prog_dc_refine<T>(
441
207M
        &mut self, reader: &mut ZByteReader<T>, block: &mut i16
442
207M
    ) -> Result<(), DecodeErrors>
443
207M
    where
444
207M
        T: ZReaderTrait
445
207M
    {
446
207M
        // refinement scan
447
207M
        if self.bits_left < 1 {
448
6.50M
            self.refill(reader)?;
449
201M
        }
450
451
207M
        if self.get_bit() == 1 {
452
4.93M
            *block = block.wrapping_add(1 << self.successive_low);
453
202M
        }
454
455
207M
        Ok(())
456
207M
    }
457
458
    /// Get a single bit from the bitstream
459
1.82G
    fn get_bit(&mut self) -> u8 {
460
1.82G
        let k = (self.aligned_buffer >> 63) as u8;
461
1.82G
        // discard a bit
462
1.82G
        self.drop_bits(1);
463
1.82G
        return k;
464
1.82G
    }
465
117M
    pub(crate) fn decode_mcu_ac_first<T>(
466
117M
        &mut self, reader: &mut ZByteReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64]
467
117M
    ) -> Result<bool, DecodeErrors>
468
117M
    where
469
117M
        T: ZReaderTrait
470
117M
    {
471
117M
        let shift = self.successive_low;
472
117M
        let fast_ac = ac_table.ac_lookup.as_ref().unwrap();
473
117M
474
117M
        let mut k = self.spec_start as usize;
475
        let (mut symbol, mut r, mut fac);
476
477
        // EOB runs are handled in mcu_prog.rs
478
        'block: loop {
479
528M
            self.refill(reader)?;
480
481
528M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
482
528M
            fac = fast_ac[symbol as usize];
483
528M
            symbol = ac_table.lookup[symbol as usize];
484
528M
485
528M
            if fac != 0 {
486
359M
                // fast ac path
487
359M
                k += ((fac >> 4) & 15) as usize; // run
488
359M
                block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value
489
359M
                self.drop_bits((fac & 15) as u8);
490
359M
                k += 1;
491
359M
            } else {
492
168M
                decode_huff!(self, symbol, ac_table);
493
494
168M
                r = symbol >> 4;
495
168M
                symbol &= 15;
496
168M
497
168M
                if symbol != 0 {
498
147M
                    k += r as usize;
499
147M
                    r = self.get_bits(symbol as u8);
500
147M
                    symbol = huff_extend(r, symbol);
501
147M
                    block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift);
502
147M
                    k += 1;
503
147M
                } else {
504
20.8M
                    if r != 15 {
505
20.7M
                        self.eob_run = 1 << r;
506
20.7M
                        self.eob_run += self.get_bits(r as u8);
507
20.7M
                        self.eob_run -= 1;
508
20.7M
                        break;
509
12.9k
                    }
510
12.9k
511
12.9k
                    k += 16;
512
                }
513
            }
514
515
507M
            if k > self.spec_end as usize {
516
96.3M
                break 'block;
517
410M
            }
518
        }
519
117M
        return Ok(true);
520
117M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Line
Count
Source
465
24.2M
    pub(crate) fn decode_mcu_ac_first<T>(
466
24.2M
        &mut self, reader: &mut ZByteReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64]
467
24.2M
    ) -> Result<bool, DecodeErrors>
468
24.2M
    where
469
24.2M
        T: ZReaderTrait
470
24.2M
    {
471
24.2M
        let shift = self.successive_low;
472
24.2M
        let fast_ac = ac_table.ac_lookup.as_ref().unwrap();
473
24.2M
474
24.2M
        let mut k = self.spec_start as usize;
475
        let (mut symbol, mut r, mut fac);
476
477
        // EOB runs are handled in mcu_prog.rs
478
        'block: loop {
479
148M
            self.refill(reader)?;
480
481
148M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
482
148M
            fac = fast_ac[symbol as usize];
483
148M
            symbol = ac_table.lookup[symbol as usize];
484
148M
485
148M
            if fac != 0 {
486
129M
                // fast ac path
487
129M
                k += ((fac >> 4) & 15) as usize; // run
488
129M
                block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value
489
129M
                self.drop_bits((fac & 15) as u8);
490
129M
                k += 1;
491
129M
            } else {
492
18.8M
                decode_huff!(self, symbol, ac_table);
493
494
18.8M
                r = symbol >> 4;
495
18.8M
                symbol &= 15;
496
18.8M
497
18.8M
                if symbol != 0 {
498
341k
                    k += r as usize;
499
341k
                    r = self.get_bits(symbol as u8);
500
341k
                    symbol = huff_extend(r, symbol);
501
341k
                    block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift);
502
341k
                    k += 1;
503
341k
                } else {
504
18.4M
                    if r != 15 {
505
18.4M
                        self.eob_run = 1 << r;
506
18.4M
                        self.eob_run += self.get_bits(r as u8);
507
18.4M
                        self.eob_run -= 1;
508
18.4M
                        break;
509
11.6k
                    }
510
11.6k
511
11.6k
                    k += 16;
512
                }
513
            }
514
515
130M
            if k > self.spec_end as usize {
516
5.73M
                break 'block;
517
124M
            }
518
        }
519
24.2M
        return Ok(true);
520
24.2M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<&[u8]>
Line
Count
Source
465
92.9M
    pub(crate) fn decode_mcu_ac_first<T>(
466
92.9M
        &mut self, reader: &mut ZByteReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64]
467
92.9M
    ) -> Result<bool, DecodeErrors>
468
92.9M
    where
469
92.9M
        T: ZReaderTrait
470
92.9M
    {
471
92.9M
        let shift = self.successive_low;
472
92.9M
        let fast_ac = ac_table.ac_lookup.as_ref().unwrap();
473
92.9M
474
92.9M
        let mut k = self.spec_start as usize;
475
        let (mut symbol, mut r, mut fac);
476
477
        // EOB runs are handled in mcu_prog.rs
478
        'block: loop {
479
379M
            self.refill(reader)?;
480
481
379M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
482
379M
            fac = fast_ac[symbol as usize];
483
379M
            symbol = ac_table.lookup[symbol as usize];
484
379M
485
379M
            if fac != 0 {
486
229M
                // fast ac path
487
229M
                k += ((fac >> 4) & 15) as usize; // run
488
229M
                block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value
489
229M
                self.drop_bits((fac & 15) as u8);
490
229M
                k += 1;
491
229M
            } else {
492
149M
                decode_huff!(self, symbol, ac_table);
493
494
149M
                r = symbol >> 4;
495
149M
                symbol &= 15;
496
149M
497
149M
                if symbol != 0 {
498
147M
                    k += r as usize;
499
147M
                    r = self.get_bits(symbol as u8);
500
147M
                    symbol = huff_extend(r, symbol);
501
147M
                    block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift);
502
147M
                    k += 1;
503
147M
                } else {
504
2.31M
                    if r != 15 {
505
2.31M
                        self.eob_run = 1 << r;
506
2.31M
                        self.eob_run += self.get_bits(r as u8);
507
2.31M
                        self.eob_run -= 1;
508
2.31M
                        break;
509
1.33k
                    }
510
1.33k
511
1.33k
                    k += 16;
512
                }
513
            }
514
515
377M
            if k > self.spec_end as usize {
516
90.5M
                break 'block;
517
286M
            }
518
        }
519
92.9M
        return Ok(true);
520
92.9M
    }
521
    #[allow(clippy::too_many_lines, clippy::op_ref)]
522
153M
    pub(crate) fn decode_mcu_ac_refine<T>(
523
153M
        &mut self, reader: &mut ZByteReader<T>, table: &HuffmanTable, block: &mut [i16; 64]
524
153M
    ) -> Result<bool, DecodeErrors>
525
153M
    where
526
153M
        T: ZReaderTrait
527
153M
    {
528
153M
        let bit = (1 << self.successive_low) as i16;
529
153M
530
153M
        let mut k = self.spec_start;
531
153M
        let (mut symbol, mut r);
532
153M
533
153M
        if self.eob_run == 0 {
534
            'no_eob: loop {
535
                // Decode a coefficient from the bit stream
536
396M
                self.refill(reader)?;
537
538
396M
                symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
539
396M
                symbol = table.lookup[symbol as usize];
540
396M
541
396M
                decode_huff!(self, symbol, table);
542
543
396M
                r = symbol >> 4;
544
396M
                symbol &= 15;
545
396M
546
396M
                if symbol == 0 {
547
71.1M
                    if r != 15 {
548
                        // EOB run is 2^r + bits
549
71.1M
                        self.eob_run = 1 << r;
550
71.1M
                        self.eob_run += self.get_bits(r as u8);
551
71.1M
                        // EOB runs are handled by the eob logic
552
71.1M
                        break 'no_eob;
553
3.15k
                    }
554
                } else {
555
325M
                    if symbol != 1 {
556
132
                        return Err(DecodeErrors::HuffmanDecode(
557
132
                            "Bad Huffman code, corrupt JPEG?".to_string()
558
132
                        ));
559
325M
                    }
560
325M
                    // get sign bit
561
325M
                    // We assume we have enough bits, which should be correct for sane images
562
325M
                    // since we refill by 32 above
563
325M
                    if self.get_bit() == 1 {
564
940k
                        symbol = i32::from(bit);
565
324M
                    } else {
566
324M
                        symbol = i32::from(-bit);
567
324M
                    }
568
                }
569
570
                // Advance over already nonzero coefficients  appending
571
                // correction bits to the non-zeroes.
572
                // A correction bit is 1 if the absolute value of the coefficient must be increased
573
574
325M
                if k <= self.spec_end {
575
                    'advance_nonzero: loop {
576
1.50G
                        let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
577
1.50G
578
1.50G
                        if *coefficient != 0 {
579
1.18G
                            if self.get_bit() == 1 && (*coefficient & bit) == 0 {
580
3.16M
                                if *coefficient >= 0 {
581
62.1k
                                    *coefficient += bit;
582
3.10M
                                } else {
583
3.10M
                                    *coefficient -= bit;
584
3.10M
                                }
585
1.18G
                            }
586
587
1.18G
                            if self.bits_left < 1 {
588
19.2M
                                self.refill(reader)?;
589
1.16G
                            }
590
                        } else {
591
315M
                            r -= 1;
592
315M
593
315M
                            if r < 0 {
594
                                // reached target zero coefficient.
595
304M
                                break 'advance_nonzero;
596
11.3M
                            }
597
                        };
598
599
1.19G
                        if k == self.spec_end {
600
20.9M
                            break 'advance_nonzero;
601
1.17G
                        }
602
1.17G
603
1.17G
                        k += 1;
604
                    }
605
2.46k
                }
606
607
325M
                if symbol != 0 {
608
325M
                    let pos = UN_ZIGZAG[k as usize & 63];
609
325M
                    // output new non-zero coefficient.
610
325M
                    block[pos & 63] = symbol as i16;
611
325M
                }
612
613
325M
                k += 1;
614
325M
615
325M
                if k > self.spec_end {
616
25.9M
                    break 'no_eob;
617
299M
                }
618
            }
619
56.8M
        }
620
153M
        if self.eob_run > 0 {
621
            // only run if block does not consists of purely zeroes
622
128M
            if &block[1..] != &[0; 63] {
623
42.1M
                self.refill(reader)?;
624
625
133M
                while k <= self.spec_end {
626
91.7M
                    let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
627
91.7M
628
91.7M
                    if *coefficient != 0 && self.get_bit() == 1 {
629
                        // check if we already modified it, if so do nothing, otherwise
630
                        // append the correction bit.
631
15.5M
                        if (*coefficient & bit) == 0 {
632
4.31M
                            if *coefficient >= 0 {
633
378k
                                *coefficient = coefficient.wrapping_add(bit);
634
3.93M
                            } else {
635
3.93M
                                *coefficient = coefficient.wrapping_sub(bit);
636
3.93M
                            }
637
11.1M
                        }
638
76.2M
                    }
639
91.7M
                    if self.bits_left < 1 {
640
                        // refill at the last possible moment
641
1.21M
                        self.refill(reader)?;
642
90.5M
                    }
643
91.7M
                    k += 1;
644
                }
645
85.8M
            }
646
            // count a block completed in EOB run
647
128M
            self.eob_run -= 1;
648
25.9M
        }
649
153M
        return Ok(true);
650
153M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Line
Count
Source
522
19.5M
    pub(crate) fn decode_mcu_ac_refine<T>(
523
19.5M
        &mut self, reader: &mut ZByteReader<T>, table: &HuffmanTable, block: &mut [i16; 64]
524
19.5M
    ) -> Result<bool, DecodeErrors>
525
19.5M
    where
526
19.5M
        T: ZReaderTrait
527
19.5M
    {
528
19.5M
        let bit = (1 << self.successive_low) as i16;
529
19.5M
530
19.5M
        let mut k = self.spec_start;
531
19.5M
        let (mut symbol, mut r);
532
19.5M
533
19.5M
        if self.eob_run == 0 {
534
            'no_eob: loop {
535
                // Decode a coefficient from the bit stream
536
191M
                self.refill(reader)?;
537
538
191M
                symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
539
191M
                symbol = table.lookup[symbol as usize];
540
191M
541
191M
                decode_huff!(self, symbol, table);
542
543
191M
                r = symbol >> 4;
544
191M
                symbol &= 15;
545
191M
546
191M
                if symbol == 0 {
547
251k
                    if r != 15 {
548
                        // EOB run is 2^r + bits
549
250k
                        self.eob_run = 1 << r;
550
250k
                        self.eob_run += self.get_bits(r as u8);
551
250k
                        // EOB runs are handled by the eob logic
552
250k
                        break 'no_eob;
553
913
                    }
554
                } else {
555
191M
                    if symbol != 1 {
556
21
                        return Err(DecodeErrors::HuffmanDecode(
557
21
                            "Bad Huffman code, corrupt JPEG?".to_string()
558
21
                        ));
559
191M
                    }
560
191M
                    // get sign bit
561
191M
                    // We assume we have enough bits, which should be correct for sane images
562
191M
                    // since we refill by 32 above
563
191M
                    if self.get_bit() == 1 {
564
904k
                        symbol = i32::from(bit);
565
190M
                    } else {
566
190M
                        symbol = i32::from(-bit);
567
190M
                    }
568
                }
569
570
                // Advance over already nonzero coefficients  appending
571
                // correction bits to the non-zeroes.
572
                // A correction bit is 1 if the absolute value of the coefficient must be increased
573
574
191M
                if k <= self.spec_end {
575
                    'advance_nonzero: loop {
576
1.08G
                        let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
577
1.08G
578
1.08G
                        if *coefficient != 0 {
579
910M
                            if self.get_bit() == 1 && (*coefficient & bit) == 0 {
580
2.70M
                                if *coefficient >= 0 {
581
53.6k
                                    *coefficient += bit;
582
2.65M
                                } else {
583
2.65M
                                    *coefficient -= bit;
584
2.65M
                                }
585
908M
                            }
586
587
910M
                            if self.bits_left < 1 {
588
14.6M
                                self.refill(reader)?;
589
896M
                            }
590
                        } else {
591
178M
                            r -= 1;
592
178M
593
178M
                            if r < 0 {
594
                                // reached target zero coefficient.
595
175M
                                break 'advance_nonzero;
596
2.52M
                            }
597
                        };
598
599
913M
                        if k == self.spec_end {
600
15.5M
                            break 'advance_nonzero;
601
897M
                        }
602
897M
603
897M
                        k += 1;
604
                    }
605
1.12k
                }
606
607
191M
                if symbol != 0 {
608
191M
                    let pos = UN_ZIGZAG[k as usize & 63];
609
191M
                    // output new non-zero coefficient.
610
191M
                    block[pos & 63] = symbol as i16;
611
191M
                }
612
613
191M
                k += 1;
614
191M
615
191M
                if k > self.spec_end {
616
18.3M
                    break 'no_eob;
617
173M
                }
618
            }
619
931k
        }
620
19.5M
        if self.eob_run > 0 {
621
            // only run if block does not consists of purely zeroes
622
1.18M
            if &block[1..] != &[0; 63] {
623
1.07M
                self.refill(reader)?;
624
625
62.2M
                while k <= self.spec_end {
626
61.1M
                    let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
627
61.1M
628
61.1M
                    if *coefficient != 0 && self.get_bit() == 1 {
629
                        // check if we already modified it, if so do nothing, otherwise
630
                        // append the correction bit.
631
12.9M
                        if (*coefficient & bit) == 0 {
632
3.30M
                            if *coefficient >= 0 {
633
372k
                                *coefficient = coefficient.wrapping_add(bit);
634
2.93M
                            } else {
635
2.93M
                                *coefficient = coefficient.wrapping_sub(bit);
636
2.93M
                            }
637
9.68M
                        }
638
48.2M
                    }
639
61.1M
                    if self.bits_left < 1 {
640
                        // refill at the last possible moment
641
787k
                        self.refill(reader)?;
642
60.4M
                    }
643
61.1M
                    k += 1;
644
                }
645
107k
            }
646
            // count a block completed in EOB run
647
1.18M
            self.eob_run -= 1;
648
18.3M
        }
649
19.5M
        return Ok(true);
650
19.5M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<&[u8]>
Line
Count
Source
522
134M
    pub(crate) fn decode_mcu_ac_refine<T>(
523
134M
        &mut self, reader: &mut ZByteReader<T>, table: &HuffmanTable, block: &mut [i16; 64]
524
134M
    ) -> Result<bool, DecodeErrors>
525
134M
    where
526
134M
        T: ZReaderTrait
527
134M
    {
528
134M
        let bit = (1 << self.successive_low) as i16;
529
134M
530
134M
        let mut k = self.spec_start;
531
134M
        let (mut symbol, mut r);
532
134M
533
134M
        if self.eob_run == 0 {
534
            'no_eob: loop {
535
                // Decode a coefficient from the bit stream
536
204M
                self.refill(reader)?;
537
538
204M
                symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
539
204M
                symbol = table.lookup[symbol as usize];
540
204M
541
204M
                decode_huff!(self, symbol, table);
542
543
204M
                r = symbol >> 4;
544
204M
                symbol &= 15;
545
204M
546
204M
                if symbol == 0 {
547
70.8M
                    if r != 15 {
548
                        // EOB run is 2^r + bits
549
70.8M
                        self.eob_run = 1 << r;
550
70.8M
                        self.eob_run += self.get_bits(r as u8);
551
70.8M
                        // EOB runs are handled by the eob logic
552
70.8M
                        break 'no_eob;
553
2.24k
                    }
554
                } else {
555
133M
                    if symbol != 1 {
556
111
                        return Err(DecodeErrors::HuffmanDecode(
557
111
                            "Bad Huffman code, corrupt JPEG?".to_string()
558
111
                        ));
559
133M
                    }
560
133M
                    // get sign bit
561
133M
                    // We assume we have enough bits, which should be correct for sane images
562
133M
                    // since we refill by 32 above
563
133M
                    if self.get_bit() == 1 {
564
35.2k
                        symbol = i32::from(bit);
565
133M
                    } else {
566
133M
                        symbol = i32::from(-bit);
567
133M
                    }
568
                }
569
570
                // Advance over already nonzero coefficients  appending
571
                // correction bits to the non-zeroes.
572
                // A correction bit is 1 if the absolute value of the coefficient must be increased
573
574
133M
                if k <= self.spec_end {
575
                    'advance_nonzero: loop {
576
414M
                        let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
577
414M
578
414M
                        if *coefficient != 0 {
579
276M
                            if self.get_bit() == 1 && (*coefficient & bit) == 0 {
580
456k
                                if *coefficient >= 0 {
581
8.56k
                                    *coefficient += bit;
582
447k
                                } else {
583
447k
                                    *coefficient -= bit;
584
447k
                                }
585
276M
                            }
586
587
276M
                            if self.bits_left < 1 {
588
4.61M
                                self.refill(reader)?;
589
272M
                            }
590
                        } else {
591
137M
                            r -= 1;
592
137M
593
137M
                            if r < 0 {
594
                                // reached target zero coefficient.
595
128M
                                break 'advance_nonzero;
596
8.81M
                            }
597
                        };
598
599
285M
                        if k == self.spec_end {
600
5.37M
                            break 'advance_nonzero;
601
280M
                        }
602
280M
603
280M
                        k += 1;
604
                    }
605
1.33k
                }
606
607
133M
                if symbol != 0 {
608
133M
                    let pos = UN_ZIGZAG[k as usize & 63];
609
133M
                    // output new non-zero coefficient.
610
133M
                    block[pos & 63] = symbol as i16;
611
133M
                }
612
613
133M
                k += 1;
614
133M
615
133M
                if k > self.spec_end {
616
7.63M
                    break 'no_eob;
617
126M
                }
618
            }
619
55.9M
        }
620
134M
        if self.eob_run > 0 {
621
            // only run if block does not consists of purely zeroes
622
126M
            if &block[1..] != &[0; 63] {
623
41.0M
                self.refill(reader)?;
624
625
71.5M
                while k <= self.spec_end {
626
30.5M
                    let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
627
30.5M
628
30.5M
                    if *coefficient != 0 && self.get_bit() == 1 {
629
                        // check if we already modified it, if so do nothing, otherwise
630
                        // append the correction bit.
631
2.51M
                        if (*coefficient & bit) == 0 {
632
1.00M
                            if *coefficient >= 0 {
633
6.15k
                                *coefficient = coefficient.wrapping_add(bit);
634
1.00M
                            } else {
635
1.00M
                                *coefficient = coefficient.wrapping_sub(bit);
636
1.00M
                            }
637
1.50M
                        }
638
28.0M
                    }
639
30.5M
                    if self.bits_left < 1 {
640
                        // refill at the last possible moment
641
428k
                        self.refill(reader)?;
642
30.0M
                    }
643
30.5M
                    k += 1;
644
                }
645
85.7M
            }
646
            // count a block completed in EOB run
647
126M
            self.eob_run -= 1;
648
7.63M
        }
649
134M
        return Ok(true);
650
134M
    }
651
652
20.3k
    pub fn update_progressive_params(&mut self, ah: u8, al: u8, spec_start: u8, spec_end: u8) {
653
20.3k
        self.successive_high = ah;
654
20.3k
        self.successive_low = al;
655
20.3k
        self.spec_start = spec_start;
656
20.3k
        self.spec_end = spec_end;
657
20.3k
    }
658
659
    /// Reset the stream if we have a restart marker
660
    ///
661
    /// Restart markers indicate drop those bits in the stream and zero out
662
    /// everything
663
    #[cold]
664
95.7k
    pub fn reset(&mut self) {
665
95.7k
        self.bits_left = 0;
666
95.7k
        self.marker = None;
667
95.7k
        self.buffer = 0;
668
95.7k
        self.aligned_buffer = 0;
669
95.7k
        self.eob_run = 0;
670
95.7k
    }
671
}
672
673
/// Do the equivalent of JPEG HUFF_EXTEND
674
#[inline(always)]
675
231M
fn huff_extend(x: i32, s: i32) -> i32 {
676
231M
    // if x<s return x else return x+offset[s] where offset[s] = ( (-1<<s)+1)
677
231M
    (x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((-1) << (s)) + 1))
678
231M
}
679
680
15.3M
const fn has_zero(v: u32) -> bool {
681
15.3M
    // Retrieved from Stanford bithacks
682
15.3M
    // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
683
15.3M
    return !((((v & 0x7F7F_7F7F) + 0x7F7F_7F7F) | v) | 0x7F7F_7F7F) != 0;
684
15.3M
}
685
686
15.3M
const fn has_byte(b: u32, val: u8) -> bool {
687
15.3M
    // Retrieved from Stanford bithacks
688
15.3M
    // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
689
15.3M
    has_zero(b ^ ((!0_u32 / 255) * (val as u32)))
690
15.3M
}
691
692
// mod tests {
693
//     use zune_core::bytestream::ZCursor;
694
//     use crate::JpegDecoder;
695
//
696
//     #[test]
697
//     fn test_image() {
698
//         let img = "/Users/etemesi/Downloads/PHO00008.JPG";
699
//         let data = std::fs::read(img).unwrap();
700
//         let mut decoder = JpegDecoder::new(ZCursor::new(&data[..]));
701
//         decoder.decode().unwrap();
702
//     }
703
// }