Coverage Report

Created: 2025-11-09 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zune-jpeg-0.5.5/src/bitstream.rs
Line
Count
Source
1
/*
2
 * Copyright (c) 2023.
3
 *
4
 * This software is free software;
5
 *
6
 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7
 */
8
9
#![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::format;
50
use alloc::string::ToString;
51
use core::cmp::min;
52
53
use zune_core::bytestream::{ZByteReaderTrait, ZReader};
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
#[rustfmt::skip]
108
pub(crate) struct BitStream {
109
    /// A MSB type buffer that is used for some certain operations
110
    pub buffer:              u64,
111
    /// A TOP  aligned MSB type buffer that is used to accelerate some operations like
112
    /// peek_bits and get_bits.
113
    ///
114
    /// By top aligned, I mean the top bit (63) represents the top bit in the buffer.
115
    aligned_buffer:          u64,
116
    /// Tell us the bits left the two buffer
117
    pub(crate) bits_left:    u8,
118
    /// Did we find a marker(RST/EOF) during decoding?
119
    pub marker:              Option<Marker>,
120
    /// An i16 with the bit corresponding to successive_low set to 1, others 0.
121
    pub successive_low_mask: i16,
122
    spec_start:              u8,
123
    spec_end:                u8,
124
    pub eob_run:             i32,
125
    pub overread_by:         usize,
126
    /// True if we have seen end of image marker.
127
    /// Don't read anything after that.
128
    pub seen_eoi:            bool,
129
}
130
131
impl BitStream {
132
    /// Create a new BitStream
133
    #[rustfmt::skip]
134
1.49k
    pub(crate) const fn new() -> BitStream {
135
1.49k
        BitStream {
136
1.49k
            buffer:              0,
137
1.49k
            aligned_buffer:      0,
138
1.49k
            bits_left:           0,
139
1.49k
            marker:              None,
140
1.49k
            successive_low_mask: 1,
141
1.49k
            spec_start:          0,
142
1.49k
            spec_end:            0,
143
1.49k
            eob_run:             0,
144
1.49k
            overread_by:         0,
145
1.49k
            seen_eoi:            false,
146
1.49k
        }
147
1.49k
    }
148
149
    /// Create a new Bitstream for progressive decoding
150
    #[allow(clippy::redundant_field_names)]
151
    #[rustfmt::skip]
152
3.97k
    pub(crate) fn new_progressive(al: u8, spec_start: u8, spec_end: u8) -> BitStream {
153
3.97k
        BitStream {
154
3.97k
            buffer:              0,
155
3.97k
            aligned_buffer:      0,
156
3.97k
            bits_left:           0,
157
3.97k
            marker:              None,
158
3.97k
            successive_low_mask: 1i16 << al,
159
3.97k
            spec_start:          spec_start,
160
3.97k
            spec_end:            spec_end,
161
3.97k
            eob_run:             0,
162
3.97k
            overread_by:         0,
163
3.97k
            seen_eoi:            false,
164
3.97k
        }
165
3.97k
    }
166
167
    /// Refill the bit buffer by (a maximum of) 32 bits
168
    ///
169
    /// # Arguments
170
    ///  - `reader`:`&mut BufReader<R>`: A mutable reference to an underlying
171
    ///    File/Memory buffer containing a valid JPEG stream
172
    ///
173
    /// This function will only refill if `self.count` is less than 32
174
    #[inline(always)] // to many call sites? ( perf improvement by 4%)
175
3.60G
    pub fn refill<T>(&mut self, reader: &mut ZReader<T>) -> Result<bool, DecodeErrors>
176
3.60G
    where
177
3.60G
        T: ZByteReaderTrait
178
    {
179
        /// Macro version of a single byte refill.
180
        /// Arguments
181
        /// buffer-> our io buffer, because rust macros cannot get values from
182
        /// the surrounding environment bits_left-> number of bits left
183
        /// to full refill
184
        macro_rules! refill {
185
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
186
                // read a byte from the stream
187
                $byte = u64::from(reader.read_u8());
188
                self.overread_by += usize::from(reader.eof()?);
189
                // append to the buffer
190
                // JPEG is a MSB type buffer so that means we append this
191
                // to the lower end (0..8) of the buffer and push the rest bits above..
192
                $buffer = ($buffer << 8) | $byte;
193
                // Increment bits left
194
                $bits_left += 8;
195
                // Check for special case  of OxFF, to see if it's a stream or a marker
196
                if $byte == 0xff {
197
                    // read next byte
198
                    let mut next_byte = u64::from(reader.read_u8());
199
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
200
                    if next_byte != 0x00 {
201
                        // skip that byte we read
202
                        while next_byte == 0xFF {
203
                            next_byte = u64::from(reader.read_u8());
204
                        }
205
206
                        if next_byte != 0x00 {
207
                            // Undo the byte append and return
208
                            $buffer >>= 8;
209
                            $bits_left -= 8;
210
211
                            if $bits_left != 0 {
212
                                self.aligned_buffer = $buffer << (64 - $bits_left);
213
                            }
214
215
                            self.marker = Marker::from_u8(next_byte as u8);
216
                            if next_byte == 0xD9 {
217
                                // special handling for eoi, fill some bytes,even if its zero,
218
                                // removes some panics
219
                                self.buffer <<= 8;
220
                                self.bits_left += 8;
221
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
222
                            }
223
224
                            return Ok(false);
225
                        }
226
                    }
227
                }
228
            };
229
        }
230
231
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
232
3.60G
        if self.bits_left < 32 {
233
458M
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
234
                // found a marker, or we are in EOI
235
                // also we are in over-reading mode, where we fill it with zeroes
236
237
                // fill with zeroes
238
439M
                self.buffer <<= 32;
239
439M
                self.bits_left += 32;
240
439M
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
241
439M
                return Ok(true);
242
18.4M
            }
243
244
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
245
            // as it is the common case
246
            //
247
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
248
            // guaranteed not to advance in case of failure (is this true), so
249
            // we revert the read later on (if we have 255), if this fails, we use the normal
250
            // byte at a time read
251
252
18.4M
            if let Ok(bytes) = reader.read_fixed_bytes_or_error::<4>() {
253
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
254
                // create buffer
255
18.4M
                let msb_buf = u32::from_be_bytes(bytes);
256
                // check if we have 0xff
257
18.4M
                if !has_byte(msb_buf, 255) {
258
16.9M
                    self.bits_left += 32;
259
16.9M
                    self.buffer <<= 32;
260
16.9M
                    self.buffer |= u64::from(msb_buf);
261
16.9M
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
262
16.9M
                    return Ok(true);
263
1.50M
                }
264
265
1.50M
                reader.rewind(4)?;
266
1.65k
            }
267
            // This serves two reasons,
268
            // 1: Make clippy shut up
269
            // 2: Favour register reuse
270
            let mut byte;
271
            // 4 refills, if all succeed the stream should contain enough bits to decode a
272
            // value
273
1.50M
            refill!(self.buffer, byte, self.bits_left);
274
1.46M
            refill!(self.buffer, byte, self.bits_left);
275
1.42M
            refill!(self.buffer, byte, self.bits_left);
276
1.39M
            refill!(self.buffer, byte, self.bits_left);
277
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
278
1.35M
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
279
3.14G
        }
280
3.15G
        return Ok(true);
