/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zune-jpeg-0.4.21/src/bitstream.rs
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2023. |
3 | | * |
4 | | * This software is free software; |
5 | | * |
6 | | * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license |
7 | | */ |
8 | | |
9 | | #![allow( |
10 | | clippy::if_not_else, |
11 | | clippy::similar_names, |
12 | | clippy::inline_always, |
13 | | clippy::doc_markdown, |
14 | | clippy::cast_sign_loss, |
15 | | clippy::cast_possible_truncation |
16 | | )] |
17 | | |
18 | | //! This file exposes a single struct that can decode a huffman encoded |
19 | | //! Bitstream in a JPEG file |
20 | | //! |
21 | | //! This code is optimized for speed. |
22 | | //! It's meant to be super duper super fast, because everyone else depends on this being fast. |
23 | | //! It's (annoyingly) serial hence we cant use parallel bitstreams(it's variable length coding.) |
24 | | //! |
25 | | //! Furthermore, on the case of refills, we have to do bytewise processing because the standard decided |
26 | | //! that we want to support markers in the middle of streams(seriously few people use RST markers). |
27 | | //! |
28 | | //! So we pull in all optimization steps: |
29 | | //! - use `inline[always]`? ✅ , |
30 | | //! - pre-execute most common cases ✅, |
31 | | //! - add random comments ✅ |
32 | | //! - fast paths ✅. |
33 | | //! |
34 | | //! Speed-wise: It is probably the fastest JPEG BitStream decoder to ever sail the seven seas because of |
35 | | //! a couple of optimization tricks. |
36 | | //! 1. Fast refills from libjpeg-turbo |
37 | | //! 2. As few as possible branches in decoder fast paths. |
38 | | //! 3. Accelerated AC table decoding borrowed from stb_image.h written by Fabian Gissen (@ rygorous), |
39 | | //! improved by me to handle more cases. |
40 | | //! 4. Safe and extensible routines(e.g. cool ways to eliminate bounds check) |
41 | | //! 5. No unsafe here |
42 | | //! |
43 | | //! Readability comes as a second priority(I tried with variable names this time, and we are wayy better than libjpeg). |
44 | | //! |
45 | | //! Anyway if you are reading this it means your cool and I hope you get whatever part of the code you are looking for |
46 | | //! (or learn something cool) |
47 | | //! |
48 | | //! Knock yourself out. |
49 | | use alloc::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 | 556 | pub(crate) const fn new() -> BitStream { |
135 | 556 | BitStream { |
136 | 556 | buffer: 0, |
137 | 556 | aligned_buffer: 0, |
138 | 556 | bits_left: 0, |
139 | 556 | marker: None, |
140 | 556 | successive_high: 0, |
141 | 556 | successive_low: 0, |
142 | 556 | spec_start: 0, |
143 | 556 | spec_end: 0, |
144 | 556 | eob_run: 0, |
145 | 556 | overread_by: 0, |
146 | 556 | seen_eoi: false, |
147 | 556 | } |
148 | 556 | } |
149 | | |
150 | | /// Create a new Bitstream for progressive decoding |
151 | | #[allow(clippy::redundant_field_names)] |
152 | 1.92k | pub(crate) fn new_progressive(ah: u8, al: u8, spec_start: u8, spec_end: u8) -> BitStream { |
153 | 1.92k | BitStream { |
154 | 1.92k | buffer: 0, |
155 | 1.92k | aligned_buffer: 0, |
156 | 1.92k | bits_left: 0, |
157 | 1.92k | marker: None, |
158 | 1.92k | successive_high: ah, |
159 | 1.92k | successive_low: al, |
160 | 1.92k | spec_start: spec_start, |
161 | 1.92k | spec_end: spec_end, |
162 | 1.92k | eob_run: 0, |
163 | 1.92k | overread_by: 0, |
164 | 1.92k | seen_eoi: false, |
165 | 1.92k | } |
166 | 1.92k | } |
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 | 538M | pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors> |
177 | 538M | where |
178 | 538M | T: ZReaderTrait |
179 | | { |
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 | 538M | if self.bits_left < 32 { |
236 | 69.6M | 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 | 66.9M | self.buffer <<= 32; |
242 | 66.9M | self.bits_left += 32; |
243 | 66.9M | self.aligned_buffer = self.buffer << (64 - self.bits_left); |
244 | 66.9M | return Ok(true); |
245 | 2.64M | } |
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.64M | 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.64M | let msb_buf = u32::from_be_bytes(bytes); |
260 | | // check if we have 0xff |
261 | 2.64M | if !has_byte(msb_buf, 255) { |
262 | 1.91M | self.bits_left += 32; |
263 | 1.91M | self.buffer <<= 32; |
264 | 1.91M | self.buffer |= u64::from(msb_buf); |
265 | 1.91M | self.aligned_buffer = self.buffer << (64 - self.bits_left); |
266 | 1.91M | return Ok(true); |
267 | 732k | } |
268 | | |
269 | 732k | reader.rewind(4); |
270 | 1.01k | } |
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 | 733k | refill!(self.buffer, byte, self.bits_left); |
278 | 577k | refill!(self.buffer, byte, self.bits_left); |
279 | 476k | refill!(self.buffer, byte, self.bits_left); |
280 | 383k | refill!(self.buffer, byte, self.bits_left); |
281 | | // Construct an MSB buffer whose top bits are the bitstream we are currently holding. |
282 | 238k | self.aligned_buffer = self.buffer << (64 - self.bits_left); |
283 | 468M | } |
284 | 469M | return Ok(true); |
285 | 538M | } 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 | 538M | pub(crate) fn refill<T>(&mut self, reader: &mut ZByteReader<T>) -> Result<bool, DecodeErrors> | 177 | 538M | where | 178 | 538M | T: ZReaderTrait | 179 | | { | 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 | 538M | if self.bits_left < 32 { | 236 | 69.6M | 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 | 66.9M | self.buffer <<= 32; | 242 | 66.9M | self.bits_left += 32; | 243 | 66.9M | self.aligned_buffer = self.buffer << (64 - self.bits_left); | 244 | 66.9M | return Ok(true); | 245 | 2.64M | } | 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.64M | 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.64M | let msb_buf = u32::from_be_bytes(bytes); | 260 | | // check if we have 0xff | 261 | 2.64M | if !has_byte(msb_buf, 255) { | 262 | 1.91M | self.bits_left += 32; | 263 | 1.91M | self.buffer <<= 32; | 264 | 1.91M | self.buffer |= u64::from(msb_buf); | 265 | 1.91M | self.aligned_buffer = self.buffer << (64 - self.bits_left); | 266 | 1.91M | return Ok(true); | 267 | 732k | } | 268 | | | 269 | 732k | reader.rewind(4); | 270 | 1.01k | } | 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 | 733k | refill!(self.buffer, byte, self.bits_left); | 278 | 577k | refill!(self.buffer, byte, self.bits_left); | 279 | 476k | refill!(self.buffer, byte, self.bits_left); | 280 | 383k | refill!(self.buffer, byte, self.bits_left); | 281 | | // Construct an MSB buffer whose top bits are the bitstream we are currently holding. | 282 | 238k | self.aligned_buffer = self.buffer << (64 - self.bits_left); | 283 | 468M | } | 284 | 469M | return Ok(true); | 285 | 538M | } |
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>> 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]> |
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 | 40.0M | fn decode_dc<T>( |
297 | 40.0M | &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32 |
298 | 40.0M | ) -> Result<bool, DecodeErrors> |
299 | 40.0M | where |
300 | 40.0M | T: ZReaderTrait |
301 | | { |
302 | | let (mut symbol, r); |
303 | | |
304 | 40.0M | if self.bits_left < 32 { |
305 | 5.23M | self.refill(reader)?; |
306 | 34.7M | }; |
307 | | // look a head HUFF_LOOKAHEAD bits into the bitstream |
308 | 40.0M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); |
309 | 40.0M | symbol = dc_table.lookup[symbol as usize]; |
310 | | |
311 | 40.0M | decode_huff!(self, symbol, dc_table); |
312 | | |
313 | 40.0M | if symbol != 0 { |
314 | 22.6M | r = self.get_bits(symbol as u8); |
315 | 22.6M | symbol = huff_extend(r, symbol); |
316 | 22.6M | } |
317 | | // Update DC prediction |
318 | 40.0M | *dc_prediction = dc_prediction.wrapping_add(symbol); |
319 | | |
320 | 40.0M | return Ok(true); |
321 | 40.0M | } 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 | 40.0M | fn decode_dc<T>( | 297 | 40.0M | &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, dc_prediction: &mut i32 | 298 | 40.0M | ) -> Result<bool, DecodeErrors> | 299 | 40.0M | where | 300 | 40.0M | T: ZReaderTrait | 301 | | { | 302 | | let (mut symbol, r); | 303 | | | 304 | 40.0M | if self.bits_left < 32 { | 305 | 5.23M | self.refill(reader)?; | 306 | 34.7M | }; | 307 | | // look a head HUFF_LOOKAHEAD bits into the bitstream | 308 | 40.0M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); | 309 | 40.0M | symbol = dc_table.lookup[symbol as usize]; | 310 | | | 311 | 40.0M | decode_huff!(self, symbol, dc_table); | 312 | | | 313 | 40.0M | if symbol != 0 { | 314 | 22.6M | r = self.get_bits(symbol as u8); | 315 | 22.6M | symbol = huff_extend(r, symbol); | 316 | 22.6M | } | 317 | | // Update DC prediction | 318 | 40.0M | *dc_prediction = dc_prediction.wrapping_add(symbol); | 319 | | | 320 | 40.0M | return Ok(true); | 321 | 40.0M | } |
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>> 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]> |
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 | 8.34M | pub fn decode_mcu_block<T>( |
339 | 8.34M | &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable, |
340 | 8.34M | qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32 |
341 | 8.34M | ) -> Result<(), DecodeErrors> |
342 | 8.34M | where |
343 | 8.34M | T: ZReaderTrait |
344 | | { |
345 | | // Get fast AC table as a reference before we enter the hot path |
346 | 8.34M | let ac_lookup = ac_table.ac_lookup.as_ref().unwrap(); |
347 | | |
348 | | let (mut symbol, mut r, mut fast_ac); |
349 | | // Decode AC coefficients |
350 | 8.34M | let mut pos: usize = 1; |
351 | | |
352 | | // decode DC, dc prediction will contain the value |
353 | 8.34M | self.decode_dc(reader, dc_table, dc_prediction)?; |
354 | | |
355 | | // set dc to be the dc prediction. |
356 | 8.34M | block[0] = *dc_prediction * qt_table[0]; |
357 | | |
358 | 378M | while pos < 64 { |
359 | 372M | self.refill(reader)?; |
360 | 372M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); |
361 | 372M | fast_ac = ac_lookup[symbol as usize]; |
362 | 372M | symbol = ac_table.lookup[symbol as usize]; |
363 | | |
364 | 372M | if fast_ac != 0 { |
365 | 369M | // FAST AC path |
366 | 369M | pos += ((fast_ac >> 4) & 15) as usize; // run |
367 | 369M | let t_pos = UN_ZIGZAG[min(pos, 63)] & 63; |
368 | 369M | |
369 | 369M | block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value |
370 | 369M | self.drop_bits((fast_ac & 15) as u8); |
371 | 369M | pos += 1; |
372 | 369M | } else { |
373 | 2.64M | decode_huff!(self, symbol, ac_table); |
374 | | |
375 | 2.64M | r = symbol >> 4; |
376 | 2.64M | symbol &= 15; |
377 | | |
378 | 2.64M | if symbol != 0 { |
379 | 172k | pos += r as usize; |
380 | 172k | r = self.get_bits(symbol as u8); |
381 | 172k | symbol = huff_extend(r, symbol); |
382 | 172k | let t_pos = UN_ZIGZAG[pos & 63] & 63; |
383 | 172k | |
384 | 172k | block[t_pos] = symbol * qt_table[t_pos]; |
385 | 172k | |
386 | 172k | pos += 1; |
387 | 2.47M | } else if r != 15 { |
388 | 2.47M | return Ok(()); |
389 | 534 | } else { |
390 | 534 | pos += 16; |
391 | 534 | } |
392 | | } |
393 | | } |
394 | 5.86M | return Ok(()); |
395 | 8.34M | } 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 | 8.34M | pub fn decode_mcu_block<T>( | 339 | 8.34M | &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, ac_table: &HuffmanTable, | 340 | 8.34M | qt_table: &[i32; DCT_BLOCK], block: &mut [i32; 64], dc_prediction: &mut i32 | 341 | 8.34M | ) -> Result<(), DecodeErrors> | 342 | 8.34M | where | 343 | 8.34M | T: ZReaderTrait | 344 | | { | 345 | | // Get fast AC table as a reference before we enter the hot path | 346 | 8.34M | let ac_lookup = ac_table.ac_lookup.as_ref().unwrap(); | 347 | | | 348 | | let (mut symbol, mut r, mut fast_ac); | 349 | | // Decode AC coefficients | 350 | 8.34M | let mut pos: usize = 1; | 351 | | | 352 | | // decode DC, dc prediction will contain the value | 353 | 8.34M | self.decode_dc(reader, dc_table, dc_prediction)?; | 354 | | | 355 | | // set dc to be the dc prediction. | 356 | 8.34M | block[0] = *dc_prediction * qt_table[0]; | 357 | | | 358 | 378M | while pos < 64 { | 359 | 372M | self.refill(reader)?; | 360 | 372M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); | 361 | 372M | fast_ac = ac_lookup[symbol as usize]; | 362 | 372M | symbol = ac_table.lookup[symbol as usize]; | 363 | | | 364 | 372M | if fast_ac != 0 { | 365 | 369M | // FAST AC path | 366 | 369M | pos += ((fast_ac >> 4) & 15) as usize; // run | 367 | 369M | let t_pos = UN_ZIGZAG[min(pos, 63)] & 63; | 368 | 369M | | 369 | 369M | block[t_pos] = i32::from(fast_ac >> 8) * (qt_table[t_pos]); // Value | 370 | 369M | self.drop_bits((fast_ac & 15) as u8); | 371 | 369M | pos += 1; | 372 | 369M | } else { | 373 | 2.64M | decode_huff!(self, symbol, ac_table); | 374 | | | 375 | 2.64M | r = symbol >> 4; | 376 | 2.64M | symbol &= 15; | 377 | | | 378 | 2.64M | if symbol != 0 { | 379 | 172k | pos += r as usize; | 380 | 172k | r = self.get_bits(symbol as u8); | 381 | 172k | symbol = huff_extend(r, symbol); | 382 | 172k | let t_pos = UN_ZIGZAG[pos & 63] & 63; | 383 | 172k | | 384 | 172k | block[t_pos] = symbol * qt_table[t_pos]; | 385 | 172k | | 386 | 172k | pos += 1; | 387 | 2.47M | } else if r != 15 { | 388 | 2.47M | return Ok(()); | 389 | 534 | } else { | 390 | 534 | pos += 16; | 391 | 534 | } | 392 | | } | 393 | | } | 394 | 5.86M | return Ok(()); | 395 | 8.34M | } |
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>> 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]> |
396 | | |
397 | | /// Peek `look_ahead` bits ahead without discarding them from the buffer |
398 | | #[inline(always)] |
399 | | #[allow(clippy::cast_possible_truncation)] |
400 | 565M | const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 { |
401 | 565M | (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32 |
402 | 565M | } 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 | 54.1k | const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 { | 401 | 54.1k | (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32 | 402 | 54.1k | } |
<zune_jpeg::bitstream::BitStream>::peek_bits::<9> Line | Count | Source | 400 | 565M | const fn peek_bits<const LOOKAHEAD: u8>(&self) -> i32 { | 401 | 565M | (self.aligned_buffer >> (64 - LOOKAHEAD)) as i32 | 402 | 565M | } |
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<16> Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::peek_bits::<9> 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> |
403 | | |
404 | | /// Discard the next `N` bits without checking |
405 | | #[inline] |
406 | 1.04G | fn drop_bits(&mut self, n: u8) { |
407 | 1.04G | debug_assert!(self.bits_left >= n); |
408 | | //self.bits_left -= n; |
409 | 1.04G | self.bits_left = self.bits_left.saturating_sub(n); |
410 | 1.04G | self.aligned_buffer <<= n; |
411 | 1.04G | } Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits <zune_jpeg::bitstream::BitStream>::drop_bits Line | Count | Source | 406 | 475M | fn drop_bits(&mut self, n: u8) { | 407 | 475M | debug_assert!(self.bits_left >= n); | 408 | | //self.bits_left -= n; | 409 | 475M | self.bits_left = self.bits_left.saturating_sub(n); | 410 | 475M | self.aligned_buffer <<= n; | 411 | 475M | } |
<zune_jpeg::bitstream::BitStream>::drop_bits Line | Count | Source | 406 | 565M | fn drop_bits(&mut self, n: u8) { | 407 | 565M | debug_assert!(self.bits_left >= n); | 408 | | //self.bits_left -= n; | 409 | 565M | self.bits_left = self.bits_left.saturating_sub(n); | 410 | 565M | self.aligned_buffer <<= n; | 411 | 565M | } |
Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits Unexecuted instantiation: <zune_jpeg::bitstream::BitStream>::drop_bits |
412 | | |
413 | | /// Read `n_bits` from the buffer and discard them |
414 | | #[inline(always)] |
415 | | #[allow(clippy::cast_possible_truncation)] |
416 | 34.8M | fn get_bits(&mut self, n_bits: u8) -> i32 { |
417 | 34.8M | let mask = (1_u64 << n_bits) - 1; |
418 | | |
419 | 34.8M | self.aligned_buffer = self.aligned_buffer.rotate_left(u32::from(n_bits)); |
420 | 34.8M | let bits = (self.aligned_buffer & mask) as i32; |
421 | 34.8M | self.bits_left = self.bits_left.wrapping_sub(n_bits); |
422 | 34.8M | bits |
423 | 34.8M | } |
424 | | |
425 | | /// Decode a DC block |
426 | | #[allow(clippy::cast_possible_truncation)] |
427 | | #[inline] |
428 | 31.6M | pub(crate) fn decode_prog_dc_first<T>( |
429 | 31.6M | &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, block: &mut i16, |
430 | 31.6M | dc_prediction: &mut i32 |
431 | 31.6M | ) -> Result<(), DecodeErrors> |
432 | 31.6M | where |
433 | 31.6M | T: ZReaderTrait |
434 | | { |
435 | 31.6M | self.decode_dc(reader, dc_table, dc_prediction)?; |
436 | 31.6M | *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low); |
437 | 31.6M | return Ok(()); |
438 | 31.6M | } 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::<_> <zune_jpeg::bitstream::BitStream>::decode_prog_dc_first::<alloc::vec::Vec<u8>> Line | Count | Source | 428 | 31.6M | pub(crate) fn decode_prog_dc_first<T>( | 429 | 31.6M | &mut self, reader: &mut ZByteReader<T>, dc_table: &HuffmanTable, block: &mut i16, | 430 | 31.6M | dc_prediction: &mut i32 | 431 | 31.6M | ) -> Result<(), DecodeErrors> | 432 | 31.6M | where | 433 | 31.6M | T: ZReaderTrait | 434 | | { | 435 | 31.6M | self.decode_dc(reader, dc_table, dc_prediction)?; | 436 | 31.6M | *block = (*dc_prediction as i16).wrapping_mul(1_i16 << self.successive_low); | 437 | 31.6M | return Ok(()); | 438 | 31.6M | } |
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>> 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]> |
439 | | #[inline] |
440 | 21.0M | pub(crate) fn decode_prog_dc_refine<T>( |
441 | 21.0M | &mut self, reader: &mut ZByteReader<T>, block: &mut i16 |
442 | 21.0M | ) -> Result<(), DecodeErrors> |
443 | 21.0M | where |
444 | 21.0M | T: ZReaderTrait |
445 | | { |
446 | | // refinement scan |
447 | 21.0M | if self.bits_left < 1 { |
448 | 668k | self.refill(reader)?; |
449 | 20.3M | } |
450 | | |
451 | 21.0M | if self.get_bit() == 1 { |
452 | 1.21M | *block = block.wrapping_add(1 << self.successive_low); |
453 | 19.8M | } |
454 | | |
455 | 21.0M | Ok(()) |
456 | 21.0M | } 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::<_> <zune_jpeg::bitstream::BitStream>::decode_prog_dc_refine::<alloc::vec::Vec<u8>> Line | Count | Source | 440 | 21.0M | pub(crate) fn decode_prog_dc_refine<T>( | 441 | 21.0M | &mut self, reader: &mut ZByteReader<T>, block: &mut i16 | 442 | 21.0M | ) -> Result<(), DecodeErrors> | 443 | 21.0M | where | 444 | 21.0M | T: ZReaderTrait | 445 | | { | 446 | | // refinement scan | 447 | 21.0M | if self.bits_left < 1 { | 448 | 668k | self.refill(reader)?; | 449 | 20.3M | } | 450 | | | 451 | 21.0M | if self.get_bit() == 1 { | 452 | 1.21M | *block = block.wrapping_add(1 << self.successive_low); | 453 | 19.8M | } | 454 | | | 455 | 21.0M | Ok(()) | 456 | 21.0M | } |
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>> 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]> |
457 | | |
458 | | /// Get a single bit from the bitstream |
459 | 475M | fn get_bit(&mut self) -> u8 { |
460 | 475M | let k = (self.aligned_buffer >> 63) as u8; |
461 | | // discard a bit |
462 | 475M | self.drop_bits(1); |
463 | 475M | return k; |
464 | 475M | } |
465 | 13.7M | pub(crate) fn decode_mcu_ac_first<T>( |
466 | 13.7M | &mut self, reader: &mut ZByteReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64] |
467 | 13.7M | ) -> Result<bool, DecodeErrors> |
468 | 13.7M | where |
469 | 13.7M | T: ZReaderTrait |
470 | | { |
471 | 13.7M | let shift = self.successive_low; |
472 | 13.7M | let fast_ac = ac_table.ac_lookup.as_ref().unwrap(); |
473 | | |
474 | 13.7M | 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 | 17.7M | self.refill(reader)?; |
480 | | |
481 | 17.7M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); |
482 | 17.7M | fac = fast_ac[symbol as usize]; |
483 | 17.7M | symbol = ac_table.lookup[symbol as usize]; |
484 | | |
485 | 17.7M | if fac != 0 { |
486 | 6.21M | // fast ac path |
487 | 6.21M | k += ((fac >> 4) & 15) as usize; // run |
488 | 6.21M | block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value |
489 | 6.21M | self.drop_bits((fac & 15) as u8); |
490 | 6.21M | k += 1; |
491 | 6.21M | } else { |
492 | 11.5M | decode_huff!(self, symbol, ac_table); |
493 | | |
494 | 11.5M | r = symbol >> 4; |
495 | 11.5M | symbol &= 15; |
496 | | |
497 | 11.5M | if symbol != 0 { |
498 | 9.27M | k += r as usize; |
499 | 9.27M | r = self.get_bits(symbol as u8); |
500 | 9.27M | symbol = huff_extend(r, symbol); |
501 | 9.27M | block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift); |
502 | 9.27M | k += 1; |
503 | 9.27M | } else { |
504 | 2.24M | if r != 15 { |
505 | 2.22M | self.eob_run = 1 << r; |
506 | 2.22M | self.eob_run += self.get_bits(r as u8); |
507 | 2.22M | self.eob_run -= 1; |
508 | 2.22M | break; |
509 | 19.7k | } |
510 | | |
511 | 19.7k | k += 16; |
512 | | } |
513 | | } |
514 | | |
515 | 15.5M | if k > self.spec_end as usize { |
516 | 11.4M | break 'block; |
517 | 4.02M | } |
518 | | } |
519 | 13.7M | return Ok(true); |
520 | 13.7M | } 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::<_> <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_first::<alloc::vec::Vec<u8>> Line | Count | Source | 465 | 13.7M | pub(crate) fn decode_mcu_ac_first<T>( | 466 | 13.7M | &mut self, reader: &mut ZByteReader<T>, ac_table: &HuffmanTable, block: &mut [i16; 64] | 467 | 13.7M | ) -> Result<bool, DecodeErrors> | 468 | 13.7M | where | 469 | 13.7M | T: ZReaderTrait | 470 | | { | 471 | 13.7M | let shift = self.successive_low; | 472 | 13.7M | let fast_ac = ac_table.ac_lookup.as_ref().unwrap(); | 473 | | | 474 | 13.7M | 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 | 17.7M | self.refill(reader)?; | 480 | | | 481 | 17.7M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); | 482 | 17.7M | fac = fast_ac[symbol as usize]; | 483 | 17.7M | symbol = ac_table.lookup[symbol as usize]; | 484 | | | 485 | 17.7M | if fac != 0 { | 486 | 6.21M | // fast ac path | 487 | 6.21M | k += ((fac >> 4) & 15) as usize; // run | 488 | 6.21M | block[UN_ZIGZAG[min(k, 63)] & 63] = (fac >> 8).wrapping_mul(1 << shift); // value | 489 | 6.21M | self.drop_bits((fac & 15) as u8); | 490 | 6.21M | k += 1; | 491 | 6.21M | } else { | 492 | 11.5M | decode_huff!(self, symbol, ac_table); | 493 | | | 494 | 11.5M | r = symbol >> 4; | 495 | 11.5M | symbol &= 15; | 496 | | | 497 | 11.5M | if symbol != 0 { | 498 | 9.27M | k += r as usize; | 499 | 9.27M | r = self.get_bits(symbol as u8); | 500 | 9.27M | symbol = huff_extend(r, symbol); | 501 | 9.27M | block[UN_ZIGZAG[k & 63] & 63] = (symbol as i16).wrapping_mul(1 << shift); | 502 | 9.27M | k += 1; | 503 | 9.27M | } else { | 504 | 2.24M | if r != 15 { | 505 | 2.22M | self.eob_run = 1 << r; | 506 | 2.22M | self.eob_run += self.get_bits(r as u8); | 507 | 2.22M | self.eob_run -= 1; | 508 | 2.22M | break; | 509 | 19.7k | } | 510 | | | 511 | 19.7k | k += 16; | 512 | | } | 513 | | } | 514 | | | 515 | 15.5M | if k > self.spec_end as usize { | 516 | 11.4M | break 'block; | 517 | 4.02M | } | 518 | | } | 519 | 13.7M | return Ok(true); | 520 | 13.7M | } |
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>> 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]> |
521 | | #[allow(clippy::too_many_lines, clippy::op_ref)] |
522 | 28.5M | pub(crate) fn decode_mcu_ac_refine<T>( |
523 | 28.5M | &mut self, reader: &mut ZByteReader<T>, table: &HuffmanTable, block: &mut [i16; 64] |
524 | 28.5M | ) -> Result<bool, DecodeErrors> |
525 | 28.5M | where |
526 | 28.5M | T: ZReaderTrait |
527 | | { |
528 | 28.5M | let bit = (1 << self.successive_low) as i16; |
529 | | |
530 | 28.5M | let mut k = self.spec_start; |
531 | | let (mut symbol, mut r); |
532 | | |
533 | 28.5M | if self.eob_run == 0 { |
534 | | 'no_eob: loop { |
535 | | // Decode a coefficient from the bit stream |
536 | 135M | self.refill(reader)?; |
537 | | |
538 | 135M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); |
539 | 135M | symbol = table.lookup[symbol as usize]; |
540 | | |
541 | 135M | decode_huff!(self, symbol, table); |
542 | | |
543 | 135M | r = symbol >> 4; |
544 | 135M | symbol &= 15; |
545 | | |
546 | 135M | if symbol == 0 { |
547 | 574k | if r != 15 { |
548 | | // EOB run is 2^r + bits |
549 | 573k | self.eob_run = 1 << r; |
550 | 573k | self.eob_run += self.get_bits(r as u8); |
551 | | // EOB runs are handled by the eob logic |
552 | 573k | break 'no_eob; |
553 | 234 | } |
554 | | } else { |
555 | 134M | if symbol != 1 { |
556 | 126 | return Err(DecodeErrors::HuffmanDecode( |
557 | 126 | "Bad Huffman code, corrupt JPEG?".to_string() |
558 | 126 | )); |
559 | 134M | } |
560 | | // get sign bit |
561 | | // We assume we have enough bits, which should be correct for sane images |
562 | | // since we refill by 32 above |
563 | 134M | if self.get_bit() == 1 { |
564 | 94.3k | symbol = i32::from(bit); |
565 | 134M | } else { |
566 | 134M | symbol = i32::from(-bit); |
567 | 134M | } |
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 | 134M | if k <= self.spec_end { |
575 | | 'advance_nonzero: loop { |
576 | 395M | let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; |
577 | | |
578 | 395M | if *coefficient != 0 { |
579 | 277M | if self.get_bit() == 1 && (*coefficient & bit) == 0 { |
580 | 9.50k | if *coefficient >= 0 { |
581 | 5.74k | *coefficient += bit; |
582 | 5.74k | } else { |
583 | 3.76k | *coefficient -= bit; |
584 | 3.76k | } |
585 | 277M | } |
586 | | |
587 | 277M | if self.bits_left < 1 { |
588 | 950k | self.refill(reader)?; |
589 | 276M | } |
590 | | } else { |
591 | 117M | r -= 1; |
592 | | |
593 | 117M | if r < 0 { |
594 | | // reached target zero coefficient. |
595 | 117M | break 'advance_nonzero; |
596 | 13.8k | } |
597 | | }; |
598 | | |
599 | 277M | if k == self.spec_end { |
600 | 16.5M | break 'advance_nonzero; |
601 | 261M | } |
602 | | |
603 | 261M | k += 1; |
604 | | } |
605 | 929k | } |
606 | | |
607 | 134M | if symbol != 0 { |
608 | 134M | let pos = UN_ZIGZAG[k as usize & 63]; |
609 | 134M | // output new non-zero coefficient. |
610 | 134M | block[pos & 63] = symbol as i16; |
611 | 134M | } |
612 | | |
613 | 134M | k += 1; |
614 | | |
615 | 134M | if k > self.spec_end { |
616 | 22.2M | break 'no_eob; |
617 | 112M | } |
618 | | } |
619 | 5.74M | } |
620 | 28.5M | if self.eob_run > 0 { |
621 | | // only run if block does not consists of purely zeroes |
622 | 6.32M | if &block[1..] != &[0; 63] { |
623 | 6.22M | self.refill(reader)?; |
624 | | |
625 | 64.5M | while k <= self.spec_end { |
626 | 58.3M | let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; |
627 | | |
628 | 58.3M | 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.28M | if (*coefficient & bit) == 0 { |
632 | 51.9k | if *coefficient >= 0 { |
633 | 44.4k | *coefficient = coefficient.wrapping_add(bit); |
634 | 44.4k | } else { |
635 | 7.55k | *coefficient = coefficient.wrapping_sub(bit); |
636 | 7.55k | } |
637 | 2.23M | } |
638 | 56.0M | } |
639 | 58.3M | if self.bits_left < 1 { |
640 | | // refill at the last possible moment |
641 | 26.7k | self.refill(reader)?; |
642 | 58.3M | } |
643 | 58.3M | k += 1; |
644 | | } |
645 | 95.5k | } |
646 | | // count a block completed in EOB run |
647 | 6.32M | self.eob_run -= 1; |
648 | 22.2M | } |
649 | 28.5M | return Ok(true); |
650 | 28.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::<_> <zune_jpeg::bitstream::BitStream>::decode_mcu_ac_refine::<alloc::vec::Vec<u8>> Line | Count | Source | 522 | 28.5M | pub(crate) fn decode_mcu_ac_refine<T>( | 523 | 28.5M | &mut self, reader: &mut ZByteReader<T>, table: &HuffmanTable, block: &mut [i16; 64] | 524 | 28.5M | ) -> Result<bool, DecodeErrors> | 525 | 28.5M | where | 526 | 28.5M | T: ZReaderTrait | 527 | | { | 528 | 28.5M | let bit = (1 << self.successive_low) as i16; | 529 | | | 530 | 28.5M | let mut k = self.spec_start; | 531 | | let (mut symbol, mut r); | 532 | | | 533 | 28.5M | if self.eob_run == 0 { | 534 | | 'no_eob: loop { | 535 | | // Decode a coefficient from the bit stream | 536 | 135M | self.refill(reader)?; | 537 | | | 538 | 135M | symbol = self.peek_bits::<HUFF_LOOKAHEAD>(); | 539 | 135M | symbol = table.lookup[symbol as usize]; | 540 | | | 541 | 135M | decode_huff!(self, symbol, table); | 542 | | | 543 | 135M | r = symbol >> 4; | 544 | 135M | symbol &= 15; | 545 | | | 546 | 135M | if symbol == 0 { | 547 | 574k | if r != 15 { | 548 | | // EOB run is 2^r + bits | 549 | 573k | self.eob_run = 1 << r; | 550 | 573k | self.eob_run += self.get_bits(r as u8); | 551 | | // EOB runs are handled by the eob logic | 552 | 573k | break 'no_eob; | 553 | 234 | } | 554 | | } else { | 555 | 134M | if symbol != 1 { | 556 | 126 | return Err(DecodeErrors::HuffmanDecode( | 557 | 126 | "Bad Huffman code, corrupt JPEG?".to_string() | 558 | 126 | )); | 559 | 134M | } | 560 | | // get sign bit | 561 | | // We assume we have enough bits, which should be correct for sane images | 562 | | // since we refill by 32 above | 563 | 134M | if self.get_bit() == 1 { | 564 | 94.3k | symbol = i32::from(bit); | 565 | 134M | } else { | 566 | 134M | symbol = i32::from(-bit); | 567 | 134M | } | 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 | 134M | if k <= self.spec_end { | 575 | | 'advance_nonzero: loop { | 576 | 395M | let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; | 577 | | | 578 | 395M | if *coefficient != 0 { | 579 | 277M | if self.get_bit() == 1 && (*coefficient & bit) == 0 { | 580 | 9.50k | if *coefficient >= 0 { | 581 | 5.74k | *coefficient += bit; | 582 | 5.74k | } else { | 583 | 3.76k | *coefficient -= bit; | 584 | 3.76k | } | 585 | 277M | } | 586 | | | 587 | 277M | if self.bits_left < 1 { | 588 | 950k | self.refill(reader)?; | 589 | 276M | } | 590 | | } else { | 591 | 117M | r -= 1; | 592 | | | 593 | 117M | if r < 0 { | 594 | | // reached target zero coefficient. | 595 | 117M | break 'advance_nonzero; | 596 | 13.8k | } | 597 | | }; | 598 | | | 599 | 277M | if k == self.spec_end { | 600 | 16.5M | break 'advance_nonzero; | 601 | 261M | } | 602 | | | 603 | 261M | k += 1; | 604 | | } | 605 | 929k | } | 606 | | | 607 | 134M | if symbol != 0 { | 608 | 134M | let pos = UN_ZIGZAG[k as usize & 63]; | 609 | 134M | // output new non-zero coefficient. | 610 | 134M | block[pos & 63] = symbol as i16; | 611 | 134M | } | 612 | | | 613 | 134M | k += 1; | 614 | | | 615 | 134M | if k > self.spec_end { | 616 | 22.2M | break 'no_eob; | 617 | 112M | } | 618 | | } | 619 | 5.74M | } | 620 | 28.5M | if self.eob_run > 0 { | 621 | | // only run if block does not consists of purely zeroes | 622 | 6.32M | if &block[1..] != &[0; 63] { | 623 | 6.22M | self.refill(reader)?; | 624 | | | 625 | 64.5M | while k <= self.spec_end { | 626 | 58.3M | let coefficient = &mut block[UN_ZIGZAG[k as usize & 63] & 63]; | 627 | | | 628 | 58.3M | 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.28M | if (*coefficient & bit) == 0 { | 632 | 51.9k | if *coefficient >= 0 { | 633 | 44.4k | *coefficient = coefficient.wrapping_add(bit); | 634 | 44.4k | } else { | 635 | 7.55k | *coefficient = coefficient.wrapping_sub(bit); | 636 | 7.55k | } | 637 | 2.23M | } | 638 | 56.0M | } | 639 | 58.3M | if self.bits_left < 1 { | 640 | | // refill at the last possible moment | 641 | 26.7k | self.refill(reader)?; | 642 | 58.3M | } | 643 | 58.3M | k += 1; | 644 | | } | 645 | 95.5k | } | 646 | | // count a block completed in EOB run | 647 | 6.32M | self.eob_run -= 1; | 648 | 22.2M | } | 649 | 28.5M | return Ok(true); | 650 | 28.5M | } |
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>> 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]> |
651 | | |
652 | 12.2k | pub fn update_progressive_params(&mut self, ah: u8, al: u8, spec_start: u8, spec_end: u8) { |
653 | 12.2k | self.successive_high = ah; |
654 | 12.2k | self.successive_low = al; |
655 | 12.2k | self.spec_start = spec_start; |
656 | 12.2k | self.spec_end = spec_end; |
657 | 12.2k | } |
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 | 25.6k | pub fn reset(&mut self) { |
665 | 25.6k | self.bits_left = 0; |
666 | 25.6k | self.marker = None; |
667 | 25.6k | self.buffer = 0; |
668 | 25.6k | self.aligned_buffer = 0; |
669 | 25.6k | self.eob_run = 0; |
670 | 25.6k | } |
671 | | } |
672 | | |
673 | | /// Do the equivalent of JPEG HUFF_EXTEND |
674 | | #[inline(always)] |
675 | 32.0M | fn huff_extend(x: i32, s: i32) -> i32 { |
676 | | // if x<s return x else return x+offset[s] where offset[s] = ( (-1<<s)+1) |
677 | 32.0M | (x) + ((((x) - (1 << ((s) - 1))) >> 31) & (((-1) << (s)) + 1)) |
678 | 32.0M | } |
679 | | |
680 | 2.64M | const fn has_zero(v: u32) -> bool { |
681 | | // Retrieved from Stanford bithacks |
682 | | // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord |
683 | 2.64M | return !((((v & 0x7F7F_7F7F) + 0x7F7F_7F7F) | v) | 0x7F7F_7F7F) != 0; |
684 | 2.64M | } |
685 | | |
686 | 2.64M | const fn has_byte(b: u32, val: u8) -> bool { |
687 | | // Retrieved from Stanford bithacks |
688 | | // @ https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord |
689 | 2.64M | has_zero(b ^ ((!0_u32 / 255) * (val as u32))) |
690 | 2.64M | } |
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 | | // } |