Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Format Rust code #279

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 24 additions & 20 deletions benches/decoding_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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/1/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/1/jpeg_lossless_sel1-rgb.jpg"
))
})
});
c.final_summary();
}
}
21 changes: 11 additions & 10 deletions examples/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,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<u8> {
Expand Down
37 changes: 22 additions & 15 deletions src/arch/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ fn transpose8(data: &mut [v128; 8]) {
// A0 B0 A1 B1 ...
// dABCDll contains elements from the lower quarter (ll) of vectors A, B, C, D, interleaved -
// A0 B0 C0 D0 A1 B1 C1 D1 ...
let d01l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[0], data[1]);
let d23l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[2], data[3]);
let d45l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[4], data[5]);
let d67l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[6], data[7]);
let d01h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[0], data[1]);
let d23h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[2], data[3]);
let d45h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[4], data[5]);
let d67h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[6], data[7]);
let d01l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[0], data[1]);
let d23l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[2], data[3]);
let d45l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[4], data[5]);
let d67l = i16x8_shuffle::<0, 8, 1, 9, 2, 10, 3, 11>(data[6], data[7]);
let d01h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[0], data[1]);
let d23h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[2], data[3]);
let d45h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[4], data[5]);
let d67h = i16x8_shuffle::<4, 12, 5, 13, 6, 14, 7, 15>(data[6], data[7]);

// Operating on 32-bits will interleave *consecutive pairs* of 16-bit integers.
let d0123ll = i32x4_shuffle::<0, 4, 1, 5>(d01l, d23l);
Expand Down Expand Up @@ -176,10 +176,7 @@ pub fn dequantize_and_idct_block_8x8(
// `output_linestride * i + 7` < output.len(), so all accesses are in-bounds.
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 _,
);
}
Expand All @@ -188,8 +185,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());
Expand Down Expand Up @@ -242,6 +243,7 @@ pub fn color_convert_line_ycbcr(y_slice: &[u8], cb_slice: &[u8], cr_slice: &[u8]

// Shuffle rrrrrrrrggggggggbbbbbbbb to rgbrgbrgb...

#[rustfmt::skip]
let rg_lanes = i8x16_shuffle::<0, 16,
1, 17,
2, 18,
Expand All @@ -251,13 +253,15 @@ 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
6, 7, 19, // r3, g3, b3
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, --
Expand All @@ -269,7 +273,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 _,
);
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -790,7 +790,7 @@ impl<R: Read> Decoder<R> {
}
}

#[allow(clippy::type_complexity)]
#[allow(clippy::type_complexity)]
fn decode_scan(
&mut self,
frame: &FrameInfo,
Expand Down
58 changes: 38 additions & 20 deletions src/huffman.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ 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;
use crate::read_u8;

const LUT_BITS: u8 = 8;

Expand Down Expand Up @@ -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] {
Expand All @@ -57,7 +57,11 @@ impl HuffmanDecoder {
}
}

pub fn decode_fast_ac<R: Read>(&mut self, reader: &mut R, table: &HuffmanTable) -> Result<Option<(i16, u8)>> {
pub fn decode_fast_ac<R: Read>(
&mut self,
reader: &mut R,
table: &HuffmanTable,
) -> Result<Option<(i16, u8)>> {
if let Some(ref ac_lut) = table.ac_lut {
if self.num_bits < LUT_BITS {
self.read_bits(reader)?;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -231,15 +243,17 @@ impl HuffmanTable {
let magnitude_category = value & 0x0f;

if magnitude_category > 0 && size + magnitude_category <= LUT_BITS {
let unextended_ac_value = (((i << size) & ((1 << LUT_BITS) - 1)) >> (LUT_BITS - magnitude_category)) as u16;
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);

table[i] = (ac_value, (run_length << 4) | (size + magnitude_category));
}
}

Some(table)
},
}
};

Ok(HuffmanTable {
Expand All @@ -255,12 +269,13 @@ impl HuffmanTable {
// Section C.2
fn derive_huffman_codes(bits: &[u8; 16]) -> Result<(Vec<u16>, Vec<u8>)> {
// 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()];
Expand Down Expand Up @@ -292,9 +307,12 @@ fn derive_huffman_codes(bits: &[u8; 16]) -> Result<(Vec<u16>, Vec<u8>)> {
// 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<HuffmanTable>],
ac_huffman_tables: &mut[Option<HuffmanTable>]) {
#[rustfmt::skip]
pub fn fill_default_mjpeg_tables(
scan: &ScanInfo,
dc_huffman_tables: &mut[Option<HuffmanTable>],
ac_huffman_tables: &mut[Option<HuffmanTable>],
) {
// Section K.3.3

if dc_huffman_tables[0].is_none() && scan.dc_table_indices.iter().any(|&i| i == 0) {
Expand Down
3 changes: 2 additions & 1 deletion src/idct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,8 @@ fn dequantize_and_idct_block_1x1(
) {
debug_assert_eq!(coefficients.len(), 64);

let s0 = (Wrapping(coefficients[0] as i32 * quantization_table[0] as i32) + Wrapping(128 * 8)) / Wrapping(8);
let s0 = (Wrapping(coefficients[0] as i32 * quantization_table[0] as i32) + Wrapping(128 * 8))
/ Wrapping(8);
output[0] = stbi_clamp(s0);
}

Expand Down
4 changes: 2 additions & 2 deletions src/marker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,15 @@ 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<Marker> {
use self::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)),
Expand Down
Loading
Loading