281
3.60G
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
175
2.86G
    pub fn refill<T>(&mut self, reader: &mut ZReader<T>) -> Result<bool, DecodeErrors>
176
2.86G
    where
177
2.86G
        T: ZByteReaderTrait
178
    {
179
        /// Macro version of a single byte refill.
180
        /// Arguments
181
        /// buffer-> our io buffer, because rust macros cannot get values from
182
        /// the surrounding environment bits_left-> number of bits left
183
        /// to full refill
184
        macro_rules! refill {
185
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
186
                // read a byte from the stream
187
                $byte = u64::from(reader.read_u8());
188
                self.overread_by += usize::from(reader.eof()?);
189
                // append to the buffer
190
                // JPEG is a MSB type buffer so that means we append this
191
                // to the lower end (0..8) of the buffer and push the rest bits above..
192
                $buffer = ($buffer << 8) | $byte;
193
                // Increment bits left
194
                $bits_left += 8;
195
                // Check for special case  of OxFF, to see if it's a stream or a marker
196
                if $byte == 0xff {
197
                    // read next byte
198
                    let mut next_byte = u64::from(reader.read_u8());
199
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
200
                    if next_byte != 0x00 {
201
                        // skip that byte we read
202
                        while next_byte == 0xFF {
203
                            next_byte = u64::from(reader.read_u8());
204
                        }
205
206
                        if next_byte != 0x00 {
207
                            // Undo the byte append and return
208
                            $buffer >>= 8;
209
                            $bits_left -= 8;
210
211
                            if $bits_left != 0 {
212
                                self.aligned_buffer = $buffer << (64 - $bits_left);
213
                            }
214
215
                            self.marker = Marker::from_u8(next_byte as u8);
216
                            if next_byte == 0xD9 {
217
                                // special handling for eoi, fill some bytes,even if its zero,
218
                                // removes some panics
219
                                self.buffer <<= 8;
220
                                self.bits_left += 8;
221
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
222
                            }
223
224
                            return Ok(false);
225
                        }
226
                    }
227
                }
228
            };
229
        }
230
231
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
232
2.86G
        if self.bits_left < 32 {
233
334M
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
234
                // found a marker, or we are in EOI
235
                // also we are in over-reading mode, where we fill it with zeroes
236
237
                // fill with zeroes
238
317M
                self.buffer <<= 32;
239
317M
                self.bits_left += 32;
240
317M
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
241
317M
                return Ok(true);
242
16.2M
            }
243
244
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
245
            // as it is the common case
246
            //
247
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
248
            // guaranteed not to advance in case of failure (is this true), so
249
            // we revert the read later on (if we have 255), if this fails, we use the normal
250
            // byte at a time read
251
252
16.2M
            if let Ok(bytes) = reader.read_fixed_bytes_or_error::<4>() {
253
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
254
                // create buffer
255
16.2M
                let msb_buf = u32::from_be_bytes(bytes);
256
                // check if we have 0xff
257
16.2M
                if !has_byte(msb_buf, 255) {
258
14.8M
                    self.bits_left += 32;
259
14.8M
                    self.buffer <<= 32;
260
14.8M
                    self.buffer |= u64::from(msb_buf);
261
14.8M
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
262
14.8M
                    return Ok(true);
263
1.39M
                }
264
265
1.39M
                reader.rewind(4)?;
266
1.18k
            }
267
            // This serves two reasons,
268
            // 1: Make clippy shut up
269
            // 2: Favour register reuse
270
            let mut byte;
271
            // 4 refills, if all succeed the stream should contain enough bits to decode a
272
            // value
273
1.39M
            refill!(self.buffer, byte, self.bits_left);
274
1.36M
            refill!(self.buffer, byte, self.bits_left);
275
1.33M
            refill!(self.buffer, byte, self.bits_left);
276
1.30M
            refill!(self.buffer, byte, self.bits_left);
277
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
278
1.27M
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
279
2.52G
        }
280
2.52G
        return Ok(true);
281
2.86G
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::refill::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
175
746M
    pub fn refill<T>(&mut self, reader: &mut ZReader<T>) -> Result<bool, DecodeErrors>
176
746M
    where
177
746M
        T: ZByteReaderTrait
178
    {
179
        /// Macro version of a single byte refill.
180
        /// Arguments
181
        /// buffer-> our io buffer, because rust macros cannot get values from
182
        /// the surrounding environment bits_left-> number of bits left
183
        /// to full refill
184
        macro_rules! refill {
185
            ($buffer:expr,$byte:expr,$bits_left:expr) => {
186
                // read a byte from the stream
187
                $byte = u64::from(reader.read_u8());
188
                self.overread_by += usize::from(reader.eof()?);
189
                // append to the buffer
190
                // JPEG is a MSB type buffer so that means we append this
191
                // to the lower end (0..8) of the buffer and push the rest bits above..
192
                $buffer = ($buffer << 8) | $byte;
193
                // Increment bits left
194
                $bits_left += 8;
195
                // Check for special case  of OxFF, to see if it's a stream or a marker
196
                if $byte == 0xff {
197
                    // read next byte
198
                    let mut next_byte = u64::from(reader.read_u8());
199
                    // Byte snuffing, if we encounter byte snuff, we skip the byte
200
                    if next_byte != 0x00 {
201
                        // skip that byte we read
202
                        while next_byte == 0xFF {
203
                            next_byte = u64::from(reader.read_u8());
204
                        }
205
206
                        if next_byte != 0x00 {
207
                            // Undo the byte append and return
208
                            $buffer >>= 8;
209
                            $bits_left -= 8;
210
211
                            if $bits_left != 0 {
212
                                self.aligned_buffer = $buffer << (64 - $bits_left);
213
                            }
214
215
                            self.marker = Marker::from_u8(next_byte as u8);
216
                            if next_byte == 0xD9 {
217
                                // special handling for eoi, fill some bytes,even if its zero,
218
                                // removes some panics
219
                                self.buffer <<= 8;
220
                                self.bits_left += 8;
221
                                self.aligned_buffer = self.buffer << (64 - self.bits_left);
222
                            }
223
224
                            return Ok(false);
225
                        }
226
                    }
227
                }
228
            };
229
        }
230
231
        // 32 bits is enough for a decode(16 bits) and receive_extend(max 16 bits)
232
746M
        if self.bits_left < 32 {
233
124M
            if self.marker.is_some() || self.overread_by > 0  || self.seen_eoi{
234
                // found a marker, or we are in EOI
235
                // also we are in over-reading mode, where we fill it with zeroes
236
237
                // fill with zeroes
238
121M
                self.buffer <<= 32;
239
121M
                self.bits_left += 32;
240
121M
                self.aligned_buffer = self.buffer << (64 - self.bits_left);
241
121M
                return Ok(true);
242
2.20M
            }
243
244
            // we optimize for the case where we don't have 255 in the stream and have 4 bytes left
245
            // as it is the common case
246
            //
247
            // so we always read 4 bytes, if read_fixed_bytes errors out, the cursor is
248
            // guaranteed not to advance in case of failure (is this true), so
249
            // we revert the read later on (if we have 255), if this fails, we use the normal
250
            // byte at a time read
251
252
2.20M
            if let Ok(bytes) = reader.read_fixed_bytes_or_error::<4>() {
253
                // we have 4 bytes to spare, read the 4 bytes into a temporary buffer
254
                // create buffer
255
2.20M
                let msb_buf = u32::from_be_bytes(bytes);
256
                // check if we have 0xff
257
2.20M
                if !has_byte(msb_buf, 255) {
258
2.09M
                    self.bits_left += 32;
259
2.09M
                    self.buffer <<= 32;
260
2.09M
                    self.buffer |= u64::from(msb_buf);
261
2.09M
                    self.aligned_buffer = self.buffer << (64 - self.bits_left);
262
2.09M
                    return Ok(true);
263
113k
                }
264
265
113k
                reader.rewind(4)?;
266
464
            }
267
            // This serves two reasons,
268
            // 1: Make clippy shut up
269
            // 2: Favour register reuse
270
            let mut byte;
271
            // 4 refills, if all succeed the stream should contain enough bits to decode a
272
            // value
273
113k
            refill!(self.buffer, byte, self.bits_left);
274
104k
            refill!(self.buffer, byte, self.bits_left);
275
94.6k
            refill!(self.buffer, byte, self.bits_left);
276
84.2k
            refill!(self.buffer, byte, self.bits_left);
277
            // Construct an MSB buffer whose top bits are the bitstream we are currently holding.
278
74.8k
            self.aligned_buffer = self.buffer << (64 - self.bits_left);
279
622M
        }
280
622M
        return Ok(true);
281
746M
    }
