/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 | | // } |