From 1305b5cf173458e0424176cb0ff0633eb619e101 Mon Sep 17 00:00:00 2001 From: Joshua Holmer Date: Mon, 26 Nov 2018 13:41:14 -0500 Subject: [PATCH] Fix clippy lints and run rustfmt --- benches/reductions.rs | 24 ++++---------- src/deflate/cfzlib.rs | 20 ++++++++---- src/interlace.rs | 7 ++-- src/lib.rs | 37 ++++++++++++--------- src/png/mod.rs | 74 +++++++++++++++++++++++++++++------------- src/png/scan_lines.rs | 21 +++++------- src/reduction/color.rs | 57 +++++++++++++++++++++++--------- tests/lib.rs | 2 +- 8 files changed, 147 insertions(+), 95 deletions(-) diff --git a/benches/reductions.rs b/benches/reductions.rs index 27aa1e77..82381b96 100644 --- a/benches/reductions.rs +++ b/benches/reductions.rs @@ -260,9 +260,7 @@ fn reductions_alpha_black(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_black.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| { - png.reduced_alpha_channel(AlphaOptim::Black) - }); + b.iter(|| png.reduced_alpha_channel(AlphaOptim::Black)); } #[bench] @@ -270,9 +268,7 @@ fn reductions_alpha_white(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_white.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| { - png.reduced_alpha_channel(AlphaOptim::White) - }); + b.iter(|| png.reduced_alpha_channel(AlphaOptim::White)); } #[bench] @@ -280,9 +276,7 @@ fn reductions_alpha_left(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_left.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| { - png.reduced_alpha_channel(AlphaOptim::Left) - }); + b.iter(|| png.reduced_alpha_channel(AlphaOptim::Left)); } #[bench] @@ -290,9 +284,7 @@ fn reductions_alpha_right(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_right.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| { - png.reduced_alpha_channel(AlphaOptim::Right) - }); + b.iter(|| png.reduced_alpha_channel(AlphaOptim::Right)); } #[bench] @@ -300,9 +292,7 @@ fn reductions_alpha_up(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_up.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| { - png.reduced_alpha_channel(AlphaOptim::Up) - }); + b.iter(|| png.reduced_alpha_channel(AlphaOptim::Up)); } #[bench] @@ -310,7 +300,5 @@ fn reductions_alpha_down(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_reduce_alpha_down.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| { - png.reduced_alpha_channel(AlphaOptim::Down) - }); + b.iter(|| png.reduced_alpha_channel(AlphaOptim::Down)); } diff --git a/src/deflate/cfzlib.rs b/src/deflate/cfzlib.rs index 540c52b7..8bbab2a9 100644 --- a/src/deflate/cfzlib.rs +++ b/src/deflate/cfzlib.rs @@ -1,8 +1,8 @@ use atomicmin::AtomicMin; -use PngResult; -use PngError; -use cloudflare_zlib::*; pub use cloudflare_zlib::is_supported; +use cloudflare_zlib::*; +use PngError; +use PngResult; impl From for PngError { fn from(err: ZError) -> Self { @@ -21,14 +21,14 @@ pub fn cfzlib_deflate( max_size: &AtomicMin, ) -> PngResult> { let mut stream = Deflate::new(level.into(), strategy.into(), window_bits.into())?; - stream.reserve(max_size.get().unwrap_or(data.len()/2)); + stream.reserve(max_size.get().unwrap_or(data.len() / 2)); let max_size = max_size.as_atomic_usize(); // max size is generally checked after each split, // so splitting the buffer into pieces gices more checks // = better chance of hitting it sooner. - let (first, rest) = data.split_at(data.len()/2); + let (first, rest) = data.split_at(data.len() / 2); stream.compress_with_limit(first, max_size)?; - let (rest1, rest2) = rest.split_at(rest.len()/2); + let (rest1, rest2) = rest.split_at(rest.len() / 2); stream.compress_with_limit(rest1, max_size)?; stream.compress_with_limit(rest2, max_size)?; Ok(stream.finish()?) @@ -36,7 +36,13 @@ pub fn cfzlib_deflate( #[test] fn compress_test() { - let vec = cfzlib_deflate(b"azxcvbnm", Z_BEST_COMPRESSION as u8, Z_DEFAULT_STRATEGY as u8, 15, &AtomicMin::new(None)).unwrap(); + let vec = cfzlib_deflate( + b"azxcvbnm", + Z_BEST_COMPRESSION as u8, + Z_DEFAULT_STRATEGY as u8, + 15, + &AtomicMin::new(None), + ).unwrap(); let res = ::deflate::inflate(&vec).unwrap(); assert_eq!(&res, b"azxcvbnm"); } diff --git a/src/interlace.rs b/src/interlace.rs index e5a59129..6d720e90 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -93,8 +93,11 @@ pub fn deinterlace_image(png: &mut PngData) { let mut current_y: usize = pass_constants.y_shift as usize; for line in png.scan_lines() { let bit_vec = BitVec::from_bytes(&line.data); - let bits_in_line = ((png.ihdr_data.width - u32::from(pass_constants.x_shift) + u32::from(pass_constants.x_step) - 1) - / u32::from(pass_constants.x_step)) as usize * bits_per_pixel as usize; + let bits_in_line = ((png.ihdr_data.width - u32::from(pass_constants.x_shift) + + u32::from(pass_constants.x_step) + - 1) + / u32::from(pass_constants.x_step)) as usize + * bits_per_pixel as usize; for (i, bit) in bit_vec.iter().enumerate() { // Avoid moving padded 0's into new image if i >= bits_in_line { diff --git a/src/lib.rs b/src/lib.rs index be5a6ff0..b6119de8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,19 +4,19 @@ extern crate byteorder; extern crate cloudflare_zlib; extern crate crc; extern crate image; -extern crate rgb; extern crate itertools; extern crate miniz_oxide; extern crate num_cpus; #[cfg(feature = "parallel")] extern crate rayon; +extern crate rgb; extern crate zopfli; use atomicmin::AtomicMin; +use crc::crc32; +use deflate::inflate; use image::{DynamicImage, GenericImageView, ImageFormat, Pixel}; use png::PngData; -use deflate::inflate; -use crc::crc32; #[cfg(feature = "parallel")] use rayon::prelude::*; use std::collections::{HashMap, HashSet}; @@ -867,8 +867,11 @@ fn perform_strip(png: &mut PngData, opts: &Options) { if png.aux_headers.get(b"sRGB").is_some() { // Files aren't supposed to have both chunks, so we chose to honor sRGB png.aux_headers.remove(b"iCCP"); - } else if let Some(intent) = png.aux_headers.get(b"iCCP") - .and_then(|iccp| srgb_rendering_intent(iccp)) { + } else if let Some(intent) = png + .aux_headers + .get(b"iCCP") + .and_then(|iccp| srgb_rendering_intent(iccp)) + { // sRGB-like profile can be safely replaced with // an sRGB chunk with the same rendering intent png.aux_headers.remove(b"iCCP"); @@ -883,7 +886,9 @@ fn srgb_rendering_intent(mut iccp: &[u8]) -> Option { loop { let (&n, rest) = iccp.split_first()?; iccp = rest; - if n == 0 {break;} + if n == 0 { + break; + } } let (&compression_method, compressed_data) = iccp.split_first()?; @@ -898,21 +903,21 @@ fn srgb_rendering_intent(mut iccp: &[u8]) -> Option { // The Profile ID header of ICC has a fixed layout, // and is supposed to contain MD5 of profile data at this offset match icc_data.get(84..100)? { - b"\x29\xf8\x3d\xde\xaf\xf2\x55\xae\x78\x42\xfa\xe4\xca\x83\x39\x0d" | - b"\xc9\x5b\xd6\x37\xe9\x5d\x8a\x3b\x0d\xf3\x8f\x99\xc1\x32\x03\x89" | - b"\xfc\x66\x33\x78\x37\xe2\x88\x6b\xfd\x72\xe9\x83\x82\x28\xf1\xb8" | - b"\x34\x56\x2a\xbf\x99\x4c\xcd\x06\x6d\x2c\x57\x21\xd0\xd6\x8c\x5d" => { + b"\x29\xf8\x3d\xde\xaf\xf2\x55\xae\x78\x42\xfa\xe4\xca\x83\x39\x0d" + | b"\xc9\x5b\xd6\x37\xe9\x5d\x8a\x3b\x0d\xf3\x8f\x99\xc1\x32\x03\x89" + | b"\xfc\x66\x33\x78\x37\xe2\x88\x6b\xfd\x72\xe9\x83\x82\x28\xf1\xb8" + | b"\x34\x56\x2a\xbf\x99\x4c\xcd\x06\x6d\x2c\x57\x21\xd0\xd6\x8c\x5d" => { Some(rendering_intent) - }, + } b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" => { // Known-bad profiles are identified by their CRC match (crc32::checksum_ieee(&icc_data), icc_data.len()) { - (0x5d5129ce, 3024) | - (0x182ea552, 3144) | - (0xf29e526d, 3144) => Some(rendering_intent), - _ => None, + (0x5d51_29ce, 3024) | (0x182e_a552, 3144) | (0xf29e_526d, 3144) => { + Some(rendering_intent) + } + _ => None, } - }, + } _ => None, } } diff --git a/src/png/mod.rs b/src/png/mod.rs index f78bbdfd..b3b38777 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -1,6 +1,3 @@ -use std::collections::hash_map::Entry::*; -use rgb::RGBA8; -use rgb::ComponentSlice; use atomicmin::AtomicMin; use byteorder::{BigEndian, WriteBytesExt}; use colors::{AlphaOptim, BitDepth, ColorType}; @@ -15,6 +12,9 @@ use itertools::flatten; use rayon::prelude::*; use reduction::bit_depth::*; use reduction::color::*; +use rgb::ComponentSlice; +use rgb::RGBA8; +use std::collections::hash_map::Entry::*; use std::collections::{HashMap, HashSet}; use std::fs::File; use std::io::{Read, Seek, SeekFrom}; @@ -49,6 +49,8 @@ pub struct PngData { pub aux_headers: HashMap<[u8; 4], Vec>, } +type PaletteWithTrns = (Option>, Option>); + impl PngData { /// Create a new `PngData` struct by opening a file #[inline] @@ -116,7 +118,11 @@ impl PngData { let ihdr_header = parse_ihdr_header(&ihdr)?; let raw_data = deflate::inflate(idat_headers.as_ref())?; - let (palette, transparency_pixel) = Self::palette_to_rgba(ihdr_header.color_type, aux_headers.remove(b"PLTE"), aux_headers.remove(b"tRNS"))?; + let (palette, transparency_pixel) = Self::palette_to_rgba( + ihdr_header.color_type, + aux_headers.remove(b"PLTE"), + aux_headers.remove(b"tRNS"), + )?; let mut png_data = Self { idat_data: idat_headers, @@ -132,10 +138,16 @@ impl PngData { } /// Handle transparency header - fn palette_to_rgba(color_type: ColorType, palette_data: Option>, trns_data: Option>) -> Result<(Option>, Option>), PngError> { + fn palette_to_rgba( + color_type: ColorType, + palette_data: Option>, + trns_data: Option>, + ) -> Result { if color_type == ColorType::Indexed { - let palette_data = palette_data.ok_or_else(|| PngError::new("no palette in indexed image"))?; - let mut palette: Vec<_> = palette_data.chunks(3) + let palette_data = + palette_data.ok_or_else(|| PngError::new("no palette in indexed image"))?; + let mut palette: Vec<_> = palette_data + .chunks(3) .map(|color| RGBA8::new(color[0], color[1], color[2], 255)) .collect(); @@ -189,14 +201,22 @@ impl PngData { } // Palette if let Some(ref palette) = self.palette { - let mut palette_data = Vec::with_capacity(palette.len()*3); + let mut palette_data = Vec::with_capacity(palette.len() * 3); for px in palette { palette_data.extend_from_slice(px.rgb().as_slice()); } write_png_block(b"PLTE", &palette_data, &mut output); - let num_transparent = palette.iter().enumerate().fold(0, |prev, (index, px)| { - if px.a != 255 {index+1} else {prev} - }); + let num_transparent = + palette.iter().enumerate().fold( + 0, + |prev, (index, px)| { + if px.a != 255 { + index + 1 + } else { + prev + } + }, + ); if num_transparent > 0 { let trns_data: Vec<_> = palette[0..num_transparent].iter().map(|px| px.a).collect(); write_png_block(b"tRNS", &trns_data, &mut output); @@ -389,21 +409,26 @@ impl PngData { let mut next_index = 0; let mut seen = HashMap::with_capacity(palette.len()); - for (i, (used, palette_map)) in used.iter().cloned().zip(palette_map.iter_mut()).enumerate() { + for (i, (used, palette_map)) in + used.iter().cloned().zip(palette_map.iter_mut()).enumerate() + { if !used { continue; } // There are invalid files that use pixel indices beyond palette size - let color = palette.get(i).cloned().unwrap_or(RGBA8::new(0,0,0,255)); + let color = palette + .get(i) + .cloned() + .unwrap_or_else(|| RGBA8::new(0, 0, 0, 255)); match seen.entry(color) { Vacant(new) => { *palette_map = next_index; new.insert(next_index); next_index += 1; - }, + } Occupied(remap_to) => { *palette_map = *remap_to.get(); - }, + } } } if (0..palette.len()).all(|i| palette_map[i] == i as u8) { @@ -421,14 +446,14 @@ impl PngData { // low bit-depths can be pre-computed for every byte value match self.ihdr_data.bit_depth { BitDepth::Four => for byte in 0..=255 { - byte_map[byte as usize] = palette_map[(byte & 0x0F) as usize] | - (palette_map[(byte >> 4) as usize] << 4); + byte_map[byte as usize] = + palette_map[(byte & 0x0F) as usize] | (palette_map[(byte >> 4) as usize] << 4); }, BitDepth::Two => for byte in 0..=255 { - byte_map[byte as usize] = palette_map[(byte & 0x03) as usize] | - (palette_map[((byte >> 2) & 0x03) as usize] << 2) | - (palette_map[((byte >> 4) & 0x03) as usize] << 4) | - (palette_map[((byte >> 6)) as usize] << 6); + byte_map[byte as usize] = palette_map[(byte & 0x03) as usize] + | (palette_map[((byte >> 2) & 0x03) as usize] << 2) + | (palette_map[((byte >> 4) & 0x03) as usize] << 4) + | (palette_map[(byte >> 6) as usize] << 6); }, _ => {} } @@ -443,8 +468,11 @@ impl PngData { self.transparency_pixel = None; if let Some(palette) = self.palette.take() { let max_index = palette_map.iter().max().cloned().unwrap_or(0) as usize; - let mut new_palette = vec![RGBA8::new(0,0,0,255); max_index+1]; - for (color, (map_to, used)) in palette.into_iter().zip(palette_map.iter().cloned().zip(used.iter().cloned())) { + let mut new_palette = vec![RGBA8::new(0, 0, 0, 255); max_index + 1]; + for (color, (map_to, used)) in palette + .into_iter() + .zip(palette_map.iter().cloned().zip(used.iter().cloned())) + { if used { new_palette[map_to as usize] = color; } diff --git a/src/png/scan_lines.rs b/src/png/scan_lines.rs index 25adc946..b7c0132d 100644 --- a/src/png/scan_lines.rs +++ b/src/png/scan_lines.rs @@ -25,11 +25,7 @@ impl<'a> Iterator for ScanLines<'a> { let (data, rest) = self.raw_data.split_at(len); self.raw_data = rest; let (&filter, data) = data.split_first().unwrap(); - ScanLine { - filter, - data, - pass, - } + ScanLine { filter, data, pass } }) } } @@ -60,11 +56,7 @@ impl<'a> Iterator for ScanLinesMut<'a> { let (data, rest) = tmp.split_at_mut(len); self.raw_data = Some(rest); let (&mut filter, data) = data.split_first_mut().unwrap(); - ScanLineMut { - filter, - data, - pass, - } + ScanLineMut { filter, data, pass } }) } } @@ -87,7 +79,11 @@ impl ScanLineRanges { width: png.ihdr_data.width, height: png.ihdr_data.height, left: png.raw_data.len(), - pass: if png.ihdr_data.interlaced == 1 {Some((1, 0))} else {None}, + pass: if png.ihdr_data.interlaced == 1 { + Some((1, 0)) + } else { + None + }, } } } @@ -154,7 +150,7 @@ impl Iterator for ScanLineRanges { // Standard, non-interlaced PNG scanlines (self.width, None) }; - let bits_per_line = pixels_per_line * self.bits_per_pixel as u32; + let bits_per_line = pixels_per_line * u32::from(self.bits_per_pixel); let bytes_per_line = ((bits_per_line + 7) / 8) as usize; let len = bytes_per_line + 1; self.left -= len; @@ -173,7 +169,6 @@ pub struct ScanLine<'a> { pub pass: Option, } - #[derive(Debug)] /// A scan line in a PNG image pub struct ScanLineMut<'a> { diff --git a/src/reduction/color.rs b/src/reduction/color.rs index 67adb03c..f0327f48 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -1,9 +1,9 @@ -use std::hash::Hash; -use rgb::{RGBA8, RGB8, FromSlice}; use colors::{BitDepth, ColorType}; use itertools::Itertools; use png::PngData; +use rgb::{FromSlice, RGB8, RGBA8}; use std::collections::HashMap; +use std::hash::Hash; use super::alpha::reduce_alpha_channel; @@ -74,8 +74,14 @@ pub fn reduce_rgba_to_grayscale_alpha(png: &mut PngData) -> bool { true } -fn reduce_scanline_to_palette(iter: impl IntoIterator, palette: &mut HashMap, reduced: &mut Vec) -> bool - where T: Eq + Hash { +fn reduce_scanline_to_palette( + iter: impl IntoIterator, + palette: &mut HashMap, + reduced: &mut Vec, +) -> bool +where + T: Eq + Hash, +{ for pixel in iter { let idx = if let Some(&idx) = palette.get(&pixel) { idx @@ -99,28 +105,49 @@ pub fn reduce_color_to_palette(png: &mut PngData) -> bool { } let mut reduced = Vec::with_capacity(png.raw_data.len()); let mut palette = HashMap::with_capacity(257); - let transparency_pixel = png.transparency_pixel.as_ref().map(|t| RGB8::new(t[1], t[3], t[5])); + let transparency_pixel = png + .transparency_pixel + .as_ref() + .map(|t| RGB8::new(t[1], t[3], t[5])); for line in png.scan_lines() { reduced.push(line.filter); let ok = if png.ihdr_data.color_type == ColorType::RGB { - reduce_scanline_to_palette(line.data.as_rgb().iter().cloned().map(|px| { - px.alpha(if Some(px) != transparency_pixel {255} else {0}) - }), &mut palette, &mut reduced) + reduce_scanline_to_palette( + line.data.as_rgb().iter().cloned().map(|px| { + px.alpha(if Some(px) != transparency_pixel { + 255 + } else { + 0 + }) + }), + &mut palette, + &mut reduced, + ) } else { debug_assert_eq!(png.ihdr_data.color_type, ColorType::RGBA); - reduce_scanline_to_palette(line.data.as_rgba().iter().cloned(), &mut palette, &mut reduced) + reduce_scanline_to_palette( + line.data.as_rgba().iter().cloned(), + &mut palette, + &mut reduced, + ) }; if !ok { return false; } } - let num_transparent = palette.iter() - .filter_map(|(px, &idx)| if px.a != 255 {Some(idx as usize +1)} else {None}) - .max(); - let trns_size = num_transparent.map(|n| n+8).unwrap_or(0); + let num_transparent = palette + .iter() + .filter_map(|(px, &idx)| { + if px.a != 255 { + Some(idx as usize + 1) + } else { + None + } + }).max(); + let trns_size = num_transparent.map(|n| n + 8).unwrap_or(0); - let headers_size = palette.len()*3 + 8 + trns_size; + let headers_size = palette.len() * 3 + 8 + trns_size; if reduced.len() + headers_size > png.raw_data.len() { // Reduction would result in a larger image return false; @@ -147,7 +174,7 @@ pub fn reduce_color_to_palette(png: &mut PngData) -> bool { sbit_header.pop(); } - let mut palette_vec = vec![RGBA8::new(0,0,0,0); palette.len()]; + let mut palette_vec = vec![RGBA8::new(0, 0, 0, 0); palette.len()]; for (color, idx) in palette { palette_vec[idx as usize] = color; } diff --git a/tests/lib.rs b/tests/lib.rs index 9233036e..06df94ad 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,7 +1,7 @@ extern crate oxipng; -use oxipng::OutFile; use oxipng::Headers; +use oxipng::OutFile; use std::default::Default; use std::fs; use std::fs::File;