282
    /// Decode the DC coefficient in a MCU block.
283
    ///
284
    /// The decoded coefficient is written to `dc_prediction`
285
    ///
286
    #[allow(
287
        clippy::cast_possible_truncation,
288
        clippy::cast_sign_loss,
289
        clippy::unwrap_used
290
    )]
291
    #[inline(always)]
292
324M
    fn decode_dc<T>(
293
324M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
294
324M
    ) -> Result<bool, DecodeErrors>
295
324M
    where
296
324M
        T: ZByteReaderTrait
297
    {
298
        let (mut symbol, r);
299
300
324M
        if self.bits_left < 32 {
301
24.8M
            self.refill(reader)?;
302
299M
        };
303
        // look a head HUFF_LOOKAHEAD bits into the bitstream
304
324M
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
305
324M
        symbol = dc_table.lookup[symbol as usize];
306
307
324M
        decode_huff!(self, symbol, dc_table);
308
309
324M
        if symbol != 0 {
310
25.3M
            r = self.get_bits(symbol as u8);
311
25.3M
            symbol = huff_extend(r, symbol);
312
299M
        }
313
        // Update DC prediction
314
324M
        *dc_prediction = dc_prediction.wrapping_add(symbol);
315
316
324M
        return Ok(true);
317
324M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
292
213M
    fn decode_dc<T>(
293
213M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
294
213M
    ) -> Result<bool, DecodeErrors>
295
213M
    where
296
213M
        T: ZByteReaderTrait
297
    {
298
        let (mut symbol, r);
299
300
213M
        if self.bits_left < 32 {
301
14.8M
            self.refill(reader)?;
302
198M
        };
303
        // look a head HUFF_LOOKAHEAD bits into the bitstream
304
213M
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
305
213M
        symbol = dc_table.lookup[symbol as usize];
306
307
213M
        decode_huff!(self, symbol, dc_table);
308
309
213M
        if symbol != 0 {
310
12.0M
            r = self.get_bits(symbol as u8);
311
12.0M
            symbol = huff_extend(r, symbol);
312
201M
        }
313
        // Update DC prediction
314
213M
        *dc_prediction = dc_prediction.wrapping_add(symbol);
315
316
213M
        return Ok(true);
317
213M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_dc::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
292
111M
    fn decode_dc<T>(
293
111M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32
294
111M
    ) -> Result<bool, DecodeErrors>
295
111M
    where
296
111M
        T: ZByteReaderTrait
297
    {
298
        let (mut symbol, r);
299
300
111M
        if self.bits_left < 32 {
301
10.0M
            self.refill(reader)?;
302
101M
        };
303
        // look a head HUFF_LOOKAHEAD bits into the bitstream
304
111M
        symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
305
111M
        symbol = dc_table.lookup[symbol as usize];
306
307
111M
        decode_huff!(self, symbol, dc_table);
308
309
111M
        if symbol != 0 {
310
13.3M
            r = self.get_bits(symbol as u8);
311
13.3M
            symbol = huff_extend(r, symbol);
312
98.0M
        }
313
        // Update DC prediction
314
111M
        *dc_prediction = dc_prediction.wrapping_add(symbol);
315
316
111M
        return Ok(true);
317
111M
    }
318
319
    /// Decode a Minimum Code Unit(MCU) as quickly as possible
320
    ///
321
    /// # Arguments
322
    /// - reader: The bitstream from where we read more bits.
323
    /// - dc_table: The Huffman table used to decode the DC coefficient
324
    /// - ac_table: The Huffman table used to decode AC values
325
    /// - block: A memory region where we will write out the decoded values
326
    /// - DC prediction: Last DC value for this component
327
    ///
328
    #[allow(
329
        clippy::many_single_char_names,
330
        clippy::cast_possible_truncation,
331
        clippy::cast_sign_loss
332
    )]
333
    #[inline(never)]
334
86.3M
    pub fn decode_mcu_block<T>(
335
86.3M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
336
86.3M
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
337
86.3M
    ) -> Result<(), DecodeErrors>
338
86.3M
    where
339
86.3M
        T: ZByteReaderTrait
