/rust/registry/src/index.crates.io-1949cf8c6b5b557f/jpeg-encoder-0.6.1/src/writer.rs
Line | Count | Source |
1 | | use crate::encoder::Component; |
2 | | use crate::huffman::{CodingClass, HuffmanTable}; |
3 | | use crate::marker::{Marker, SOFType}; |
4 | | use crate::quantization::QuantizationTable; |
5 | | use crate::EncodingError; |
6 | | |
7 | | /// Density settings |
8 | | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
9 | | pub enum Density { |
10 | | /// No pixel density is set, which means "1 pixel per pixel" |
11 | | None, |
12 | | |
13 | | /// Horizontal and vertical dots per inch (dpi) |
14 | | Inch { x: u16, y: u16 }, |
15 | | |
16 | | /// Horizontal and vertical dots per centimeters |
17 | | Centimeter { x: u16, y: u16 }, |
18 | | } |
19 | | |
20 | | /// Zig-zag sequence of quantized DCT coefficients |
21 | | /// |
22 | | /// Figure A.6 |
23 | | pub static ZIGZAG: [u8; 64] = [ |
24 | | 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, |
25 | | 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, |
26 | | 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, |
27 | | ]; |
28 | | |
29 | | const BUFFER_SIZE: usize = core::mem::size_of::<usize>() * 8; |
30 | | |
31 | | /// A no_std alternative for `std::io::Write` |
32 | | /// |
33 | | /// An implementation of a subset of `std::io::Write` necessary to use the encoder without `std`. |
34 | | /// This trait is implemented for `std::io::Write` if the `std` feature is enabled. |
35 | | pub trait JfifWrite { |
36 | | /// Writes the whole buffer. The behavior must be identical to std::io::Write::write_all |
37 | | /// # Errors |
38 | | /// |
39 | | /// Return an error if the data can't be written |
40 | | fn write_all(&mut self, buf: &[u8]) -> Result<(), EncodingError>; |
41 | | } |
42 | | |
43 | | #[cfg(not(feature = "std"))] |
44 | | impl<W: JfifWrite + ?Sized> JfifWrite for &mut W { |
45 | | fn write_all(&mut self, buf: &[u8]) -> Result<(), EncodingError> { |
46 | | (**self).write_all(buf) |
47 | | } |
48 | | } |
49 | | |
50 | | #[cfg(not(feature = "std"))] |
51 | | impl JfifWrite for alloc::vec::Vec<u8> { |
52 | | fn write_all(&mut self, buf: &[u8]) -> Result<(), EncodingError> { |
53 | | self.extend_from_slice(buf); |
54 | | Ok(()) |
55 | | } |
56 | | } |
57 | | |
58 | | #[cfg(feature = "std")] |
59 | | impl<W: std::io::Write + ?Sized> JfifWrite for W { |
60 | | #[inline(always)] |
61 | 0 | fn write_all(&mut self, buf: &[u8]) -> Result<(), EncodingError> { |
62 | 0 | self.write_all(buf)?; |
63 | 0 | Ok(()) |
64 | 0 | } Unexecuted instantiation: <_ as jpeg_encoder::writer::JfifWrite>::write_all Unexecuted instantiation: <&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>> as jpeg_encoder::writer::JfifWrite>::write_all |
65 | | } |
66 | | |
67 | | pub(crate) struct JfifWriter<W: JfifWrite> { |
68 | | w: W, |
69 | | bit_buffer: usize, |
70 | | free_bits: i8, |
71 | | } |
72 | | |
73 | | impl<W: JfifWrite> JfifWriter<W> { |
74 | 0 | pub fn new(w: W) -> Self { |
75 | 0 | JfifWriter { |
76 | 0 | w, |
77 | 0 | bit_buffer: 0, |
78 | 0 | free_bits: BUFFER_SIZE as i8, |
79 | 0 | } |
80 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::new Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::new |
81 | | |
82 | | #[inline(always)] |
83 | 0 | pub fn write(&mut self, buf: &[u8]) -> Result<(), EncodingError> { |
84 | 0 | self.w.write_all(buf) |
85 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write |
86 | | |
87 | | #[inline(always)] |
88 | 0 | pub fn write_u8(&mut self, value: u8) -> Result<(), EncodingError> { |
89 | 0 | self.w.write_all(&[value]) |
90 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_u8 Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_u8 |
91 | | |
92 | | #[inline(always)] |
93 | 0 | pub fn write_u16(&mut self, value: u16) -> Result<(), EncodingError> { |
94 | 0 | self.w.write_all(&value.to_be_bytes()) |
95 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_u16 Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_u16 |
96 | | |
97 | 0 | pub fn finalize_bit_buffer(&mut self) -> Result<(), EncodingError> { |
98 | 0 | self.write_bits(0x7F, 7)?; |
99 | 0 | self.flush_bit_buffer()?; |
100 | 0 | self.bit_buffer = 0; |
101 | 0 | self.free_bits = BUFFER_SIZE as i8; |
102 | | |
103 | 0 | Ok(()) |
104 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::finalize_bit_buffer Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::finalize_bit_buffer |
105 | | |
106 | 0 | pub fn flush_bit_buffer(&mut self) -> Result<(), EncodingError> { |
107 | 0 | while self.free_bits <= (BUFFER_SIZE as i8 - 8) { |
108 | 0 | self.flush_byte_from_bit_buffer(self.free_bits)?; |
109 | 0 | self.free_bits += 8; |
110 | | } |
111 | | |
112 | 0 | Ok(()) |
113 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::flush_bit_buffer Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::flush_bit_buffer |
114 | | |
115 | | #[inline(always)] |
116 | 0 | fn flush_byte_from_bit_buffer(&mut self, free_bits: i8) -> Result<(), EncodingError> { |
117 | 0 | let value = (self.bit_buffer >> (BUFFER_SIZE as i8 - 8 - free_bits)) & 0xFF; |
118 | | |
119 | 0 | self.write_u8(value as u8)?; |
120 | | |
121 | 0 | if value == 0xFF { |
122 | 0 | self.write_u8(0x00)?; |
123 | 0 | } |
124 | | |
125 | 0 | Ok(()) |
126 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::flush_byte_from_bit_buffer Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::flush_byte_from_bit_buffer |
127 | | |
128 | | #[inline(always)] |
129 | | #[allow(overflowing_literals)] |
130 | 0 | fn write_bit_buffer(&mut self) -> Result<(), EncodingError> { |
131 | 0 | if (self.bit_buffer |
132 | 0 | & 0x8080808080808080 |
133 | 0 | & !(self.bit_buffer.wrapping_add(0x0101010101010101))) |
134 | 0 | != 0 |
135 | | { |
136 | 0 | for i in 0..(BUFFER_SIZE / 8) { |
137 | 0 | self.flush_byte_from_bit_buffer((i * 8) as i8)?; |
138 | | } |
139 | 0 | Ok(()) |
140 | | } else { |
141 | 0 | self.w.write_all(&self.bit_buffer.to_be_bytes()) |
142 | | } |
143 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_bit_buffer Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_bit_buffer |
144 | | |
145 | 0 | pub fn write_bits(&mut self, value: u32, size: u8) -> Result<(), EncodingError> { |
146 | 0 | let size = size as i8; |
147 | 0 | let value = value as usize; |
148 | | |
149 | 0 | let free_bits = self.free_bits - size; |
150 | | |
151 | 0 | if free_bits < 0 { |
152 | 0 | self.bit_buffer = (self.bit_buffer << (size + free_bits)) | (value >> -free_bits); |
153 | 0 | self.write_bit_buffer()?; |
154 | 0 | self.bit_buffer = value; |
155 | 0 | self.free_bits = free_bits + BUFFER_SIZE as i8; |
156 | 0 | } else { |
157 | 0 | self.free_bits = free_bits; |
158 | 0 | self.bit_buffer = (self.bit_buffer << size) | value; |
159 | 0 | } |
160 | 0 | Ok(()) |
161 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_bits Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_bits |
162 | | |
163 | 0 | pub fn write_marker(&mut self, marker: Marker) -> Result<(), EncodingError> { |
164 | 0 | self.write(&[0xFF, marker.into()]) |
165 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_marker Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_marker |
166 | | |
167 | 0 | pub fn write_segment(&mut self, marker: Marker, data: &[u8]) -> Result<(), EncodingError> { |
168 | 0 | self.write_marker(marker)?; |
169 | 0 | self.write_u16(data.len() as u16 + 2)?; |
170 | 0 | self.write(data)?; |
171 | | |
172 | 0 | Ok(()) |
173 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_segment Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_segment |
174 | | |
175 | 0 | pub fn write_header(&mut self, density: &Density) -> Result<(), EncodingError> { |
176 | 0 | self.write_marker(Marker::APP(0))?; |
177 | 0 | self.write_u16(16)?; |
178 | | |
179 | 0 | self.write(b"JFIF\0")?; |
180 | 0 | self.write(&[0x01, 0x02])?; |
181 | | |
182 | 0 | match *density { |
183 | | Density::None => { |
184 | 0 | self.write_u8(0x00)?; |
185 | 0 | self.write_u16(1)?; |
186 | 0 | self.write_u16(1)?; |
187 | | } |
188 | 0 | Density::Inch { x, y } => { |
189 | 0 | self.write_u8(0x01)?; |
190 | 0 | self.write_u16(x)?; |
191 | 0 | self.write_u16(y)?; |
192 | | } |
193 | 0 | Density::Centimeter { x, y } => { |
194 | 0 | self.write_u8(0x02)?; |
195 | 0 | self.write_u16(x)?; |
196 | 0 | self.write_u16(y)?; |
197 | | } |
198 | | } |
199 | | |
200 | 0 | self.write(&[0x00, 0x00]) |
201 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_header Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_header |
202 | | |
203 | | /// Append huffman table segment |
204 | | /// |
205 | | /// - `class`: 0 for DC or 1 for AC |
206 | | /// - `dest`: 0 for luma or 1 for chroma tables |
207 | | /// |
208 | | /// Layout: |
209 | | /// ```txt |
210 | | /// |--------|---------------|--------------------------|--------------------|--------| |
211 | | /// | 0xFFC4 | 16 bit length | 4 bit class / 4 bit dest | 16 byte num codes | values | |
212 | | /// |--------|---------------|--------------------------|--------------------|--------| |
213 | | /// ``` |
214 | | /// |
215 | 0 | pub fn write_huffman_segment( |
216 | 0 | &mut self, |
217 | 0 | class: CodingClass, |
218 | 0 | destination: u8, |
219 | 0 | table: &HuffmanTable, |
220 | 0 | ) -> Result<(), EncodingError> { |
221 | 0 | assert!(destination < 4, "Bad destination: {}", destination); |
222 | | |
223 | 0 | self.write_marker(Marker::DHT)?; |
224 | 0 | self.write_u16(2 + 1 + 16 + table.values().len() as u16)?; |
225 | | |
226 | 0 | self.write_u8(((class as u8) << 4) | destination)?; |
227 | 0 | self.write(table.length())?; |
228 | 0 | self.write(table.values())?; |
229 | | |
230 | 0 | Ok(()) |
231 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_huffman_segment Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_huffman_segment |
232 | | |
233 | | /// Append a quantization table |
234 | | /// |
235 | | /// - `precision`: 0 which means 1 byte per value. |
236 | | /// - `dest`: 0 for luma or 1 for chroma tables |
237 | | /// |
238 | | /// Layout: |
239 | | /// ```txt |
240 | | /// |--------|---------------|------------------------------|--------|--------|-----|--------| |
241 | | /// | 0xFFDB | 16 bit length | 4 bit precision / 4 bit dest | V(0,0) | V(0,1) | ... | V(7,7) | |
242 | | /// |--------|---------------|------------------------------|--------|--------|-----|--------| |
243 | | /// ``` |
244 | | /// |
245 | 0 | pub fn write_quantization_segment( |
246 | 0 | &mut self, |
247 | 0 | destination: u8, |
248 | 0 | table: &QuantizationTable, |
249 | 0 | ) -> Result<(), EncodingError> { |
250 | 0 | assert!(destination < 4, "Bad destination: {}", destination); |
251 | | |
252 | 0 | self.write_marker(Marker::DQT)?; |
253 | 0 | self.write_u16(2 + 1 + 64)?; |
254 | | |
255 | 0 | self.write_u8(destination)?; |
256 | | |
257 | 0 | for &v in ZIGZAG.iter() { |
258 | 0 | self.write_u8(table.get(v as usize))?; |
259 | | } |
260 | | |
261 | 0 | Ok(()) |
262 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_quantization_segment Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_quantization_segment |
263 | | |
264 | 0 | pub fn write_dri(&mut self, restart_interval: u16) -> Result<(), EncodingError> { |
265 | 0 | self.write_marker(Marker::DRI)?; |
266 | 0 | self.write_u16(4)?; |
267 | 0 | self.write_u16(restart_interval) |
268 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_dri Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_dri |
269 | | |
270 | | #[inline] |
271 | 0 | pub fn huffman_encode(&mut self, val: u8, table: &HuffmanTable) -> Result<(), EncodingError> { |
272 | 0 | let &(size, code) = table.get_for_value(val); |
273 | 0 | self.write_bits(code as u32, size) |
274 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::huffman_encode Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::huffman_encode |
275 | | |
276 | | #[inline] |
277 | 0 | pub fn huffman_encode_value( |
278 | 0 | &mut self, |
279 | 0 | size: u8, |
280 | 0 | symbol: u8, |
281 | 0 | value: u16, |
282 | 0 | table: &HuffmanTable, |
283 | 0 | ) -> Result<(), EncodingError> { |
284 | 0 | let &(num_bits, code) = table.get_for_value(symbol); |
285 | | |
286 | 0 | let mut temp = value as u32; |
287 | 0 | temp |= (code as u32) << size; |
288 | 0 | let size = size + num_bits; |
289 | | |
290 | 0 | self.write_bits(temp, size) |
291 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::huffman_encode_value Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::huffman_encode_value |
292 | | |
293 | 0 | pub fn write_block( |
294 | 0 | &mut self, |
295 | 0 | block: &[i16; 64], |
296 | 0 | prev_dc: i16, |
297 | 0 | dc_table: &HuffmanTable, |
298 | 0 | ac_table: &HuffmanTable, |
299 | 0 | ) -> Result<(), EncodingError> { |
300 | 0 | self.write_dc(block[0], prev_dc, dc_table)?; |
301 | 0 | self.write_ac_block(block, 1, 64, ac_table) |
302 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_block Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_block |
303 | | |
304 | 0 | pub fn write_dc( |
305 | 0 | &mut self, |
306 | 0 | value: i16, |
307 | 0 | prev_dc: i16, |
308 | 0 | dc_table: &HuffmanTable, |
309 | 0 | ) -> Result<(), EncodingError> { |
310 | 0 | let diff = value - prev_dc; |
311 | 0 | let (size, value) = get_code(diff); |
312 | | |
313 | 0 | self.huffman_encode_value(size, size, value, dc_table)?; |
314 | | |
315 | 0 | Ok(()) |
316 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_dc Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_dc |
317 | | |
318 | 0 | pub fn write_ac_block( |
319 | 0 | &mut self, |
320 | 0 | block: &[i16; 64], |
321 | 0 | start: usize, |
322 | 0 | end: usize, |
323 | 0 | ac_table: &HuffmanTable, |
324 | 0 | ) -> Result<(), EncodingError> { |
325 | 0 | let mut zero_run = 0; |
326 | | |
327 | 0 | for &value in &block[start..end] { |
328 | 0 | if value == 0 { |
329 | 0 | zero_run += 1; |
330 | 0 | } else { |
331 | 0 | while zero_run > 15 { |
332 | 0 | self.huffman_encode(0xF0, ac_table)?; |
333 | 0 | zero_run -= 16; |
334 | | } |
335 | | |
336 | 0 | let (size, value) = get_code(value); |
337 | 0 | let symbol = (zero_run << 4) | size; |
338 | | |
339 | 0 | self.huffman_encode_value(size, symbol, value, ac_table)?; |
340 | | |
341 | 0 | zero_run = 0; |
342 | | } |
343 | | } |
344 | | |
345 | 0 | if zero_run > 0 { |
346 | 0 | self.huffman_encode(0x00, ac_table)?; |
347 | 0 | } |
348 | | |
349 | 0 | Ok(()) |
350 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_ac_block Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_ac_block |
351 | | |
352 | 0 | pub fn write_frame_header( |
353 | 0 | &mut self, |
354 | 0 | width: u16, |
355 | 0 | height: u16, |
356 | 0 | components: &[Component], |
357 | 0 | progressive: bool, |
358 | 0 | ) -> Result<(), EncodingError> { |
359 | 0 | if progressive { |
360 | 0 | self.write_marker(Marker::SOF(SOFType::ProgressiveDCT))?; |
361 | | } else { |
362 | 0 | self.write_marker(Marker::SOF(SOFType::BaselineDCT))?; |
363 | | } |
364 | | |
365 | 0 | self.write_u16(2 + 1 + 2 + 2 + 1 + (components.len() as u16) * 3)?; |
366 | | |
367 | | // Precision |
368 | 0 | self.write_u8(8)?; |
369 | | |
370 | 0 | self.write_u16(height)?; |
371 | 0 | self.write_u16(width)?; |
372 | | |
373 | 0 | self.write_u8(components.len() as u8)?; |
374 | | |
375 | 0 | for component in components.iter() { |
376 | 0 | self.write_u8(component.id)?; |
377 | 0 | self.write_u8( |
378 | 0 | (component.horizontal_sampling_factor << 4) | component.vertical_sampling_factor, |
379 | 0 | )?; |
380 | 0 | self.write_u8(component.quantization_table)?; |
381 | | } |
382 | | |
383 | 0 | Ok(()) |
384 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_frame_header Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_frame_header |
385 | | |
386 | 0 | pub fn write_scan_header( |
387 | 0 | &mut self, |
388 | 0 | components: &[&Component], |
389 | 0 | spectral: Option<(u8, u8)>, |
390 | 0 | ) -> Result<(), EncodingError> { |
391 | 0 | self.write_marker(Marker::SOS)?; |
392 | | |
393 | 0 | self.write_u16(2 + 1 + (components.len() as u16) * 2 + 3)?; |
394 | | |
395 | 0 | self.write_u8(components.len() as u8)?; |
396 | | |
397 | 0 | for component in components.iter() { |
398 | 0 | self.write_u8(component.id)?; |
399 | 0 | self.write_u8((component.dc_huffman_table << 4) | component.ac_huffman_table)?; |
400 | | } |
401 | | |
402 | 0 | let (spectral_start, spectral_end) = spectral.unwrap_or((0, 63)); |
403 | | |
404 | | // Start of spectral or predictor selection |
405 | 0 | self.write_u8(spectral_start)?; |
406 | | |
407 | | // End of spectral selection |
408 | 0 | self.write_u8(spectral_end)?; |
409 | | |
410 | | // Successive approximation bit position high and low |
411 | 0 | self.write_u8(0)?; |
412 | | |
413 | 0 | Ok(()) |
414 | 0 | } Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<_>>::write_scan_header Unexecuted instantiation: <jpeg_encoder::writer::JfifWriter<&mut std::io::cursor::Cursor<alloc::vec::Vec<u8>>>>::write_scan_header |
415 | | } |
416 | | |
417 | | #[inline] |
418 | 0 | pub(crate) fn get_code(value: i16) -> (u8, u16) { |
419 | 0 | let temp = value - (value.is_negative() as i16); |
420 | 0 | let temp2 = value.abs(); |
421 | | |
422 | | /* |
423 | | * Doing this instead of 16 - temp2.leading_zeros() |
424 | | * Gives the compiler the information that leadings_zeros |
425 | | * is always called on a non zero value, which removes a branch on x86 |
426 | | */ |
427 | 0 | let num_bits = 15 - (temp2 << 1 | 1).leading_zeros() as u16; |
428 | | |
429 | 0 | let coefficient = temp & ((1 << num_bits as usize) - 1); |
430 | | |
431 | 0 | (num_bits as u8, coefficient as u16) |
432 | 0 | } Unexecuted instantiation: jpeg_encoder::writer::get_code Unexecuted instantiation: jpeg_encoder::writer::get_code |