From 9ba6c2c78baef98ba693a80432235626eb3ef359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Kr=C3=B3lak?= Date: Sun, 30 Apr 2023 12:33:27 +0200 Subject: [PATCH 1/2] Rustfmt fixes --- benches/decoding_benchmark.rs | 44 ++--- examples/decode.rs | 21 +-- src/arch/wasm.rs | 19 +- src/decoder.rs | 2 +- src/huffman.rs | 170 ++++++++++++------ src/idct.rs | 61 +++---- src/marker.rs | 4 +- src/parser.rs | 328 +++++++++++++++++++++++++--------- src/upsampler.rs | 211 +++++++++++++--------- src/worker/immediate.rs | 31 +++- tests/lib.rs | 19 +- tests/rayon-0.rs | 8 +- tests/rayon-1.rs | 8 +- tests/rayon-2.rs | 6 +- tests/rayon.rs | 8 +- tests/reftest/mod.rs | 94 ++++++---- 16 files changed, 682 insertions(+), 352 deletions(-) diff --git a/benches/decoding_benchmark.rs b/benches/decoding_benchmark.rs index fb8282de..3d5a6b64 100644 --- a/benches/decoding_benchmark.rs +++ b/benches/decoding_benchmark.rs @@ -18,24 +18,28 @@ fn read_metadata(image: &[u8]) -> ImageInfo { fn main() { let mut c = Criterion::default().configure_from_args(); - c.bench_function("decode a 512x512 JPEG", |b| b.iter(|| { - read_image(include_bytes!("tower.jpg")) - })); - - c.bench_function("decode a 512x512 progressive JPEG", |b| b.iter(|| { - read_image(include_bytes!("tower_progressive.jpg")) - })); - - c.bench_function("decode a 512x512 grayscale JPEG", |b| b.iter(|| { - read_image(include_bytes!("tower_grayscale.jpg")) - })); - - c.bench_function("extract metadata from an image", |b| b.iter(|| { - read_metadata(include_bytes!("tower.jpg")) - })); - - c.bench_function("decode a 3072x2048 RGB Lossless JPEG", |b| b.iter(|| { - read_image(include_bytes!("../tests/reftest/images/lossless/jpeg_lossless_sel1-rgb.jpg")) - })); + c.bench_function("decode a 512x512 JPEG", |b| { + b.iter(|| read_image(include_bytes!("tower.jpg"))) + }); + + c.bench_function("decode a 512x512 progressive JPEG", |b| { + b.iter(|| read_image(include_bytes!("tower_progressive.jpg"))) + }); + + c.bench_function("decode a 512x512 grayscale JPEG", |b| { + b.iter(|| read_image(include_bytes!("tower_grayscale.jpg"))) + }); + + c.bench_function("extract metadata from an image", |b| { + b.iter(|| read_metadata(include_bytes!("tower.jpg"))) + }); + + c.bench_function("decode a 3072x2048 RGB Lossless JPEG", |b| { + b.iter(|| { + read_image(include_bytes!( + "../tests/reftest/images/lossless/jpeg_lossless_sel1-rgb.jpg" + )) + }) + }); c.final_summary(); -} \ No newline at end of file +} diff --git a/examples/decode.rs b/examples/decode.rs index 13934fe0..bf806c6c 100644 --- a/examples/decode.rs +++ b/examples/decode.rs @@ -32,26 +32,27 @@ fn main() { jpeg::PixelFormat::L16 => { encoder.set_depth(png::BitDepth::Sixteen); encoder.set_color(png::ColorType::Grayscale); - }, - jpeg::PixelFormat::RGB24 => { + } + jpeg::PixelFormat::RGB24 => { encoder.set_depth(png::BitDepth::Eight); encoder.set_color(png::ColorType::RGB); - }, + } jpeg::PixelFormat::CMYK32 => { data = cmyk_to_rgb(&mut data); encoder.set_depth(png::BitDepth::Eight); encoder.set_color(png::ColorType::RGB) - }, + } jpeg::PixelFormat::L8 => { encoder.set_depth(png::BitDepth::Eight); encoder.set_color(png::ColorType::Grayscale); - }, + } } - - encoder.write_header() - .expect("writing png header failed") - .write_image_data(&data) - .expect("png encoding failed"); + + encoder + .write_header() + .expect("writing png header failed") + .write_image_data(&data) + .expect("png encoding failed"); } fn cmyk_to_rgb(input: &[u8]) -> Vec { diff --git a/src/arch/wasm.rs b/src/arch/wasm.rs index 7a94551f..ec29428e 100644 --- a/src/arch/wasm.rs +++ b/src/arch/wasm.rs @@ -83,6 +83,7 @@ fn idct8(data: &mut [v128; 8]) { #[cfg(target_arch = "wasm32")] #[target_feature(enable = "simd128")] +#[rustfmt::skip] fn transpose8(data: &mut [v128; 8]) { // Transpose a 8x8 matrix with a sequence of interleaving operations. // Naming: dABl contains elements from the *l*ower halves of vectors A and B, interleaved, i.e. @@ -174,6 +175,7 @@ pub fn dequantize_and_idct_block_8x8( // SAFETY: the assert at the start of this function ensures // `output_linestride * i + 7` < output.len(), so all accesses are in-bounds. + #[rustfmt::skip] unsafe { v128_store64_lane::<0>( u8x16_narrow_i16x8( @@ -188,8 +190,12 @@ pub fn dequantize_and_idct_block_8x8( #[cfg(target_arch = "wasm32")] #[target_feature(enable = "simd128")] -pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8], output: &mut [u8]) -> usize { - +pub fn color_convert_line_ycbcr( + y_slice: &[u8], + cb_slice: &[u8], + cr_slice: &[u8], + output: &mut [u8], +) -> usize { assert!(output.len() % 3 == 0); let num = output.len() / 3; assert!(num <= y_slice.len()); @@ -241,7 +247,7 @@ pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8] let b = u8x16_narrow_i16x8(i16x8_shr(b, SHIFT), zero); // Shuffle rrrrrrrrggggggggbbbbbbbb to rgbrgbrgb... - + #[rustfmt::skip] let rg_lanes = i8x16_shuffle::<0, 16, 1, 17, 2, 18, @@ -251,6 +257,7 @@ pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8] 6, 22, 7, 23>(r, g); + #[rustfmt::skip] let rgb_low = i8x16_shuffle::<0, 1, 16, // r0, g0, b0 2, 3, 17, // r1, g1, b1 4, 5, 18, // r2, g2, b2 @@ -258,6 +265,7 @@ pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8] 8, 9, 20, // r4, g4, b4 10>(rg_lanes, b); // r5 + #[rustfmt::skip] let rgb_hi = i8x16_shuffle::<11, 21, 12, // g5, b5, r6 13, 22, 14, // g6, b6, r7 15, 23, 0, // g7, b7, -- @@ -269,7 +277,10 @@ pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8] // `output.len() - 1`. unsafe { v128_store(output.as_mut_ptr().wrapping_add(24 * i) as *mut _, rgb_low); - v128_store64_lane::<0>(rgb_hi, output.as_mut_ptr().wrapping_add(24 * i + 16) as *mut _); + v128_store64_lane::<0>( + rgb_hi, + output.as_mut_ptr().wrapping_add(24 * i + 16) as *mut _, + ); } } diff --git a/src/decoder.rs b/src/decoder.rs index 40115690..92d95ea9 100644 --- a/src/decoder.rs +++ b/src/decoder.rs @@ -778,7 +778,7 @@ impl Decoder { } } -#[allow(clippy::type_complexity)] + #[allow(clippy::type_complexity)] fn decode_scan( &mut self, frame: &FrameInfo, diff --git a/src/huffman.rs b/src/huffman.rs index fca57c1b..9a88bec0 100644 --- a/src/huffman.rs +++ b/src/huffman.rs @@ -1,12 +1,13 @@ +use crate::error::{Error, Result}; +use crate::marker::Marker; +use crate::parser::ScanInfo; +use crate::read_u8; + use alloc::borrow::ToOwned; use alloc::vec; use alloc::vec::Vec; use core::iter; use std::io::Read; -use crate::read_u8; -use crate::error::{Error, Result}; -use crate::marker::Marker; -use crate::parser::ScanInfo; const LUT_BITS: u8 = 8; @@ -38,11 +39,10 @@ impl HuffmanDecoder { if size > 0 { self.consume_bits(size); Ok(value) - } - else { + } else { let bits = self.peek_bits(16); - for i in LUT_BITS .. 16 { + for i in LUT_BITS..16 { let code = (bits >> (15 - i)) as i32; if code <= table.maxcode[i as usize] { @@ -57,7 +57,11 @@ impl HuffmanDecoder { } } - pub fn decode_fast_ac(&mut self, reader: &mut R, table: &HuffmanTable) -> Result> { + pub fn decode_fast_ac( + &mut self, + reader: &mut R, + table: &HuffmanTable, + ) -> Result> { if let Some(ref ac_lut) = table.ac_lut { if self.num_bits < LUT_BITS { self.read_bits(reader)?; @@ -144,8 +148,12 @@ impl HuffmanDecoder { } match next_byte { - 0x00 => return Err(Error::Format("FF 00 found where marker was expected".to_owned())), - _ => self.marker = Some(Marker::from_u8(next_byte).unwrap()), + 0x00 => { + return Err(Error::Format( + "FF 00 found where marker was expected".to_owned(), + )) + } + _ => self.marker = Some(Marker::from_u8(next_byte).unwrap()), } continue; @@ -198,7 +206,7 @@ impl HuffmanTable { let mut maxcode = [-1i32; 16]; let mut j = 0; - for i in 0 .. 16 { + for i in 0..16 { if bits[i] != 0 { delta[i] = j as i32 - huffcode[j] as i32; j += bits[i] as usize; @@ -209,7 +217,11 @@ impl HuffmanTable { // Build a lookup table for faster decoding. let mut lut = [(0u8, 0u8); 1 << LUT_BITS]; - for (i, &size) in huffsize.iter().enumerate().filter(|&(_, &size)| size <= LUT_BITS) { + for (i, &size) in huffsize + .iter() + .enumerate() + .filter(|&(_, &size)| size <= LUT_BITS) + { let bits_remaining = LUT_BITS - size; let start = (huffcode[i] << bits_remaining) as usize; @@ -231,6 +243,7 @@ impl HuffmanTable { let magnitude_category = value & 0x0f; if magnitude_category > 0 && size + magnitude_category <= LUT_BITS { + #[rustfmt::skip] let unextended_ac_value = (((i << size) & ((1 << LUT_BITS) - 1)) >> (LUT_BITS - magnitude_category)) as u16; let ac_value = extend(unextended_ac_value, magnitude_category); @@ -239,7 +252,7 @@ impl HuffmanTable { } Some(table) - }, + } }; Ok(HuffmanTable { @@ -255,12 +268,13 @@ impl HuffmanTable { // Section C.2 fn derive_huffman_codes(bits: &[u8; 16]) -> Result<(Vec, Vec)> { // Figure C.1 - let huffsize = bits.iter() - .enumerate() - .fold(Vec::new(), |mut acc, (i, &value)| { - acc.extend(iter::repeat((i + 1) as u8).take(value as usize)); - acc - }); + let huffsize = bits + .iter() + .enumerate() + .fold(Vec::new(), |mut acc, (i, &value)| { + acc.extend(iter::repeat((i + 1) as u8).take(value as usize)); + acc + }); // Figure C.2 let mut huffcode = vec![0u16; huffsize.len()]; @@ -292,55 +306,99 @@ fn derive_huffman_codes(bits: &[u8; 16]) -> Result<(Vec, Vec)> { // MJPEG frames and decode them with a regular JPEG decoder, but you have to prepend the DHT // segment to them, or else the decoder won't have any idea how to decompress the data. // The exact table necessary is given in the OpenDML spec."" -pub fn fill_default_mjpeg_tables(scan: &ScanInfo, - dc_huffman_tables: &mut[Option], - ac_huffman_tables: &mut[Option]) { +pub fn fill_default_mjpeg_tables( + scan: &ScanInfo, + dc_huffman_tables: &mut [Option], + ac_huffman_tables: &mut [Option], +) { // Section K.3.3 if dc_huffman_tables[0].is_none() && scan.dc_table_indices.iter().any(|&i| i == 0) { // Table K.3 - dc_huffman_tables[0] = Some(HuffmanTable::new( - &[0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], - &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], HuffmanTableClass::DC).unwrap()); + dc_huffman_tables[0] = Some( + HuffmanTable::new( + &[ + 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + ], + HuffmanTableClass::DC, + ) + .unwrap(), + ); } if dc_huffman_tables[1].is_none() && scan.dc_table_indices.iter().any(|&i| i == 1) { // Table K.4 - dc_huffman_tables[1] = Some(HuffmanTable::new( - &[0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], - &[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B], HuffmanTableClass::DC).unwrap()); + dc_huffman_tables[1] = Some( + HuffmanTable::new( + &[ + 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + ], + HuffmanTableClass::DC, + ) + .unwrap(), + ); } if ac_huffman_tables[0].is_none() && scan.ac_table_indices.iter().any(|&i| i == 0) { // Table K.5 - ac_huffman_tables[0] = Some(HuffmanTable::new( - &[0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7D], - &[0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, - 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, - 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, - 0x29, 0x2A, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, - 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, - 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, - 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, - 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, - 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, 0xE2, - 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, - 0xF9, 0xFA - ], HuffmanTableClass::AC).unwrap()); + ac_huffman_tables[0] = Some( + HuffmanTable::new( + &[ + 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04, 0x04, 0x00, + 0x00, 0x01, 0x7D, + ], + &[ + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, + 0x51, 0x61, 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xA1, 0x08, 0x23, 0x42, + 0xB1, 0xC1, 0x15, 0x52, 0xD1, 0xF0, 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0A, + 0x16, 0x17, 0x18, 0x19, 0x1A, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x34, 0x35, + 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, + 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x83, 0x84, + 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, + 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, + 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xE1, + 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF1, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, + ], + HuffmanTableClass::AC, + ) + .unwrap(), + ); } if ac_huffman_tables[1].is_none() && scan.ac_table_indices.iter().any(|&i| i == 1) { // Table K.6 - ac_huffman_tables[1] = Some(HuffmanTable::new( - &[0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77], - &[0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, - 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, - 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, - 0x27, 0x28, 0x29, 0x2A, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, - 0x49, 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, - 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, - 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, - 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, - 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, - 0xF9, 0xFA - ], HuffmanTableClass::AC).unwrap()); + ac_huffman_tables[1] = Some( + HuffmanTable::new( + &[ + 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04, 0x00, + 0x01, 0x02, 0x77, + ], + &[ + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, + 0x07, 0x61, 0x71, 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xA1, 0xB1, + 0xC1, 0x09, 0x23, 0x33, 0x52, 0xF0, 0x15, 0x62, 0x72, 0xD1, 0x0A, 0x16, 0x24, + 0x34, 0xE1, 0x25, 0xF1, 0x17, 0x18, 0x19, 0x1A, 0x26, 0x27, 0x28, 0x29, 0x2A, + 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4A, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x63, 0x64, 0x65, 0x66, + 0x67, 0x68, 0x69, 0x6A, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x82, + 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9A, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, + 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xC2, 0xC3, 0xC4, 0xC5, + 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, + 0xDA, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xF2, 0xF3, 0xF4, + 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, + ], + HuffmanTableClass::AC, + ) + .unwrap(), + ); } } diff --git a/src/idct.rs b/src/idct.rs index 99f10ffa..47504e2c 100644 --- a/src/idct.rs +++ b/src/idct.rs @@ -560,6 +560,7 @@ fn dequantize_and_idct_block_1x1( ) { debug_assert_eq!(coefficients.len(), 64); + #[rustfmt::skip] let s0 = (Wrapping(coefficients[0] as i32 * quantization_table[0] as i32) + Wrapping(128 * 8)) / Wrapping(8); output[0] = stbi_clamp(s0); } @@ -581,26 +582,26 @@ fn stbi_fsh(x: Wrapping) -> Wrapping { fn test_dequantize_and_idct_block_8x8() { #[rustfmt::skip] let coefficients: [i16; 8 * 8] = [ - -14, -39, 58, -2, 3, 3, 0, 1, - 11, 27, 4, -3, 3, 0, 1, 0, - -6, -13, -9, -1, -2, -1, 0, 0, - -4, 0, -1, -2, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, 0, 0, - -3, -2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0 + -14, -39, 58, -2, 3, 3, 0, 1, + 11, 27, 4, -3, 3, 0, 1, 0, + -6, -13, -9, -1, -2, -1, 0, 0, + -4, 0, -1, -2, 0, 0, 0, 0, + 3, 0, 0, 0, 0, 0, 0, 0, + -3, -2, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, ]; #[rustfmt::skip] let quantization_table: [u16; 8 * 8] = [ - 8, 6, 5, 8, 12, 20, 26, 31, - 6, 6, 7, 10, 13, 29, 30, 28, - 7, 7, 8, 12, 20, 29, 35, 28, - 7, 9, 11, 15, 26, 44, 40, 31, - 9, 11, 19, 28, 34, 55, 52, 39, + 8, 6, 5, 8, 12, 20, 26, 31, + 6, 6, 7, 10, 13, 29, 30, 28, + 7, 7, 8, 12, 20, 29, 35, 28, + 7, 9, 11, 15, 26, 44, 40, 31, + 9, 11, 19, 28, 34, 55, 52, 39, 12, 18, 28, 32, 41, 52, 57, 46, 25, 32, 39, 44, 52, 61, 60, 51, - 36, 46, 48, 49, 56, 50, 52, 50 + 36, 46, 48, 49, 56, 50, 52, 50, ]; let output_linestride: usize = 8; let mut output = [0u8; 8 * 8]; @@ -612,14 +613,14 @@ fn test_dequantize_and_idct_block_8x8() { ); #[rustfmt::skip] let expected_output = [ - 118, 92, 110, 83, 77, 93, 144, 198, - 172, 116, 114, 87, 78, 93, 146, 191, - 194, 107, 91, 76, 71, 93, 160, 198, - 196, 100, 80, 74, 67, 92, 174, 209, - 182, 104, 88, 81, 68, 89, 178, 206, - 105, 64, 59, 59, 63, 94, 183, 201, - 35, 27, 28, 37, 72, 121, 203, 204, - 37, 45, 41, 47, 98, 154, 223, 208 + 118, 92, 110, 83, 77, 93, 144, 198, + 172, 116, 114, 87, 78, 93, 146, 191, + 194, 107, 91, 76, 71, 93, 160, 198, + 196, 100, 80, 74, 67, 92, 174, 209, + 182, 104, 88, 81, 68, 89, 178, 206, + 105, 64, 59, 59, 63, 94, 183, 201, + 35, 27, 28, 37, 72, 121, 203, 204, + 37, 45, 41, 47, 98, 154, 223, 208, ]; for i in 0..64 { assert!((output[i] as i16 - expected_output[i] as i16).abs() <= 1); @@ -644,14 +645,14 @@ fn test_dequantize_and_idct_block_8x8_saturated() { dequantize_and_idct_block_8x8(&[i16::MAX; 8 * 8], &[u16::MAX; 8 * 8], 8, &mut output); #[rustfmt::skip] let expected = [ - 0, 0, 0, 255, 255, 0, 0, 255, - 0, 0, 215, 0, 0, 255, 255, 0, - 255, 255, 255, 255, 255, 0, 0, 255, - 0, 0, 255, 0, 255, 0, 255, 255, - 0, 0, 255, 255, 0, 255, 0, 0, - 255, 255, 0, 255, 255, 255, 170, 0, - 0, 255, 0, 0, 0, 0, 0, 255, - 255, 255, 0, 255, 0, 255, 0, 0 + 0, 0, 0, 255, 255, 0, 0, 255, + 0, 0, 215, 0, 0, 255, 255, 0, + 255, 255, 255, 255, 255, 0, 0, 255, + 0, 0, 255, 0, 255, 0, 255, 255, + 0, 0, 255, 255, 0, 255, 0, 0, + 255, 255, 0, 255, 255, 255, 170, 0, + 0, 255, 0, 0, 0, 0, 0, 255, + 255, 255, 0, 255, 0, 255, 0, 0, ]; assert_eq!(&output[..], &expected[..]); } diff --git a/src/marker.rs b/src/marker.rs index 2fe74be2..99bc873c 100644 --- a/src/marker.rs +++ b/src/marker.rs @@ -58,7 +58,7 @@ pub enum Marker { impl Marker { pub fn has_length(self) -> bool { use self::Marker::*; - ! matches!(self, RST(..) | SOI | EOI | TEM) + !matches!(self, RST(..) | SOI | EOI | TEM) } pub fn from_u8(n: u8) -> Option { @@ -66,7 +66,7 @@ impl Marker { match n { 0x00 => None, // Byte stuffing 0x01 => Some(TEM), - 0x02 ..= 0xBF => Some(RES), + 0x02..=0xBF => Some(RES), 0xC0 => Some(SOF(0)), 0xC1 => Some(SOF(1)), 0xC2 => Some(SOF(2)), diff --git a/src/parser.rs b/src/parser.rs index bf13aba0..4760611c 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,13 +1,13 @@ -use alloc::borrow::ToOwned; -use alloc::{format, vec}; -use alloc::vec::Vec; -use core::ops::{self, Range}; -use std::io::{self, Read}; -use crate::{read_u16_from_be, read_u8}; use crate::error::{Error, Result, UnsupportedFeature}; use crate::huffman::{HuffmanTable, HuffmanTableClass}; use crate::marker::Marker; use crate::marker::Marker::*; +use crate::{read_u16_from_be, read_u8}; +use alloc::borrow::ToOwned; +use alloc::vec::Vec; +use alloc::{format, vec}; +use core::ops::{self, Range}; +use std::io::{self, Read}; #[derive(Clone, Copy, Debug, PartialEq)] pub struct Dimensions { @@ -45,7 +45,6 @@ pub enum Predictor { RaRb, // (Ra + Rb)/2 } - #[derive(Clone)] pub struct FrameInfo { pub is_baseline: bool, @@ -124,7 +123,7 @@ impl FrameInfo { self.output_size = Dimensions { width: (self.image_size.width as f32 * idct_size as f32 / 8.0).ceil() as u16, - height: (self.image_size.height as f32 * idct_size as f32 / 8.0).ceil() as u16 + height: (self.image_size.height as f32 * idct_size as f32 / 8.0).ceil() as u16, }; Ok(()) @@ -138,7 +137,10 @@ fn read_length(reader: &mut R, marker: Marker) -> Result { let length = usize::from(read_u16_from_be(reader)?); if length < 2 { - return Err(Error::Format(format!("encountered {:?} with invalid length {}", marker, length))); + return Err(Error::Format(format!( + "encountered {:?} with invalid length {}", + marker, length + ))); } Ok(length - 2) @@ -165,36 +167,42 @@ pub fn parse_sof(reader: &mut R, marker: Marker) -> Result { let is_baseline = marker == SOF(0); let is_differential = match marker { - SOF(0 ..= 3) | SOF(9 ..= 11) => false, - SOF(5 ..= 7) | SOF(13 ..= 15) => true, + SOF(0..=3) | SOF(9..=11) => false, + SOF(5..=7) | SOF(13..=15) => true, _ => panic!(), }; + let coding_process = match marker { SOF(0) | SOF(1) | SOF(5) | SOF(9) | SOF(13) => CodingProcess::DctSequential, - SOF(2) | SOF(6) | SOF(10) | SOF(14) => CodingProcess::DctProgressive, - SOF(3) | SOF(7) | SOF(11) | SOF(15) => CodingProcess::Lossless, + SOF(2) | SOF(6) | SOF(10) | SOF(14) => CodingProcess::DctProgressive, + SOF(3) | SOF(7) | SOF(11) | SOF(15) => CodingProcess::Lossless, _ => panic!(), }; let entropy_coding = match marker { - SOF(0 ..= 3) | SOF(5 ..= 7) => EntropyCoding::Huffman, - SOF(9 ..= 11) | SOF(13 ..= 15) => EntropyCoding::Arithmetic, + SOF(0..=3) | SOF(5..=7) => EntropyCoding::Huffman, + SOF(9..=11) | SOF(13..=15) => EntropyCoding::Arithmetic, _ => panic!(), }; let precision = read_u8(reader)?; match precision { - 8 => {}, + 8 => {} 12 => { if is_baseline { - return Err(Error::Format("12 bit sample precision is not allowed in baseline".to_owned())); + return Err(Error::Format( + "12 bit sample precision is not allowed in baseline".to_owned(), + )); } - }, + } _ => { if coding_process != CodingProcess::Lossless || precision > 16 { - return Err(Error::Format(format!("invalid precision {} in frame header", precision))) + return Err(Error::Format(format!( + "invalid precision {} in frame header", + precision, + ))); } - }, + } } let height = read_u16_from_be(reader)?; @@ -214,10 +222,14 @@ pub fn parse_sof(reader: &mut R, marker: Marker) -> Result { let component_count = read_u8(reader)?; if component_count == 0 { - return Err(Error::Format("zero component count in frame header".to_owned())); + return Err(Error::Format( + "zero component count in frame header".to_owned(), + )); } if coding_process == CodingProcess::DctProgressive && component_count > 4 { - return Err(Error::Format("progressive frame with more than 4 components".to_owned())); + return Err(Error::Format( + "progressive frame with more than 4 components".to_owned(), + )); } if length != 6 + 3 * component_count as usize { @@ -226,12 +238,15 @@ pub fn parse_sof(reader: &mut R, marker: Marker) -> Result { let mut components: Vec = Vec::with_capacity(component_count as usize); - for _ in 0 .. component_count { + for _ in 0..component_count { let identifier = read_u8(reader)?; // Each component's identifier must be unique. if components.iter().any(|c| c.identifier == identifier) { - return Err(Error::Format(format!("duplicate frame component identifier {}", identifier))); + return Err(Error::Format(format!( + "duplicate frame component identifier {}", + identifier, + ))); } let byte = read_u8(reader)?; @@ -239,16 +254,27 @@ pub fn parse_sof(reader: &mut R, marker: Marker) -> Result { let vertical_sampling_factor = byte & 0x0f; if horizontal_sampling_factor == 0 || horizontal_sampling_factor > 4 { - return Err(Error::Format(format!("invalid horizontal sampling factor {}", horizontal_sampling_factor))); + return Err(Error::Format(format!( + "invalid horizontal sampling factor {}", + horizontal_sampling_factor + ))); } if vertical_sampling_factor == 0 || vertical_sampling_factor > 4 { - return Err(Error::Format(format!("invalid vertical sampling factor {}", vertical_sampling_factor))); + return Err(Error::Format(format!( + "invalid vertical sampling factor {}", + vertical_sampling_factor + ))); } let quantization_table_index = read_u8(reader)?; - if quantization_table_index > 3 || (coding_process == CodingProcess::Lossless && quantization_table_index != 0) { - return Err(Error::Format(format!("invalid quantization table index {}", quantization_table_index))); + if quantization_table_index > 3 + || (coding_process == CodingProcess::Lossless && quantization_table_index != 0) + { + return Err(Error::Format(format!( + "invalid quantization table index {}", + quantization_table_index, + ))); } components.push(Component { @@ -257,8 +283,14 @@ pub fn parse_sof(reader: &mut R, marker: Marker) -> Result { vertical_sampling_factor, quantization_table_index: quantization_table_index as usize, dct_scale: 8, - size: Dimensions {width: 0, height: 0}, - block_size: Dimensions {width: 0, height: 0}, + size: Dimensions { + width: 0, + height: 0, + }, + block_size: Dimensions { + width: 0, + height: 0, + }, }); } @@ -288,8 +320,16 @@ fn ceil_div(x: u32, y: u32) -> Result { } fn update_component_sizes(size: Dimensions, components: &mut [Component]) -> Result { - let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap() as u32; - let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap() as u32; + let h_max = components + .iter() + .map(|c| c.horizontal_sampling_factor) + .max() + .unwrap() as u32; + let v_max = components + .iter() + .map(|c| c.vertical_sampling_factor) + .max() + .unwrap() as u32; let mcu_size = Dimensions { width: ceil_div(size.width as u32, h_max * 8)?, @@ -297,8 +337,18 @@ fn update_component_sizes(size: Dimensions, components: &mut [Component]) -> Res }; for component in components { - component.size.width = ceil_div(size.width as u32 * component.horizontal_sampling_factor as u32 * component.dct_scale as u32, h_max * 8)?; - component.size.height = ceil_div(size.height as u32 * component.vertical_sampling_factor as u32 * component.dct_scale as u32, v_max * 8)?; + component.size.width = ceil_div( + size.width as u32 + * component.horizontal_sampling_factor as u32 + * component.dct_scale as u32, + h_max * 8, + )?; + component.size.height = ceil_div( + size.height as u32 + * component.vertical_sampling_factor as u32 + * component.dct_scale as u32, + v_max * 8, + )?; component.block_size.width = mcu_size.width * component.horizontal_sampling_factor as u16; component.block_size.height = mcu_size.height * component.vertical_sampling_factor as u16; @@ -315,15 +365,44 @@ fn test_update_component_sizes() { vertical_sampling_factor: 2, quantization_table_index: 0, dct_scale: 8, - size: Dimensions { width: 0, height: 0 }, - block_size: Dimensions { width: 0, height: 0 }, + size: Dimensions { + width: 0, + height: 0, + }, + block_size: Dimensions { + width: 0, + height: 0, + }, }]; let mcu = update_component_sizes( - Dimensions { width: 800, height: 280 }, - &mut components).unwrap(); - assert_eq!(mcu, Dimensions { width: 50, height: 18 }); - assert_eq!(components[0].block_size, Dimensions { width: 100, height: 36 }); - assert_eq!(components[0].size, Dimensions { width: 800, height: 280 }); + Dimensions { + width: 800, + height: 280, + }, + &mut components, + ) + .unwrap(); + assert_eq!( + mcu, + Dimensions { + width: 50, + height: 18, + } + ); + assert_eq!( + components[0].block_size, + Dimensions { + width: 100, + height: 36, + } + ); + assert_eq!( + components[0].size, + Dimensions { + width: 800, + height: 280, + } + ); } // Section B.2.3 @@ -336,7 +415,10 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result let component_count = read_u8(reader)?; if component_count == 0 || component_count > 4 { - return Err(Error::Format(format!("invalid component count {} in scan header", component_count))); + return Err(Error::Format(format!( + "invalid component count {} in scan header", + component_count + ))); } if length != 4 + 2 * component_count as usize { @@ -347,7 +429,7 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result let mut dc_table_indices = Vec::with_capacity(component_count as usize); let mut ac_table_indices = Vec::with_capacity(component_count as usize); - for _ in 0 .. component_count { + for _ in 0..component_count { let identifier = read_u8(reader)?; let component_index = match frame.components.iter().position(|c| c.identifier == identifier) { @@ -357,12 +439,17 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result // Each of the scan's components must be unique. if component_indices.contains(&component_index) { - return Err(Error::Format(format!("duplicate scan component identifier {}", identifier))); + return Err(Error::Format(format!( + "duplicate scan component identifier {}", + identifier, + ))); } // "... the ordering in the scan header shall follow the ordering in the frame header." if component_index < *component_indices.iter().max().unwrap_or(&0) { - return Err(Error::Format("the scan component order does not follow the order in the frame header".to_owned())); + return Err(Error::Format( + "the scan component order does not follow the order in the frame header".to_owned(), + )); } let byte = read_u8(reader)?; @@ -370,10 +457,16 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result let ac_table_index = byte & 0x0f; if dc_table_index > 3 || (frame.is_baseline && dc_table_index > 1) { - return Err(Error::Format(format!("invalid dc table index {}", dc_table_index))); + return Err(Error::Format(format!( + "invalid dc table index {}", + dc_table_index, + ))); } if ac_table_index > 3 || (frame.is_baseline && ac_table_index > 1) { - return Err(Error::Format(format!("invalid ac table index {}", ac_table_index))); + return Err(Error::Format(format!( + "invalid ac table index {}", + ac_table_index, + ))); } component_indices.push(component_index); @@ -381,12 +474,18 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result ac_table_indices.push(ac_table_index as usize); } - let blocks_per_mcu = component_indices.iter().map(|&i| { - frame.components[i].horizontal_sampling_factor as u32 * frame.components[i].vertical_sampling_factor as u32 - }).fold(0, ops::Add::add); + let blocks_per_mcu = component_indices + .iter() + .map(|&i| { + frame.components[i].horizontal_sampling_factor as u32 + * frame.components[i].vertical_sampling_factor as u32 + }) + .fold(0, ops::Add::add); if component_count > 1 && blocks_per_mcu > 10 { - return Err(Error::Format("scan with more than one component and more than 10 blocks per MCU".to_owned())); + return Err(Error::Format( + "scan with more than one component and more than 10 blocks per MCU".to_owned(), + )); } // Also utilized as 'Predictor' in lossless coding, as MEAN in JPEG-LS etc. @@ -405,31 +504,49 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result if frame.coding_process == CodingProcess::DctProgressive { predictor_selection = Predictor::NoPrediction; - if spectral_selection_end > 63 || spectral_selection_start > spectral_selection_end || - (spectral_selection_start == 0 && spectral_selection_end != 0) { - return Err(Error::Format(format!("invalid spectral selection parameters: ss={}, se={}", spectral_selection_start, spectral_selection_end))); + if spectral_selection_end > 63 + || spectral_selection_start > spectral_selection_end + || (spectral_selection_start == 0 && spectral_selection_end != 0) + { + return Err(Error::Format(format!( + "invalid spectral selection parameters: ss={}, se={}", + spectral_selection_start, spectral_selection_end, + ))); } if spectral_selection_start != 0 && component_count != 1 { - return Err(Error::Format("spectral selection scan with AC coefficients can't have more than one component".to_owned())); + return Err(Error::Format( + "spectral selection scan with AC coefficients can't have more than one component" + .to_owned(), + )); } if successive_approximation_high > 13 || successive_approximation_low > 13 { - return Err(Error::Format(format!("invalid successive approximation parameters: ah={}, al={}", successive_approximation_high, successive_approximation_low))); + return Err(Error::Format(format!( + "invalid successive approximation parameters: ah={}, al={}", + successive_approximation_high, successive_approximation_low, + ))); } // Section G.1.1.1.2 // "Each scan which follows the first scan for a given band progressively improves // the precision of the coefficients by one bit, until full precision is reached." - if successive_approximation_high != 0 && successive_approximation_high != successive_approximation_low + 1 { - return Err(Error::Format("successive approximation scan with more than one bit of improvement".to_owned())); - } - } - else if frame.coding_process == CodingProcess::Lossless { + if successive_approximation_high != 0 + && successive_approximation_high != successive_approximation_low + 1 + { + return Err(Error::Format( + "successive approximation scan with more than one bit of improvement".to_owned(), + )); + } + } else if frame.coding_process == CodingProcess::Lossless { if spectral_selection_end != 0 { - return Err(Error::Format("spectral selection end shall be zero in lossless scan".to_owned())); + return Err(Error::Format( + "spectral selection end shall be zero in lossless scan".to_owned(), + )); } if successive_approximation_high != 0 { - return Err(Error::Format("successive approximation high shall be zero in lossless scan".to_owned())); + return Err(Error::Format( + "successive approximation high shall be zero in lossless scan".to_owned(), + )); } predictor_selection = match spectral_selection_start { 0 => Predictor::NoPrediction, @@ -441,20 +558,26 @@ pub fn parse_sos(reader: &mut R, frame: &FrameInfo) -> Result 6 => Predictor::RaRbRc3, 7 => Predictor::RaRb, _ => { - return Err(Error::Format(format!("invalid predictor selection value: {}", spectral_selection_start))); - }, + return Err(Error::Format(format!( + "invalid predictor selection value: {}", + spectral_selection_start, + ))); + } }; - } - else { + } else { predictor_selection = Predictor::NoPrediction; if spectral_selection_end == 0 { spectral_selection_end = 63; } if spectral_selection_start != 0 || spectral_selection_end != 63 { - return Err(Error::Format("spectral selection is not allowed in non-progressive scan".to_owned())); + return Err(Error::Format( + "spectral selection is not allowed in non-progressive scan".to_owned(), + )); } if successive_approximation_high != 0 || successive_approximation_low != 0 { - return Err(Error::Format("successive approximation is not allowed in non-progressive scan".to_owned())); + return Err(Error::Format( + "successive approximation is not allowed in non-progressive scan".to_owned(), + )); } } @@ -493,10 +616,16 @@ pub fn parse_dqt(reader: &mut R) -> Result<[Option<[u16; 64]>; 4]> { // libjpeg allows this behavior though, and there are images in the wild using it. So to // match libjpeg's behavior we are deviating from the JPEG spec here. if precision > 1 { - return Err(Error::Format(format!("invalid precision {} in DQT", precision))); + return Err(Error::Format(format!( + "invalid precision {} in DQT", + precision, + ))); } if index > 3 { - return Err(Error::Format(format!("invalid destination identifier {} in DQT", index))); + return Err(Error::Format(format!( + "invalid destination identifier {} in DQT", + index, + ))); } if length < 65 + 64 * precision { return Err(Error::Format("invalid length in DQT".to_owned())); @@ -513,7 +642,9 @@ pub fn parse_dqt(reader: &mut R) -> Result<[Option<[u16; 64]>; 4]> { } if table.iter().any(|&val| val == 0) { - return Err(Error::Format("quantization table contains element with a zero value".to_owned())); + return Err(Error::Format( + "quantization table contains element with a zero value".to_owned(), + )); } tables[index] = Some(table); @@ -525,7 +656,10 @@ pub fn parse_dqt(reader: &mut R) -> Result<[Option<[u16; 64]>; 4]> { // Section B.2.4.2 #[allow(clippy::type_complexity)] -pub fn parse_dht(reader: &mut R, is_baseline: Option) -> Result<(Vec>, Vec>)> { +pub fn parse_dht( + reader: &mut R, + is_baseline: Option, +) -> Result<(Vec>, Vec>)> { let mut length = read_length(reader, DHT)?; let mut dc_tables = vec![None, None, None, None]; let mut ac_tables = vec![None, None, None, None]; @@ -540,24 +674,34 @@ pub fn parse_dht(reader: &mut R, is_baseline: Option) -> Result<( return Err(Error::Format(format!("invalid class {} in DHT", class))); } if is_baseline == Some(true) && index > 1 { - return Err(Error::Format("a maximum of two huffman tables per class are allowed in baseline".to_owned())); + return Err(Error::Format( + "a maximum of two huffman tables per class are allowed in baseline".to_owned(), + )); } if index > 3 { - return Err(Error::Format(format!("invalid destination identifier {} in DHT", index))); + return Err(Error::Format(format!( + "invalid destination identifier {} in DHT", + index, + ))); } let mut counts = [0u8; 16]; reader.read_exact(&mut counts)?; - let size = counts.iter().map(|&val| val as usize).fold(0, ops::Add::add); + let size = counts + .iter() + .map(|&val| val as usize) + .fold(0, ops::Add::add); if size == 0 { - return Err(Error::Format("encountered table with zero length in DHT".to_owned())); - } - else if size > 256 { - return Err(Error::Format("encountered table with excessive length in DHT".to_owned())); - } - else if size > length - 17 { + return Err(Error::Format( + "encountered table with zero length in DHT".to_owned(), + )); + } else if size > 256 { + return Err(Error::Format( + "encountered table with excessive length in DHT".to_owned(), + )); + } else if size > length - 17 { return Err(Error::Format("invalid length in DHT".to_owned())); } @@ -565,8 +709,12 @@ pub fn parse_dht(reader: &mut R, is_baseline: Option) -> Result<( reader.read_exact(&mut values)?; match class { - 0 => dc_tables[index] = Some(HuffmanTable::new(&counts, &values, HuffmanTableClass::DC)?), - 1 => ac_tables[index] = Some(HuffmanTable::new(&counts, &values, HuffmanTableClass::AC)?), + 0 => { + dc_tables[index] = Some(HuffmanTable::new(&counts, &values, HuffmanTableClass::DC)?) + } + 1 => { + ac_tables[index] = Some(HuffmanTable::new(&counts, &values, HuffmanTableClass::AC)?) + } _ => unreachable!(), } @@ -667,19 +815,23 @@ pub fn parse_app(reader: &mut R, marker: Marker) -> Result AdobeColorTransform::Unknown, 1 => AdobeColorTransform::YCbCr, 2 => AdobeColorTransform::YCCK, - _ => return Err(Error::Format("invalid color transform in adobe app segment".to_owned())), + _ => { + return Err(Error::Format( + "invalid color transform in adobe app segment".to_owned(), + )) + } }; result = Some(AppData::Adobe(color_transform)); } } - }, - _ => {}, + } + _ => {} } skip_bytes(reader, length - bytes_read)?; diff --git a/src/upsampler.rs b/src/upsampler.rs index 10640fe2..dedf7526 100644 --- a/src/upsampler.rs +++ b/src/upsampler.rs @@ -1,12 +1,12 @@ +use crate::error::{Error, Result, UnsupportedFeature}; +use crate::parser::Component; use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; -use crate::error::{Error, Result, UnsupportedFeature}; -use crate::parser::Component; pub struct Upsampler { components: Vec, - line_buffer_size: usize + line_buffer_size: usize, } struct UpsamplerComponent { @@ -17,17 +17,33 @@ struct UpsamplerComponent { } impl Upsampler { - pub fn new(components: &[Component], output_width: u16, output_height: u16) -> Result { - let h_max = components.iter().map(|c| c.horizontal_sampling_factor).max().unwrap(); - let v_max = components.iter().map(|c| c.vertical_sampling_factor).max().unwrap(); + pub fn new( + components: &[Component], + output_width: u16, + output_height: u16, + ) -> Result { + let h_max = components + .iter() + .map(|c| c.horizontal_sampling_factor) + .max() + .unwrap(); + let v_max = components + .iter() + .map(|c| c.vertical_sampling_factor) + .max() + .unwrap(); let mut upsampler_components = Vec::with_capacity(components.len()); for component in components { - let upsampler = choose_upsampler((component.horizontal_sampling_factor, - component.vertical_sampling_factor), - (h_max, v_max), - output_width, - output_height)?; + let upsampler = choose_upsampler( + ( + component.horizontal_sampling_factor, + component.vertical_sampling_factor, + ), + (h_max, v_max), + output_width, + output_height, + )?; upsampler_components.push(UpsamplerComponent { upsampler, width: component.size.width as usize, @@ -36,28 +52,38 @@ impl Upsampler { }); } - let buffer_size = components.iter().map(|c| c.size.width).max().unwrap() as usize * h_max as usize; + let buffer_size = + components.iter().map(|c| c.size.width).max().unwrap() as usize * h_max as usize; Ok(Upsampler { components: upsampler_components, - line_buffer_size: buffer_size + line_buffer_size: buffer_size, }) } - pub fn upsample_and_interleave_row(&self, component_data: &[Vec], row: usize, output_width: usize, output: &mut [u8], color_convert: fn(&[Vec], &mut [u8])) { + pub fn upsample_and_interleave_row( + &self, + component_data: &[Vec], + row: usize, + output_width: usize, + output: &mut [u8], + color_convert: fn(&[Vec], &mut [u8]), + ) { let component_count = component_data.len(); let mut line_buffers = vec![vec![0u8; self.line_buffer_size]; component_count]; debug_assert_eq!(component_count, self.components.len()); for (i, component) in self.components.iter().enumerate() { - component.upsampler.upsample_row(&component_data[i], - component.width, - component.height, - component.row_stride, - row, - output_width, - &mut line_buffers[i]); + component.upsampler.upsample_row( + &component_data[i], + component.width, + component.height, + component.row_stride, + row, + output_width, + &mut line_buffers[i], + ); } color_convert(&line_buffers, output); } @@ -70,13 +96,15 @@ struct UpsamplerH2V2; struct UpsamplerGeneric { horizontal_scaling_factor: u8, - vertical_scaling_factor: u8 + vertical_scaling_factor: u8, } -fn choose_upsampler(sampling_factors: (u8, u8), - max_sampling_factors: (u8, u8), - output_width: u16, - output_height: u16) -> Result> { +fn choose_upsampler( + sampling_factors: (u8, u8), + max_sampling_factors: (u8, u8), + output_width: u16, + output_height: u16, +) -> Result> { let h1 = sampling_factors.0 == max_sampling_factors.0 || output_width == 1; let v1 = sampling_factors.1 == max_sampling_factors.1 || output_height == 1; let h2 = sampling_factors.0 * 2 == max_sampling_factors.0; @@ -106,41 +134,47 @@ fn choose_upsampler(sampling_factors: (u8, u8), #[allow(clippy::too_many_arguments)] trait Upsample { - fn upsample_row(&self, - input: &[u8], - input_width: usize, - input_height: usize, - row_stride: usize, - row: usize, - output_width: usize, - output: &mut [u8]); + fn upsample_row( + &self, + input: &[u8], + input_width: usize, + input_height: usize, + row_stride: usize, + row: usize, + output_width: usize, + output: &mut [u8], + ); } impl Upsample for UpsamplerH1V1 { - fn upsample_row(&self, - input: &[u8], - _input_width: usize, - _input_height: usize, - row_stride: usize, - row: usize, - output_width: usize, - output: &mut [u8]) { - let input = &input[row * row_stride ..]; + fn upsample_row( + &self, + input: &[u8], + _input_width: usize, + _input_height: usize, + row_stride: usize, + row: usize, + output_width: usize, + output: &mut [u8], + ) { + let input = &input[row * row_stride..]; output[..output_width].copy_from_slice(&input[..output_width]); } } impl Upsample for UpsamplerH2V1 { - fn upsample_row(&self, - input: &[u8], - input_width: usize, - _input_height: usize, - row_stride: usize, - row: usize, - _output_width: usize, - output: &mut [u8]) { - let input = &input[row * row_stride ..]; + fn upsample_row( + &self, + input: &[u8], + input_width: usize, + _input_height: usize, + row_stride: usize, + row: usize, + _output_width: usize, + output: &mut [u8], + ) { + let input = &input[row * row_stride..]; if input_width == 1 { output[0] = input[0]; @@ -151,33 +185,36 @@ impl Upsample for UpsamplerH2V1 { output[0] = input[0]; output[1] = ((input[0] as u32 * 3 + input[1] as u32 + 2) >> 2) as u8; - for i in 1 .. input_width - 1 { + for i in 1..input_width - 1 { let sample = 3 * input[i] as u32 + 2; - output[i * 2] = ((sample + input[i - 1] as u32) >> 2) as u8; + output[i * 2] = ((sample + input[i - 1] as u32) >> 2) as u8; output[i * 2 + 1] = ((sample + input[i + 1] as u32) >> 2) as u8; } - output[(input_width - 1) * 2] = ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8; + output[(input_width - 1) * 2] = + ((input[input_width - 1] as u32 * 3 + input[input_width - 2] as u32 + 2) >> 2) as u8; output[(input_width - 1) * 2 + 1] = input[input_width - 1]; } } impl Upsample for UpsamplerH1V2 { - fn upsample_row(&self, - input: &[u8], - _input_width: usize, - input_height: usize, - row_stride: usize, - row: usize, - output_width: usize, - output: &mut [u8]) { + fn upsample_row( + &self, + input: &[u8], + _input_width: usize, + input_height: usize, + row_stride: usize, + row: usize, + output_width: usize, + output: &mut [u8], + ) { let row_near = row as f32 / 2.0; // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we // want it to be the next row. let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32); - let input_near = &input[row_near as usize * row_stride ..]; - let input_far = &input[row_far as usize * row_stride ..]; + let input_near = &input[row_near as usize * row_stride..]; + let input_far = &input[row_far as usize * row_stride..]; let output = &mut output[..output_width]; let input_near = &input_near[..output_width]; @@ -189,21 +226,23 @@ impl Upsample for UpsamplerH1V2 { } impl Upsample for UpsamplerH2V2 { - fn upsample_row(&self, - input: &[u8], - input_width: usize, - input_height: usize, - row_stride: usize, - row: usize, - _output_width: usize, - output: &mut [u8]) { + fn upsample_row( + &self, + input: &[u8], + input_width: usize, + input_height: usize, + row_stride: usize, + row: usize, + _output_width: usize, + output: &mut [u8], + ) { let row_near = row as f32 / 2.0; // If row_near's fractional is 0.0 we want row_far to be the previous row and if it's 0.5 we // want it to be the next row. let row_far = (row_near + row_near.fract() * 3.0 - 0.25).min((input_height - 1) as f32); - let input_near = &input[row_near as usize * row_stride ..]; - let input_far = &input[row_far as usize * row_stride ..]; + let input_near = &input[row_near as usize * row_stride..]; + let input_far = &input[row_far as usize * row_stride..]; if input_width == 1 { let value = ((3 * input_near[0] as u32 + input_far[0] as u32 + 2) >> 2) as u8; @@ -215,12 +254,12 @@ impl Upsample for UpsamplerH2V2 { let mut t1 = 3 * input_near[0] as u32 + input_far[0] as u32; output[0] = ((t1 + 2) >> 2) as u8; - for i in 1 .. input_width { + for i in 1..input_width { let t0 = t1; t1 = 3 * input_near[i] as u32 + input_far[i] as u32; output[i * 2 - 1] = ((3 * t0 + t1 + 8) >> 4) as u8; - output[i * 2] = ((3 * t1 + t0 + 8) >> 4) as u8; + output[i * 2] = ((3 * t1 + t0 + 8) >> 4) as u8; } output[input_width * 2 - 1] = ((t1 + 2) >> 2) as u8; @@ -229,14 +268,16 @@ impl Upsample for UpsamplerH2V2 { impl Upsample for UpsamplerGeneric { // Uses nearest neighbor sampling - fn upsample_row(&self, - input: &[u8], - input_width: usize, - _input_height: usize, - row_stride: usize, - row: usize, - _output_width: usize, - output: &mut [u8]) { + fn upsample_row( + &self, + input: &[u8], + input_width: usize, + _input_height: usize, + row_stride: usize, + row: usize, + _output_width: usize, + output: &mut [u8], + ) { let mut index = 0; let start = (row / self.vertical_scaling_factor as usize) * row_stride; let input = &input[start..(start + input_width)]; diff --git a/src/worker/immediate.rs b/src/worker/immediate.rs index 8c6e7dbd..448812d8 100644 --- a/src/worker/immediate.rs +++ b/src/worker/immediate.rs @@ -1,13 +1,13 @@ -use alloc::vec; -use alloc::vec::Vec; -use core::mem; -use core::convert::TryInto; +use super::{RowData, Worker}; +use crate::alloc::sync::Arc; use crate::decoder::MAX_COMPONENTS; use crate::error::Result; use crate::idct::dequantize_and_idct_block; -use crate::alloc::sync::Arc; use crate::parser::Component; -use super::{RowData, Worker}; +use alloc::vec; +use alloc::vec::Vec; +use core::convert::TryInto; +use core::mem; pub struct ImmediateWorker { offsets: [usize; MAX_COMPONENTS], @@ -32,7 +32,13 @@ impl ImmediateWorker { assert!(self.results[data.index].is_empty()); self.offsets[data.index] = 0; - self.results[data.index].resize(data.component.block_size.width as usize * data.component.block_size.height as usize * data.component.dct_scale * data.component.dct_scale, 0u8); + self.results[data.index].resize( + data.component.block_size.width as usize + * data.component.block_size.height as usize + * data.component.dct_scale + * data.component.dct_scale, + 0u8, + ); self.components[data.index] = Some(data.component); self.quantization_tables[data.index] = Some(data.quantization_table); } @@ -42,7 +48,8 @@ impl ImmediateWorker { let component = self.components[index].as_ref().unwrap(); let quantization_table = self.quantization_tables[index].as_ref().unwrap(); - let block_count = component.block_size.width as usize * component.vertical_sampling_factor as usize; + let block_count = + component.block_size.width as usize * component.vertical_sampling_factor as usize; let line_stride = component.block_size.width as usize * component.dct_scale; assert_eq!(data.len(), block_count * 64); @@ -54,7 +61,13 @@ impl ImmediateWorker { let coefficients = data[i * 64..(i + 1) * 64].try_into().unwrap(); let output = &mut self.results[index][self.offsets[index] + y * line_stride + x..]; - dequantize_and_idct_block(component.dct_scale, coefficients, quantization_table, line_stride, output); + dequantize_and_idct_block( + component.dct_scale, + coefficients, + quantization_table, + line_stride, + output, + ); } self.offsets[index] += block_count * component.dct_scale * component.dct_scale; diff --git a/tests/lib.rs b/tests/lib.rs index 3ee186be..fe4c6330 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -2,18 +2,21 @@ extern crate jpeg_decoder as jpeg; extern crate png; extern crate walkdir; -use std::path::Path; use std::fs::File; +use std::path::Path; mod common; mod crashtest; mod reftest; #[test] -#[cfg(all(target_family="wasm", target_os="unknown"))] +#[cfg(all(target_family = "wasm", target_os = "unknown"))] #[wasm_bindgen_test::wasm_bindgen_test] fn included_file() { - const FILE: &[u8] = include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/reftest/images/mozilla/jpg-progressive.jpg")); + const FILE: &[u8] = include_bytes!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/tests/reftest/images/mozilla/jpg-progressive.jpg", + )); let mut data = FILE; let mut decoder = jpeg::Decoder::new(&mut data); @@ -33,7 +36,11 @@ fn included_file() { #[test] fn read_info() { - let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); + let path = Path::new("tests") + .join("reftest") + .join("images") + .join("mozilla") + .join("jpg-progressive.jpg"); let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); let ref_data = decoder.decode().unwrap(); @@ -68,9 +75,7 @@ fn read_icc_profile() { // Test if chunks are concatenated in the correct order #[test] fn read_icc_profile_random_order() { - let path = Path::new("tests") - .join("icc") - .join("icc_chunk_order.jpeg"); + let path = Path::new("tests").join("icc").join("icc_chunk_order.jpeg"); let mut decoder = jpeg::Decoder::new(File::open(&path).unwrap()); decoder.decode().unwrap(); diff --git a/tests/rayon-0.rs b/tests/rayon-0.rs index 484816cc..05db6d7e 100644 --- a/tests/rayon-0.rs +++ b/tests/rayon-0.rs @@ -1,10 +1,14 @@ //! Must be a separate test because it modifies the _global_ rayon pool. -use std::{fs::File, path::Path}; use jpeg_decoder::Decoder; +use std::{fs::File, path::Path}; #[test] fn decoding_in_global_pool() { - let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); + let path = Path::new("tests") + .join("reftest") + .join("images") + .join("mozilla") + .join("jpg-progressive.jpg"); rayon::ThreadPoolBuilder::new() .num_threads(1) diff --git a/tests/rayon-1.rs b/tests/rayon-1.rs index e6bd8968..f0520394 100644 --- a/tests/rayon-1.rs +++ b/tests/rayon-1.rs @@ -1,10 +1,14 @@ //! Must be a separate test because it modifies the _global_ rayon pool. -use std::{fs::File, path::Path}; use jpeg_decoder::Decoder; +use std::{fs::File, path::Path}; #[test] fn decoding_in_fetched_global_pool() { - let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); + let path = Path::new("tests") + .join("reftest") + .join("images") + .join("mozilla") + .join("jpg-progressive.jpg"); rayon::ThreadPoolBuilder::new() .num_threads(1) diff --git a/tests/rayon-2.rs b/tests/rayon-2.rs index 982f837e..9b3eec0d 100644 --- a/tests/rayon-2.rs +++ b/tests/rayon-2.rs @@ -1,6 +1,6 @@ //! Must be a separate test because it modifies the _global_ rayon pool. -use std::{fs::File, path::Path}; use jpeg_decoder::Decoder; +use std::{fs::File, path::Path}; #[test] fn decoding_in_global_pool() { @@ -18,6 +18,6 @@ fn decoding_in_global_pool() { let mut decoder = Decoder::new(File::open(&path).unwrap()); let _ = decoder.decode().unwrap(); }); - }).collect(); + }) + .collect(); } - diff --git a/tests/rayon.rs b/tests/rayon.rs index 9222a854..67997a90 100644 --- a/tests/rayon.rs +++ b/tests/rayon.rs @@ -1,9 +1,13 @@ -use std::{fs::File, path::Path}; use jpeg_decoder::Decoder; +use std::{fs::File, path::Path}; #[test] fn decoding_in_limited_threadpool_does_not_deadlock() { - let path = Path::new("tests").join("reftest").join("images").join("mozilla").join("jpg-progressive.jpg"); + let path = Path::new("tests") + .join("reftest") + .join("images") + .join("mozilla") + .join("jpg-progressive.jpg"); let pool = rayon::ThreadPoolBuilder::new() .num_threads(1) diff --git a/tests/reftest/mod.rs b/tests/reftest/mod.rs index 9b2eeab0..62958aca 100644 --- a/tests/reftest/mod.rs +++ b/tests/reftest/mod.rs @@ -16,6 +16,7 @@ fn reftest() { } #[test] +#[rustfmt::skip] fn reftest_scaled() { let base = &Path::new("tests").join("reftest").join("images"); reftest_scaled_file(&base.join("rgb.jpg"), 500, 333, &base.join("rgb.png")); @@ -39,7 +40,9 @@ fn reftest_scaled_file(path: &Path, width: u16, height: u16, ref_path: &Path) { } fn reftest_decoder(mut decoder: jpeg::Decoder, path: &Path, ref_path: &Path) { - let mut data = decoder.decode().expect(&format!("failed to decode file: {:?}", path)); + let mut data = decoder + .decode() + .expect(&format!("failed to decode file: {:?}", path)); let info = decoder.info().unwrap(); let mut pixel_format = info.pixel_format; @@ -55,68 +58,97 @@ fn reftest_decoder(mut decoder: jpeg::Decoder, path: &Path, // disable the default 8bit output of png v0.16.8 (fixed in master branch of png) decoder.set_transformations(png::Transformations::EXPAND); } - + let (ref_info, mut ref_reader) = decoder.read_info().expect("png failed to read info"); assert_eq!(ref_info.width, info.width as u32); assert_eq!(ref_info.height, info.height as u32); let mut ref_data = vec![0; ref_info.buffer_size()]; - ref_reader.next_frame(&mut ref_data).expect("png decode failed"); + ref_reader + .next_frame(&mut ref_data) + .expect("png decode failed"); let mut ref_pixel_format = ref_info.color_type; - if ref_pixel_format == png::ColorType::RGBA { + if ref_pixel_format == png::ColorType::RGBA { ref_data = rgba_to_rgb(&ref_data); ref_pixel_format = png::ColorType::RGB; } - let (refdata_16, data_u16) : (Vec, Vec) = match pixel_format { + let (refdata_16, data_u16): (Vec, Vec) = match pixel_format { jpeg::PixelFormat::L8 => { assert_eq!(ref_pixel_format, png::ColorType::Grayscale); assert_eq!(ref_info.bit_depth, png::BitDepth::Eight); - (ref_data.iter().map(|x| *x as u16).collect(), data.iter().map(|x| *x as u16).collect()) - }, + ( + ref_data.iter().map(|x| *x as u16).collect(), + data.iter().map(|x| *x as u16).collect(), + ) + } jpeg::PixelFormat::L16 => { assert_eq!(ref_pixel_format, png::ColorType::Grayscale); assert_eq!(ref_info.bit_depth, png::BitDepth::Sixteen); - (ref_data.chunks_exact(2).map(|a| u16::from_be_bytes([a[0],a[1]])).collect(), - data.chunks_exact(2).map(|a| u16::from_ne_bytes([a[0],a[1]])).collect()) - }, + ( + ref_data + .chunks_exact(2) + .map(|a| u16::from_be_bytes([a[0], a[1]])) + .collect(), + data.chunks_exact(2) + .map(|a| u16::from_ne_bytes([a[0], a[1]])) + .collect(), + ) + } jpeg::PixelFormat::RGB24 => { assert_eq!(ref_pixel_format, png::ColorType::RGB); assert_eq!(ref_info.bit_depth, png::BitDepth::Eight); - (ref_data.iter().map(|x| *x as u16).collect(), data.iter().map(|x| *x as u16).collect()) - }, + ( + ref_data.iter().map(|x| *x as u16).collect(), + data.iter().map(|x| *x as u16).collect(), + ) + } _ => panic!(), }; assert_eq!(data_u16.len(), refdata_16.len()); let mut max_diff = 0; - let pixels: Vec = data_u16.iter().zip(refdata_16.iter()).map(|(&a, &b)| { - let diff = (a as isize - b as isize).abs(); - max_diff = cmp::max(diff, max_diff); - - if (info.coding_process != jpeg::CodingProcess::Lossless && diff <= 3) || diff == 0 { - // White for correct - 0xFF - } else { - // "1100" in the RGBA channel with an error for an incorrect value - // This results in some number of C0 and FFs, which is much more - // readable (and distinguishable) than the previous difference-wise - // scaling but does not require reconstructing the actual RGBA pixel. - 0xC0 - } - }).collect(); + let pixels: Vec = data_u16 + .iter() + .zip(refdata_16.iter()) + .map(|(&a, &b)| { + let diff = (a as isize - b as isize).abs(); + max_diff = cmp::max(diff, max_diff); + + if (info.coding_process != jpeg::CodingProcess::Lossless && diff <= 3) || diff == 0 { + // White for correct + 0xFF + } else { + // "1100" in the RGBA channel with an error for an incorrect value + // This results in some number of C0 and FFs, which is much more + // readable (and distinguishable) than the previous difference-wise + // scaling but does not require reconstructing the actual RGBA pixel. + 0xC0 + } + }) + .collect(); if pixels.iter().any(|&a| a < 255) { - let output_path = path.with_file_name(format!("{}-diff.png", path.file_stem().unwrap().to_str().unwrap())); + let output_path = path.with_file_name(format!( + "{}-diff.png", + path.file_stem().unwrap().to_str().unwrap() + )); let output = File::create(&output_path).unwrap(); let mut encoder = png::Encoder::new(output, info.width as u32, info.height as u32); encoder.set_depth(png::BitDepth::Eight); encoder.set_color(ref_pixel_format); - encoder.write_header().expect("png failed to write header").write_image_data(&pixels).expect("png failed to write data"); - - panic!("decoding difference: {:?}, maximum difference was {}", output_path, max_diff); + encoder + .write_header() + .expect("png failed to write header") + .write_image_data(&pixels) + .expect("png failed to write data"); + + panic!( + "decoding difference: {:?}, maximum difference was {}", + output_path, max_diff, + ); } } From 43393c8dac016ef13817a5e21549ee718491e565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Kr=C3=B3lak?= Date: Sun, 30 Apr 2023 15:51:11 +0200 Subject: [PATCH 2/2] Reformat expression to pass rustfmt --- src/arch/wasm.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/arch/wasm.rs b/src/arch/wasm.rs index ec29428e..10ac820b 100644 --- a/src/arch/wasm.rs +++ b/src/arch/wasm.rs @@ -175,13 +175,9 @@ pub fn dequantize_and_idct_block_8x8( // SAFETY: the assert at the start of this function ensures // `output_linestride * i + 7` < output.len(), so all accesses are in-bounds. - #[rustfmt::skip] unsafe { v128_store64_lane::<0>( - u8x16_narrow_i16x8( - i16x8_shr(data_with_offset, SHIFT + 3), - i16x8_splat(0), - ), + u8x16_narrow_i16x8(i16x8_shr(data_with_offset, SHIFT + 3), i16x8_splat(0)), output.as_mut_ptr().wrapping_add(output_linestride * i) as *mut _, ); }