340
    {
341
        // Get fast AC table as a reference before we enter the hot path
342
86.3M
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
343
344
        let (mut symbol, mut r, mut fast_ac);
345
        // Decode AC coefficients
346
86.3M
        let mut pos: usize = 1;
347
348
        // decode DC, dc prediction will contain the value
349
86.3M
        self.decode_dc(reader, dc_table, dc_prediction)?;
350
351
        // set dc to be the dc prediction.
352
86.3M
        block[0] = *dc_prediction * qt_table[0];
353
354
2.40G
        while pos < 64 {
355
2.36G
            self.refill(reader)?;
356
2.36G
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
357
2.36G
            fast_ac = ac_lookup[symbol as usize];
358
2.36G
            symbol = ac_table.lookup[symbol as usize];
359
360
2.36G
            if fast_ac != 0 {
361
2.27G
                //  FAST AC path
362
2.27G
                pos += ((fast_ac >> 4) & 15) as usize; // run
363
2.27G
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
364
2.27G
365
2.27G
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
366
2.27G
                self.drop_bits((fast_ac & 15) as u8);
367
2.27G
                pos += 1;
368
2.27G
            } else {
369
94.5M
                decode_huff!(self, symbol, ac_table);
370
371
94.5M
                r = symbol >> 4;
372
94.5M
                symbol &= 15;
373
374
94.5M
                if symbol != 0 {
375
50.8M
                    pos += r as usize;
376
50.8M
                    r = self.get_bits(symbol as u8);
377
50.8M
                    symbol = huff_extend(r, symbol);
378
50.8M
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
379
50.8M
380
50.8M
                    block[t_pos] = symbol * qt_table[t_pos];
381
50.8M
382
50.8M
                    pos += 1;
383
50.8M
                } else if r != 15 {
384
43.6M
                    return Ok(());
385
140k
                } else {
386
140k
                    pos += 16;
387
140k
                }
388
            }
389
        }
390
42.7M
        return Ok(());
391
86.3M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
334
67.1M
    pub fn decode_mcu_block<T>(
335
67.1M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
336
67.1M
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
337
67.1M
    ) -> Result<(), DecodeErrors>
338
67.1M
    where
339
67.1M
        T: ZByteReaderTrait
340
    {
341
        // Get fast AC table as a reference before we enter the hot path
342
67.1M
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
343
344
        let (mut symbol, mut r, mut fast_ac);
345
        // Decode AC coefficients
346
67.1M
        let mut pos: usize = 1;
347
348
        // decode DC, dc prediction will contain the value
349
67.1M
        self.decode_dc(reader, dc_table, dc_prediction)?;
350
351
        // set dc to be the dc prediction.
352
67.1M
        block[0] = *dc_prediction * qt_table[0];
353
354
1.95G
        while pos < 64 {
355
1.93G
            self.refill(reader)?;
356
1.93G
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
357
1.93G
            fast_ac = ac_lookup[symbol as usize];
358
1.93G
            symbol = ac_table.lookup[symbol as usize];
359
360
1.93G
            if fast_ac != 0 {
361
1.88G
                //  FAST AC path
362
1.88G
                pos += ((fast_ac >> 4) & 15) as usize; // run
363
1.88G
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
364
1.88G
365
1.88G
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
366
1.88G
                self.drop_bits((fast_ac & 15) as u8);
367
1.88G
                pos += 1;
368
1.88G
            } else {
369
43.3M
                decode_huff!(self, symbol, ac_table);
370
371
43.3M
                r = symbol >> 4;
372
43.3M
                symbol &= 15;
373
374
43.3M
                if symbol != 0 {
375
5.60M
                    pos += r as usize;
376
5.60M
                    r = self.get_bits(symbol as u8);
377
5.60M
                    symbol = huff_extend(r, symbol);
378
5.60M
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
379
5.60M
380
5.60M
                    block[t_pos] = symbol * qt_table[t_pos];
381
5.60M
382
5.60M
                    pos += 1;
383
37.7M
                } else if r != 15 {
384
37.5M
                    return Ok(());
385
114k
                } else {
386
114k
                    pos += 16;
387
114k
                }
388
            }
389
        }
390
29.5M
        return Ok(());
391
67.1M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_block::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
334
19.2M
    pub fn decode_mcu_block<T>(
335
19.2M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable,
336
19.2M
        qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32
337
19.2M
    ) -> Result<(), DecodeErrors>
338
19.2M
    where
339
19.2M
        T: ZByteReaderTrait
340
    {
341
        // Get fast AC table as a reference before we enter the hot path
342
19.2M
        let ac_lookup = ac_table.ac_lookup.as_ref().unwrap();
343
344
        let (mut symbol, mut r, mut fast_ac);
345
        // Decode AC coefficients
346
19.2M
        let mut pos: usize = 1;
347
348
        // decode DC, dc prediction will contain the value
349
19.2M
        self.decode_dc(reader, dc_table, dc_prediction)?;
350
351
        // set dc to be the dc prediction.
352
19.2M
        block[0] = *dc_prediction * qt_table[0];
353
354
450M
        while pos < 64 {
355
437M
            self.refill(reader)?;
356
437M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
357
437M
            fast_ac = ac_lookup[symbol as usize];
358
437M
            symbol = ac_table.lookup[symbol as usize];
359
360
437M
            if fast_ac != 0 {
361
385M
                //  FAST AC path
362
385M
                pos += ((fast_ac >> 4) & 15) as usize; // run
363
385M
                let t_pos = UN_ZIGZAG[min(pos, 63)] & 63;
364
385M
365
385M
                block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value
366
385M
                self.drop_bits((fast_ac & 15) as u8);
367
385M
                pos += 1;
368
385M
            } else {
369
51.2M
                decode_huff!(self, symbol, ac_table);
370
371
51.2M
                r = symbol >> 4;
372
51.2M
                symbol &= 15;
373
374
51.2M
                if symbol != 0 {
375
45.2M
                    pos += r as usize;
376
45.2M
                    r = self.get_bits(symbol as u8);
377
45.2M
                    symbol = huff_extend(r, symbol);
378
45.2M
                    let t_pos = UN_ZIGZAG[pos & 63] & 63;
379
45.2M
380
45.2M
                    block[t_pos] = symbol * qt_table[t_pos];
381
45.2M
382
45.2M
                    pos += 1;
383
45.2M
                } else if r != 15 {
384
6.02M
                    return Ok(());
385
26.5k
                } else {
386
26.5k
                    pos += 16;
387
26.5k
                }
388
            }
389
        }
390
13.2M
        return Ok(());
391
19.2M
    }
392
393
    /// Peek `look_ahead` bits ahead without discarding them from the buffer
394
    #[inline(always)]
395
    #[allow(clippy::cast_possible_truncation)]
396
3.87G
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
397
3.87G
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
398
3.87G
    }
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::<_>
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>
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
396
7.85M
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
397
7.85M
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
398
7.85M
    }
<zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Line
Count
Source
396
3.02G
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
397
3.02G
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
398
3.02G
    }
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
396
210k
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
397
210k
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
398
210k
    }
<zune_jpeg::bitstream::BitStream>::peek_bits::<9>
Line
Count
Source
396
839M
    const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 {
397
839M
        (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32
398
839M
    }
399
400
    /// Discard the next `N` bits without checking
401
    #[inline]
402
6.40G
    fn drop_bits(&mut self, n: u8) {
403
6.40G
        debug_assert!(self.bits_left >= n);
404
        //self.bits_left -= n;
405
6.40G
        self.bits_left = self.bits_left.saturating_sub(n);
406
6.40G
        self.aligned_buffer <<= n;
407
6.40G
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
<zune_jpeg::bitstream::BitStream>::drop_bits
Line
Count
Source
402
2.54G
    fn drop_bits(&mut self, n: u8) {
403
2.54G
        debug_assert!(self.bits_left >= n);
404
        //self.bits_left -= n;
405
2.54G
        self.bits_left = self.bits_left.saturating_sub(n);
406
2.54G
        self.aligned_buffer <<= n;
407
2.54G
    }
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
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits
<zune_jpeg::bitstream::BitStream>::drop_bits
Line
Count
Source
402
3.02G
    fn drop_bits(&mut self, n: u8) {
403
3.02G
        debug_assert!(self.bits_left >= n);
404
        //self.bits_left -= n;
405
3.02G
        self.bits_left = self.bits_left.saturating_sub(n);
406
3.02G
        self.aligned_buffer <<= n;
407
3.02G
    }
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
402
839M
    fn drop_bits(&mut self, n: u8) {
403
839M
        debug_assert!(self.bits_left >= n);
404
        //self.bits_left -= n;
405
839M
        self.bits_left = self.bits_left.saturating_sub(n);
406
839M
        self.aligned_buffer <<= n;
407
839M
    }
408
409
    /// Read `n_bits` from the buffer  and discard them
410
    #[inline(always)]
411
    #[allow(clippy::cast_possible_truncation)]
412
185M
    fn get_bits(&mut self, n_bits: u8) -> i32 {
413
185M
        let mask = (1_u64 << n_bits) - 1;
414
415
185M
        self.aligned_buffer = self.aligned_buffer.rotate_left(u32::from(n_bits));
416
185M
        let bits = (self.aligned_buffer & mask) as i32;
417
185M
        self.bits_left = self.bits_left.wrapping_sub(n_bits);
418
185M
        bits
419
185M
    }
420
421
    /// Decode a DC block
422
    #[allow(clippy::cast_possible_truncation)]
423
    #[inline]
424
238M
    pub(crate) fn decode_prog_dc_first<T>(
425
238M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, block: &mut i16,
426
238M
        dc_prediction: &mut i32
427
238M
    ) -> Result<(), DecodeErrors>
428
238M
    where
429
238M
        T: ZByteReaderTrait
430
    {
431
238M
        self.decode_dc(reader, dc_table, dc_prediction)?;
432
238M
        *block = (*dc_prediction as i16).wrapping_mul(self.successive_low_mask);
433
238M
        return Ok(());
434
238M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
424
146M
    pub(crate) fn decode_prog_dc_first<T>(
425
146M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, block: &mut i16,
426
146M
        dc_prediction: &mut i32
427
146M
    ) -> Result<(), DecodeErrors>
428
146M
    where
429
146M
        T: ZByteReaderTrait
430
    {
431
146M
        self.decode_dc(reader, dc_table, dc_prediction)?;
432
146M
        *block = (*dc_prediction as i16).wrapping_mul(self.successive_low_mask);
433
146M
        return Ok(());
434
146M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
424
92.1M
    pub(crate) fn decode_prog_dc_first<T>(
425
92.1M
        &mut self, reader: &mut ZReader<T>, dc_table: &HuffmanTable, block: &mut i16,
426
92.1M
        dc_prediction: &mut i32
427
92.1M
    ) -> Result<(), DecodeErrors>
428
92.1M
    where
429
92.1M
        T: ZByteReaderTrait
430
    {
431
92.1M
        self.decode_dc(reader, dc_table, dc_prediction)?;
432
92.1M
        *block = (*dc_prediction as i16).wrapping_mul(self.successive_low_mask);
433
92.1M
        return Ok(());
434
92.1M
    }
435
    #[inline]
436
174M
    pub(crate) fn decode_prog_dc_refine<T>(
437
174M
        &mut self, reader: &mut ZReader<T>, block: &mut i16
438
174M
    ) -> Result<(), DecodeErrors>
439
174M
    where
440
174M
        T: ZByteReaderTrait
441
    {
442
        // refinement scan
443
174M
        if self.bits_left < 1 {
444
5.44M
            self.refill(reader)?;
445
            // if we find a marker, it may happens we don't refill.
446
            // So let's confirm again that refill worked
447
5.44M
            if self.bits_left < 1 {
448
32
                return Err(DecodeErrors::Format(
449
32
                    "Marker found where not expected in refine bit".to_string()
450
32
                ));
451
5.44M
            }
452
169M
        }
453
454
174M
        if self.get_bit() == 1 {
455
4.98M
            *block = block.wrapping_add(self.successive_low_mask);
456
169M
        }
457
458
174M
        Ok(())
459
174M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
436
148M
    pub(crate) fn decode_prog_dc_refine<T>(
437
148M
        &mut self, reader: &mut ZReader<T>, block: &mut i16
438
148M
    ) -> Result<(), DecodeErrors>
439
148M
    where
440
148M
        T: ZByteReaderTrait
441
    {
442
        // refinement scan
443
148M
        if self.bits_left < 1 {
444
4.62M
            self.refill(reader)?;
445
            // if we find a marker, it may happens we don't refill.
446
            // So let's confirm again that refill worked
447
4.62M
            if self.bits_left < 1 {
448
29
                return Err(DecodeErrors::Format(
449
29
                    "Marker found where not expected in refine bit".to_string()
450
29
                ));
451
4.62M
            }
452
143M
        }
453
454
148M
        if self.get_bit() == 1 {
455
4.89M
            *block = block.wrapping_add(self.successive_low_mask);
456
143M
        }
457
458
148M
        Ok(())
459
148M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
436
26.3M
    pub(crate) fn decode_prog_dc_refine<T>(
437
26.3M
        &mut self, reader: &mut ZReader<T>, block: &mut i16
438
26.3M
    ) -> Result<(), DecodeErrors>
439
26.3M
    where
440
26.3M
        T: ZByteReaderTrait
441
    {
442
        // refinement scan
443
26.3M
        if self.bits_left < 1 {
444
823k
            self.refill(reader)?;
445
            // if we find a marker, it may happens we don't refill.
446
            // So let's confirm again that refill worked
447
823k
            if self.bits_left < 1 {
448
3
                return Err(DecodeErrors::Format(
449
3
                    "Marker found where not expected in refine bit".to_string()
450
3
                ));
451
823k
            }
452
25.5M
        }
453
454
26.3M
        if self.get_bit() == 1 {
455
90.0k
            *block = block.wrapping_add(self.successive_low_mask);
456
26.2M
        }
457
458
26.3M
        Ok(())
459
26.3M
    }
460
461
    /// Get a single bit from the bitstream
462
2.54G
    fn get_bit(&mut self) -> u8 {
463
2.54G
        let k = (self.aligned_buffer >> 63) as u8;
464
        // discard a bit
465
2.54G
        self.drop_bits(1);
466
2.54G
        return k;
467
2.54G
    }
468
80.0M
    pub(crate) fn decode_mcu_ac_first<T>(
469
80.0M
        &mut self, reader: &mut ZReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64]
470
80.0M
    ) -> Result<bool, DecodeErrors>
471
80.0M
    where
472
80.0M
        T: ZByteReaderTrait
473
    {
474
80.0M
        let fast_ac = ac_table.ac_lookup.as_ref().unwrap();
475
80.0M
        let bit = self.successive_low_mask;
476
477
80.0M
        let mut k = self.spec_start as usize;
478
        let (mut symbol, mut r, mut fac);
479
480
        // EOB runs are handled in mcu_prog.rs
481
        'block: loop {
482
723M
            self.refill(reader)?;
483
484
723M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
485
723M
            fac = fast_ac[symbol as usize];
486
723M
            symbol = ac_table.lookup[symbol as usize];
487
488
723M
            if fac != 0 {
489
630M
                // fast ac path
490
630M
                k += ((fac >> 4) & 15) as usize; // run
491
630M
                block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(bit); // value
492
630M
                self.drop_bits((fac & 15) as u8);
493
630M
                k += 1;
494
630M
            } else {
495
93.4M
                decode_huff!(self, symbol, ac_table);
496
497
93.4M
                r = symbol >> 4;
498
93.4M
                symbol &= 15;
499
500
93.4M
                if symbol != 0 {
501
74.0M
                    k += r as usize;
502
74.0M
                    r = self.get_bits(symbol as u8);
503
74.0M
                    symbol = huff_extend(r, symbol);
504
74.0M
                    block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(bit);
505
74.0M
                    k += 1;
506
74.0M
                } else {
507
19.3M
                    if r != 15 {
508
19.3M
                        self.eob_run = 1 << r;
509
19.3M
                        self.eob_run += self.get_bits(r as u8);
510
19.3M
                        self.eob_run -= 1;
511
19.3M
                        break;
512
49.9k
                    }
513
514
49.9k
                    k += 16;
515
                }
516
            }
517
518
704M
            if k > self.spec_end as usize {
519
60.7M
                break 'block;
520
643M
            }
521
        }
522
80.0M
        return Ok(true);
523
80.0M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
468
36.6M
    pub(crate) fn decode_mcu_ac_first<T>(
469
36.6M
        &mut self, reader: &mut ZReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64]
470
36.6M
    ) -> Result<bool, DecodeErrors>
471
36.6M
    where
472
36.6M
        T: ZByteReaderTrait
473
    {
474
36.6M
        let fast_ac = ac_table.ac_lookup.as_ref().unwrap();
475
36.6M
        let bit = self.successive_low_mask;
476
477
36.6M
        let mut k = self.spec_start as usize;
478
        let (mut symbol, mut r, mut fac);
479
480
        // EOB runs are handled in mcu_prog.rs
481
        'block: loop {
482
466M
            self.refill(reader)?;
483
484
466M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
485
466M
            fac = fast_ac[symbol as usize];
486
466M
            symbol = ac_table.lookup[symbol as usize];
487
488
466M
            if fac != 0 {
489
438M
                // fast ac path
490
438M
                k += ((fac >> 4) & 15) as usize; // run
491
438M
                block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(bit); // value
492
438M
                self.drop_bits((fac & 15) as u8);
493
438M
                k += 1;
494
438M
            } else {
495
27.5M
                decode_huff!(self, symbol, ac_table);
496
497
27.5M
                r = symbol >> 4;
498
27.5M
                symbol &= 15;
499
500
27.5M
                if symbol != 0 {
501
8.42M
                    k += r as usize;
502
8.42M
                    r = self.get_bits(symbol as u8);
503
8.42M
                    symbol = huff_extend(r, symbol);
504
8.42M
                    block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(bit);
505
8.42M
                    k += 1;
506
8.42M
                } else {
507
19.1M
                    if r != 15 {
508
19.1M
                        self.eob_run = 1 << r;
509
19.1M
                        self.eob_run += self.get_bits(r as u8);
510
19.1M
                        self.eob_run -= 1;
511
19.1M
                        break;
512
10.7k
                    }
513
514
10.7k
                    k += 16;
515
                }
516
            }
517
518
447M
            if k > self.spec_end as usize {
519
17.4M
                break 'block;
520
429M
            }
521
        }
522
36.6M
        return Ok(true);
523
36.6M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
468
43.4M
    pub(crate) fn decode_mcu_ac_first<T>(
469
43.4M
        &mut self, reader: &mut ZReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64]
470
43.4M
    ) -> Result<bool, DecodeErrors>
471
43.4M
    where
472
43.4M
        T: ZByteReaderTrait
473
    {
474
43.4M
        let fast_ac = ac_table.ac_lookup.as_ref().unwrap();
475
43.4M
        let bit = self.successive_low_mask;
476
477
43.4M
        let mut k = self.spec_start as usize;
478
        let (mut symbol, mut r, mut fac);
479
480
        // EOB runs are handled in mcu_prog.rs
481
        'block: loop {
482
257M
            self.refill(reader)?;
483
484
257M
            symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
485
257M
            fac = fast_ac[symbol as usize];
486
257M
            symbol = ac_table.lookup[symbol as usize];
487
488
257M
            if fac != 0 {
489
191M
                // fast ac path
490
191M
                k += ((fac >> 4) & 15) as usize; // run
491
191M
                block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(bit); // value
492
191M
                self.drop_bits((fac & 15) as u8);
493
191M
                k += 1;
494
191M
            } else {
495
65.8M
                decode_huff!(self, symbol, ac_table);
496
497
65.8M
                r = symbol >> 4;
498
65.8M
                symbol &= 15;
499
500
65.8M
                if symbol != 0 {
501
65.6M
                    k += r as usize;
502
65.6M
                    r = self.get_bits(symbol as u8);
503
65.6M
                    symbol = huff_extend(r, symbol);
504
65.6M
                    block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(bit);
505
65.6M
                    k += 1;
506
65.6M
                } else {
507
201k
                    if r != 15 {
508
162k
                        self.eob_run = 1 << r;
509
162k
                        self.eob_run += self.get_bits(r as u8);
510
162k
                        self.eob_run -= 1;
511
162k
                        break;
512
39.2k
                    }
513
514
39.2k
                    k += 16;
515
                }
516
            }
517
518
257M
            if k > self.spec_end as usize {
519
43.2M
                break 'block;
520
213M
            }
521
        }
522
43.4M
        return Ok(true);
523
43.4M
    }
524
    #[allow(clippy::too_many_lines, clippy::op_ref)]
525
60.4M
    pub(crate) fn decode_mcu_ac_refine<T>(
526
60.4M
        &mut self, reader: &mut ZReader<T>, table: &HuffmanTable, block: &mut [i16; 64]
527
60.4M
    ) -> Result<bool, DecodeErrors>
528
60.4M
    where
529
60.4M
        T: ZByteReaderTrait
530
    {
531
60.4M
        let bit = self.successive_low_mask;
532
533
60.4M
        let mut k = self.spec_start;
534
        let (mut symbol, mut r);
535
536
60.4M
        if self.eob_run == 0 {
537
            'no_eob: loop {
538
                // Decode a coefficient from the bit stream
539
446M
                self.refill(reader)?;
540
541
446M
                symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
542
446M
                symbol = table.lookup[symbol as usize];
543
544
446M
                decode_huff!(self, symbol, table);
545
546
446M
                r = symbol >> 4;
547
446M
                symbol &= 15;
548
549
446M
                if symbol == 0 {
550
16.0M
                    if r != 15 {
551
                        // EOB run is 2^r + bits
552
15.9M
                        self.eob_run = 1 << r;
553
15.9M
                        self.eob_run += self.get_bits(r as u8);
554
                        // EOB runs are handled by the eob logic
555
15.9M
                        break 'no_eob;
556
47.3k
                    }
557
                } else {
558
430M
                    if symbol != 1 {
559
324
                        return Err(DecodeErrors::HuffmanDecode(
560
324
                            "Bad Huffman code, corrupt JPEG?".to_string()
561
324
                        ));
562
430M
                    }
563
                    // get sign bit
564
                    // We assume we have enough bits, which should be correct for sane images
565
                    // since we refill by 32 above
566
430M
                    if self.get_bit() == 1 {
567
1.11M
                        symbol = i32::from(bit);
568
429M
                    } else {
569
429M
                        symbol = i32::from(-bit);
570
429M
                    }
571
                }
572
573
                // Advance over already nonzero coefficients  appending
574
                // correction bits to the non-zeroes.
575
                // A correction bit is 1 if the absolute value of the coefficient must be increased
576
577
430M
                if k <= self.spec_end {
578
                    'advance_nonzero: loop {
579
2.23G
                        let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
580
581
2.23G
                        if *coefficient != 0 {
582
1.83G
                            if self.get_bit() == 1 && (*coefficient & bit) == 0 {
583
1.29M
                                if *coefficient >= 0 {
584
145k
                                    *coefficient += bit;
585
1.15M
                                } else {
586
1.15M
                                    *coefficient -= bit;
587
1.15M
                                }
588
1.83G
                            }
589
590
1.83G
                            if self.bits_left < 1 {
591
29.1M
                                self.refill(reader)?;
592
1.80G
                            }
593
                        } else {
594
401M
                            r -= 1;
595
596
401M
                            if r < 0 {
597
                                // reached target zero coefficient.
598
397M
                                break 'advance_nonzero;
599
3.25M
                            }
600
                        };
601
602
1.83G
                        if k == self.spec_end {
603
31.2M
                            break 'advance_nonzero;
604
1.80G
                        }
605
606
1.80G
                        k += 1;
607
                    }
608
1.83M
                }
609
610
430M
                if symbol != 0 {
611
430M
                    let pos = UN_ZIGZAG[k as usize & 63];
612
430M
                    // output new non-zero coefficient.
613
430M
                    block[pos & 63] = symbol as i16;
614
430M
                }
615
616
430M
                k += 1;
617
618
430M
                if k > self.spec_end {
619
40.5M
                    break 'no_eob;
620
390M
                }
621
            }
622
4.01M
        }
623
60.4M
        if self.eob_run > 0 {
624
            // only run if block does not consists of purely zeroes
625
19.9M
            if &block[1..] != &[0; 63] {
626
6.72M
                self.refill(reader)?;
627
628
135M
                while k <= self.spec_end {
629
129M
                    let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
630
631
129M
                    if *coefficient != 0 && self.get_bit() == 1 {
632
                        // check if we already modified it, if so do nothing, otherwise
633
                        // append the correction bit.
634
17.8M
                        if (*coefficient & bit) == 0 {
635
3.47M
                            if *coefficient >= 0 {
636
365k
                                *coefficient = coefficient.wrapping_add(bit);
637
3.11M
                            } else {
638
3.11M
                                *coefficient = coefficient.wrapping_sub(bit);
639
3.11M
                            }
640
14.3M
                        }
641
111M
                    }
642
129M
                    if self.bits_left < 1 {
643
                        // refill at the last possible moment
644
1.47M
                        self.refill(reader)?;
645
127M
                    }
646
129M
                    k += 1;
647
                }
648
13.2M
            }
649
            // count a block completed in EOB run
650
19.9M
            self.eob_run -= 1;
651
40.5M
        }
652
60.4M
        return Ok(true);
653
60.4M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<_>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
525
47.6M
    pub(crate) fn decode_mcu_ac_refine<T>(
526
47.6M
        &mut self, reader: &mut ZReader<T>, table: &HuffmanTable, block: &mut [i16; 64]
527
47.6M
    ) -> Result<bool, DecodeErrors>
528
47.6M
    where
529
47.6M
        T: ZByteReaderTrait
530
    {
531
47.6M
        let bit = self.successive_low_mask;
532
533
47.6M
        let mut k = self.spec_start;
534
        let (mut symbol, mut r);
535
536
47.6M
        if self.eob_run == 0 {
537
            'no_eob: loop {
538
                // Decode a coefficient from the bit stream
539
413M
                self.refill(reader)?;
540
541
413M
                symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
542
413M
                symbol = table.lookup[symbol as usize];
543
544
413M
                decode_huff!(self, symbol, table);
545
546
413M
                r = symbol >> 4;
547
413M
                symbol &= 15;
548
549
413M
                if symbol == 0 {
550
6.14M
                    if r != 15 {
551
                        // EOB run is 2^r + bits
552
6.14M
                        self.eob_run = 1 << r;
553
6.14M
                        self.eob_run += self.get_bits(r as u8);
554
                        // EOB runs are handled by the eob logic
555
6.14M
                        break 'no_eob;
556
1.32k
                    }
557
                } else {
558
406M
                    if symbol != 1 {
559
220
                        return Err(DecodeErrors::HuffmanDecode(
560
220
                            "Bad Huffman code, corrupt JPEG?".to_string()
561
220
                        ));
562
406M
                    }
563
                    // get sign bit
564
                    // We assume we have enough bits, which should be correct for sane images
565
                    // since we refill by 32 above
566
406M
                    if self.get_bit() == 1 {
567
1.08M
                        symbol = i32::from(bit);
568
405M
                    } else {
569
405M
                        symbol = i32::from(-bit);
570
405M
                    }
571
                }
572
573
                // Advance over already nonzero coefficients  appending
574
                // correction bits to the non-zeroes.
575
                // A correction bit is 1 if the absolute value of the coefficient must be increased
576
577
406M
                if k <= self.spec_end {
578
                    'advance_nonzero: loop {
579
2.09G
                        let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
580
581
2.09G
                        if *coefficient != 0 {
582
1.71G
                            if self.get_bit() == 1 && (*coefficient & bit) == 0 {
583
952k
                                if *coefficient >= 0 {
584
125k
                                    *coefficient += bit;
585
827k
                                } else {
586
827k
                                    *coefficient -= bit;
587
827k
                                }
588
1.71G
                            }
589
590
1.71G
                            if self.bits_left < 1 {
591
27.0M
                                self.refill(reader)?;
592
1.68G
                            }
593
                        } else {
594
378M
                            r -= 1;
595
596
378M
                            if r < 0 {
597
                                // reached target zero coefficient.
598
375M
                                break 'advance_nonzero;
599
2.91M
                            }
600
                        };
601
602
1.71G
                        if k == self.spec_end {
603
29.3M
                            break 'advance_nonzero;
604
1.68G
                        }
605
606
1.68G
                        k += 1;
607
                    }
608
1.81M
                }
609
610
406M
                if symbol != 0 {
611
406M
                    let pos = UN_ZIGZAG[k as usize & 63];
612
406M
                    // output new non-zero coefficient.
613
406M
                    block[pos & 63] = symbol as i16;
614
406M
                }
615
616
406M
                k += 1;
617
618
406M
                if k > self.spec_end {
619
38.0M
                    break 'no_eob;
620
368M
                }
621
            }
622
3.38M
        }
623
47.6M
        if self.eob_run > 0 {
624
            // only run if block does not consists of purely zeroes
625
9.52M
            if &block[1..] != &[0; 63] {
626
1.94M
                self.refill(reader)?;
627
628
102M
                while k <= self.spec_end {
629
100M
                    let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
630
631
100M
                    if *coefficient != 0 && self.get_bit() == 1 {
632
                        // check if we already modified it, if so do nothing, otherwise
633
                        // append the correction bit.
634
16.7M
                        if (*coefficient & bit) == 0 {
635
3.20M
                            if *coefficient >= 0 {
636
348k
                                *coefficient = coefficient.wrapping_add(bit);
637
2.85M
                            } else {
638
2.85M
                                *coefficient = coefficient.wrapping_sub(bit);
639
2.85M
                            }
640
13.5M
                        }
641
83.6M
                    }
642
100M
                    if self.bits_left < 1 {
643
                        // refill at the last possible moment
644
1.10M
                        self.refill(reader)?;
645
99.2M
                    }
646
100M
                    k += 1;
647
                }
648
7.58M
            }
649
            // count a block completed in EOB run
650
9.52M
            self.eob_run -= 1;
651
38.0M
        }
652
47.6M
        return Ok(true);
653
47.6M
    }
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
<zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<zune_core::bytestream::reader::no_std_readers::ZCursor<&[u8]>>
Line
Count
Source
525
12.8M
    pub(crate) fn decode_mcu_ac_refine<T>(
526
12.8M
        &mut self, reader: &mut ZReader<T>, table: &HuffmanTable, block: &mut [i16; 64]
527
12.8M
    ) -> Result<bool, DecodeErrors>
528
12.8M
    where
529
12.8M
        T: ZByteReaderTrait
530
    {
531
12.8M
        let bit = self.successive_low_mask;
532
533
12.8M
        let mut k = self.spec_start;
534
        let (mut symbol, mut r);
535
536
12.8M
        if self.eob_run == 0 {
537
            'no_eob: loop {
538
                // Decode a coefficient from the bit stream
539
33.8M
                self.refill(reader)?;
540
541
33.8M
                symbol = self.peek_bits::<HUFF_LOOKAHEAD>();
542
33.8M
                symbol = table.lookup[symbol as usize];
543
544
33.8M
                decode_huff!(self, symbol, table);
545
546
33.8M
                r = symbol >> 4;
547
33.8M
                symbol &= 15;
548
549
33.8M
                if symbol == 0 {
550
9.87M
                    if r != 15 {
551
                        // EOB run is 2^r + bits
552
9.82M
                        self.eob_run = 1 << r;
553
9.82M
                        self.eob_run += self.get_bits(r as u8);
554
                        // EOB runs are handled by the eob logic
555
9.82M
                        break 'no_eob;
556
45.9k
                    }
557
                } else {
558
23.9M
                    if symbol != 1 {
559
104
                        return Err(DecodeErrors::HuffmanDecode(
560
104
                            "Bad Huffman code, corrupt JPEG?".to_string()
561
104
                        ));
562
23.9M
                    }
563
                    // get sign bit
564
                    // We assume we have enough bits, which should be correct for sane images
565
                    // since we refill by 32 above
566
23.9M
                    if self.get_bit() == 1 {
567
30.2k
                        symbol = i32::from(bit);
568
23.9M
                    } else {
569
23.9M
                        symbol = i32::from(-bit);
570
23.9M
                    }
571
                }
572
573
                // Advance over already nonzero coefficients  appending
574
                // correction bits to the non-zeroes.
575
                // A correction bit is 1 if the absolute value of the coefficient must be increased
576
577
24.0M
                if k <= self.spec_end {
578
                    'advance_nonzero: loop {
579
142M
                        let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
580
581
142M
                        if *coefficient != 0 {
582
119M
                            if self.get_bit() == 1 && (*coefficient & bit) == 0 {
583
344k
                                if *coefficient >= 0 {
584
20.0k
                                    *coefficient += bit;
585
324k
                                } else {
586
324k
                                    *coefficient -= bit;
587
324k
                                }
588
119M
                            }
589
590
119M
                            if self.bits_left < 1 {
591
2.03M
                                self.refill(reader)?;
592
117M
                            }
593
                        } else {
594
22.3M
                            r -= 1;
595
596
22.3M
                            if r < 0 {
597
                                // reached target zero coefficient.
598
22.0M
                                break 'advance_nonzero;
599
339k
                            }
600
                        };
601
602
120M
                        if k == self.spec_end {
603
1.96M
                            break 'advance_nonzero;
604
118M
                        }
605
606
118M
                        k += 1;
607
                    }
608
17.3k
                }
609
610
24.0M
                if symbol != 0 {
611
23.9M
                    let pos = UN_ZIGZAG[k as usize & 63];
612
23.9M
                    // output new non-zero coefficient.
613
23.9M
                    block[pos & 63] = symbol as i16;
614
23.9M
                }
615
616
24.0M
                k += 1;
617
618
24.0M
                if k > self.spec_end {
619
2.42M
                    break 'no_eob;
620
21.5M
                }
621
            }
622
634k
        }
623
12.8M
        if self.eob_run > 0 {
624
            // only run if block does not consists of purely zeroes
625
10.4M
            if &block[1..] != &[0; 63] {
626
4.78M
                self.refill(reader)?;
627
628
33.4M
                while k <= self.spec_end {
629
28.6M
                    let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63];
630
631
28.6M
                    if *coefficient != 0 && self.get_bit() == 1 {
632
                        // check if we already modified it, if so do nothing, otherwise
633
                        // append the correction bit.
634
1.11M
                        if (*coefficient & bit) == 0 {
635
274k
                            if *coefficient >= 0 {
636
17.0k
                                *coefficient = coefficient.wrapping_add(bit);
637
257k
                            } else {
638
257k
                                *coefficient = coefficient.wrapping_sub(bit);
639
257k
                            }
640
844k
                        }
641
27.5M
                    }
642
28.6M
                    if self.bits_left < 1 {
643
                        // refill at the last possible moment
644
370k
                        self.refill(reader)?;
645
28.2M
                    }
646
28.6M
                    k += 1;
647
                }
648
5.67M
            }
649
            // count a block completed in EOB run
650
10.4M
            self.eob_run -= 1;
651
2.42M
        }
652
12.8M
        return Ok(true);
653
12.8M
    }
654
655
24.4k
    pub fn update_progressive_params(&mut self, _ah: u8, al: u8, spec_start: u8, spec_end: u8) {
656
24.4k
        self.successive_low_mask = 1i16 << al;
657
24.4k
        self.spec_start = spec_start;
658
24.4k
        self.spec_end = spec_end;
659
24.4k
    }
660
661
    /// Reset the stream if we have a restart marker
662
    ///
663
    /// Restart markers indicate drop those bits in the stream and zero out
664
    /// everything
665
    #[cold]
666
187k
    pub fn reset(&mut self) {
667
187k
        self.bits_left = 0;
668
187k
        self.marker = None;
669
187k
        self.buffer = 0;
670
187k
        self.aligned_buffer = 0;
671
187k
        self.eob_run = 0;
672
187k
    }
673
}
674
675
/// Do the equivalent of JPEG HUFF_EXTEND
676
#[inline(always)]
677
150M
fn huff_extend(x: i32, s: i32) -> i32 {
678
    // if x<s return x else return x+offset[s] where offset[s] = ( (-1<<s)+1)
679
150M
    (x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((-1) << (s)) + 1))
680
150M
}
681
682
18.4M
const fn has_zero(v: u32) -> bool {
683
    // Retrieved from Stanford bithacks
684
    // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
685
18.4M
    return !((((v & 0x7F7F_7F7F) + 0x7F7F_7F7F) | v) | 0x7F7F_7F7F) != 0;
686
18.4M
}
687
688
18.4M
const fn has_byte(b: u32, val: u8) -> bool {
689
    // Retrieved from Stanford bithacks
690
    // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord
691
18.4M
    has_zero(b ^ ((!0_u32 / 255) * (val as u32)))
692
18.4M
}
693
694
// mod tests {
695
//     use zune_core::bytestream::ZCursor;
696
//     use zune_core::colorspace::ColorSpace;
697
//     use zune_core::options::DecoderOptions;
698
//
699
//     use crate::errors::DecodeErrors;
700
//     use crate::JpegDecoder;
701
//
702
//     #[test]
703
//     fn test_image() {
704
//         let img = "/Users/etemesi/Downloads/nepo.jpg";
705
//         let data = std::fs::read(img).unwrap();
706
//         let options = DecoderOptions::new_cmd().jpeg_set_out_colorspace(ColorSpace::RGB);
707
//         let mut decoder = JpegDecoder::new_with_options(ZCursor::new(&data[..]), options);
708
//
709
//         decoder.decode().unwrap();
710
//         println!("{:?}",decoder.options.jpeg_get_out_colorspace())
711
//
712
//     }
713
// }