From 0db03c6faffce0b25a41a88e268fdf40868d68f0 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Sun, 3 Sep 2017 23:36:09 -0400 Subject: [PATCH] Fix new clippy lints --- CHANGELOG.md | 1 + Cargo.lock | 29 +++++-- benches/deflate.rs | 2 +- benches/filters.rs | 2 +- benches/interlacing.rs | 2 +- benches/reductions.rs | 2 +- benches/zopfli.rs | 2 +- src/deflate/mod.rs | 9 +- src/error.rs | 4 +- src/filters.rs | 192 +++++++++++++++++++++-------------------- src/interlace.rs | 140 +++++++++++++----------------- src/lib.rs | 119 ++++++++++++------------- src/main.rs | 25 +++--- src/png.rs | 178 +++++++++++++++++--------------------- src/reduction.rs | 23 +++-- tests/reduction.rs | 2 +- 16 files changed, 351 insertions(+), 381 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c8e73cb..0aac5423 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ trials for optimizing the alpha channel, using the previously mentioned fast heuristic. This option will make optimization of images with transparency somewhat slower, but may improve compression. + - Code cleanup ### Version 0.16.3 - Fix command-line help text ([#70](https://github.com/shssoichiro/oxipng/issues/70)) diff --git a/Cargo.lock b/Cargo.lock index 793cf27d..d368c1a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ dependencies = [ "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy 0.0.144 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy 0.0.156 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -98,21 +98,22 @@ dependencies = [ [[package]] name = "clippy" -version = "0.0.144" +version = "0.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clippy_lints 0.0.144 (registry+https://github.com/rust-lang/crates.io-index)", + "clippy_lints 0.0.156 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clippy_lints" -version = "0.0.144" +version = "0.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -176,6 +177,11 @@ name = "gcc" version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "getopts" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "image" version = "0.14.0" @@ -298,6 +304,15 @@ dependencies = [ "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pulldown-cmark" +version = "0.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quine-mc_cluskey" version = "0.2.4" @@ -553,8 +568,8 @@ dependencies = [ "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" "checksum cargo_metadata 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "be1057b8462184f634c3a208ee35b0f935cfd94b694b26deadccd98732088d7b" "checksum clap 2.25.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7f1aabf260a8f3fefa8871f16b531038c98dd9eab1cfa2c575e78c459abfa3a0" -"checksum clippy 0.0.144 (registry+https://github.com/rust-lang/crates.io-index)" = "e0349a693e7dd889e2a008f3b8deaacf33b8b649df01982d29b4a56c13531365" -"checksum clippy_lints 0.0.144 (registry+https://github.com/rust-lang/crates.io-index)" = "0331317f8aa85cb8651ee449814ef7a8ef682009bef8d63b28ac10eedb969f92" +"checksum clippy 0.0.156 (registry+https://github.com/rust-lang/crates.io-index)" = "2811d5bced647bd40952beab39ff901607d7091df81efcc6277efaf87d914291" +"checksum clippy_lints 0.0.156 (registry+https://github.com/rust-lang/crates.io-index)" = "4d0b9204632f8fd5071c10ebfe95709e03438b29447850ac39ea71c575625b26" "checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" "checksum crc 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc1914fae6f18ae347320f0ba5e4fc270e17c037ea621fe41ec7e8adf67d11b0" "checksum deflate 0.7.14 (registry+https://github.com/rust-lang/crates.io-index)" = "e34344f1728e41039d49e87f428bbcb62b6bb82edfc2588253a8aa32a139a3a9" @@ -563,6 +578,7 @@ dependencies = [ "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4b63a4792d4f8f686defe3b39b92127fea6344de5d38202b2ee5a11bbbf29d6a" "checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a" +"checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum image 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d61d2b3f000fb41d268312b92d4dd5ee7823163ceee71a67c676271585dfe598" "checksum inflate 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d1238524675af3938a7c74980899535854b88ba07907bb1c944abe5b8fc437e5" "checksum itertools 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e58359414720377f59889192f1ec0e726049ce5735bc21fdb0c4c8ae638305bb" @@ -579,6 +595,7 @@ dependencies = [ "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" "checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584" "checksum png 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6535266009941ceac9a17e6d681cd2adc75611cd4833db853282e8d4c470239c" +"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" "checksum rand 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "022e0636ec2519ddae48154b028864bdce4eaf7d35226ab8e65c611be97b189d" diff --git a/benches/deflate.rs b/benches/deflate.rs index 7a0727b9..3fa7666f 100644 --- a/benches/deflate.rs +++ b/benches/deflate.rs @@ -1,7 +1,7 @@ #![feature(test)] -extern crate test; extern crate oxipng; +extern crate test; use oxipng::png; use oxipng::deflate; diff --git a/benches/filters.rs b/benches/filters.rs index 602ca391..6708538b 100644 --- a/benches/filters.rs +++ b/benches/filters.rs @@ -1,7 +1,7 @@ #![feature(test)] -extern crate test; extern crate oxipng; +extern crate test; use oxipng::png; use test::Bencher; diff --git a/benches/interlacing.rs b/benches/interlacing.rs index 478aff2a..c87cedd5 100644 --- a/benches/interlacing.rs +++ b/benches/interlacing.rs @@ -1,7 +1,7 @@ #![feature(test)] -extern crate test; extern crate oxipng; +extern crate test; use oxipng::png; use test::Bencher; diff --git a/benches/reductions.rs b/benches/reductions.rs index a0ecc38e..87b187f5 100644 --- a/benches/reductions.rs +++ b/benches/reductions.rs @@ -1,7 +1,7 @@ #![feature(test)] -extern crate test; extern crate oxipng; +extern crate test; use oxipng::png; use oxipng::colors::AlphaOptim; diff --git a/benches/zopfli.rs b/benches/zopfli.rs index 16269c70..9fdc9875 100644 --- a/benches/zopfli.rs +++ b/benches/zopfli.rs @@ -1,7 +1,7 @@ #![feature(test)] -extern crate test; extern crate oxipng; +extern crate test; use oxipng::png; use oxipng::deflate; diff --git a/src/deflate/mod.rs b/src/deflate/mod.rs index d71e52cf..b25edb45 100644 --- a/src/deflate/mod.rs +++ b/src/deflate/mod.rs @@ -1,6 +1,5 @@ use error::PngError; use miniz_sys; -use libc::c_int; use std::cmp::max; use zopfli; @@ -30,8 +29,12 @@ pub fn deflate(data: &[u8], zc: u8, zm: u8, zs: u8, zw: u8) -> Result, P // Compressed input should be smaller than decompressed, so allocate less than data.len() // However, it needs a minimum capacity in order to handle very small images let mut output = Vec::with_capacity(max(1024, data.len() / 20)); - let mut stream = - miniz_stream::Stream::new_compress(zc as c_int, zw as c_int, zm as c_int, zs as c_int); + let mut stream = miniz_stream::Stream::new_compress( + i32::from(zc), + i32::from(zw), + i32::from(zm), + i32::from(zs), + ); loop { match stream.compress_vec(input.as_mut(), output.as_mut()) { miniz_sys::MZ_OK => output.reserve(max(1024, data.len() / 20)), diff --git a/src/error.rs b/src/error.rs index d7e5a768..3a24980f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -23,6 +23,8 @@ impl fmt::Display for PngError { impl PngError { #[inline] pub fn new(description: &str) -> PngError { - PngError { description: description.to_owned() } + PngError { + description: description.to_owned(), + } } } diff --git a/src/filters.rs b/src/filters.rs index 3f227260..5cb5de5b 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -6,17 +6,22 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> Vec } 1 => { filtered.extend_from_slice(&data[0..bpp]); - filtered.extend(data.iter().skip(bpp).zip(data.iter()).map(|(cur, last)| { - cur.wrapping_sub(*last) - })); + filtered.extend( + data.iter() + .skip(bpp) + .zip(data.iter()) + .map(|(cur, last)| cur.wrapping_sub(*last)), + ); } 2 => { if last_line.is_empty() { filtered.extend_from_slice(data); } else { - filtered.extend(data.iter().zip(last_line.iter()).map(|(cur, last)| { - cur.wrapping_sub(*last) - })); + filtered.extend( + data.iter() + .zip(last_line.iter()) + .map(|(cur, last)| cur.wrapping_sub(*last)), + ); }; } 3 => { @@ -28,31 +33,29 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> Vec }); } else { filtered.push(match i.checked_sub(bpp) { - Some(x) => { - byte.wrapping_sub(((data[x] as u16 + last_line[i] as u16) >> 1) as u8) - } + Some(x) => byte.wrapping_sub( + ((u16::from(data[x]) + u16::from(last_line[i])) >> 1) as u8, + ), None => byte.wrapping_sub(last_line[i] >> 1), }); }; } } - 4 => { - for (i, byte) in data.iter().enumerate() { - if last_line.is_empty() { - filtered.push(match i.checked_sub(bpp) { - Some(x) => byte.wrapping_sub(data[x]), - None => *byte, - }); - } else { - filtered.push(match i.checked_sub(bpp) { - Some(x) => { - byte.wrapping_sub(paeth_predictor(data[x], last_line[i], last_line[x])) - } - None => byte.wrapping_sub(last_line[i]), - }); - }; - } - } + 4 => for (i, byte) in data.iter().enumerate() { + if last_line.is_empty() { + filtered.push(match i.checked_sub(bpp) { + Some(x) => byte.wrapping_sub(data[x]), + None => *byte, + }); + } else { + filtered.push(match i.checked_sub(bpp) { + Some(x) => { + byte.wrapping_sub(paeth_predictor(data[x], last_line[i], last_line[x])) + } + None => byte.wrapping_sub(last_line[i]), + }); + }; + }, _ => unreachable!(), } filtered @@ -64,8 +67,58 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V 0 => { unfiltered.extend_from_slice(data); } - 1 => { - for (i, byte) in data.iter().enumerate() { + 1 => for (i, byte) in data.iter().enumerate() { + match i.checked_sub(bpp) { + Some(x) => { + let b = unfiltered[x]; + unfiltered.push(byte.wrapping_add(b)); + } + None => { + unfiltered.push(*byte); + } + }; + }, + 2 => { + if last_line.is_empty() { + unfiltered.extend_from_slice(data); + } else { + unfiltered.extend( + data.iter() + .zip(last_line.iter()) + .map(|(cur, last)| cur.wrapping_add(*last)), + ); + }; + } + 3 => for (i, byte) in data.iter().enumerate() { + if last_line.is_empty() { + match i.checked_sub(bpp) { + Some(x) => { + let b = unfiltered[x]; + unfiltered.push(byte.wrapping_add(b >> 1)); + } + None => { + unfiltered.push(*byte); + } + }; + } else { + match i.checked_sub(bpp) { + Some(x) => { + let b = unfiltered[x]; + unfiltered + .push( + byte.wrapping_add( + ((u16::from(b) + u16::from(last_line[i])) >> 1) as u8, + ), + ); + } + None => { + unfiltered.push(byte.wrapping_add(last_line[i] >> 1)); + } + }; + }; + }, + 4 => for (i, byte) in data.iter().enumerate() { + if last_line.is_empty() { match i.checked_sub(bpp) { Some(x) => { let b = unfiltered[x]; @@ -75,71 +128,20 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V unfiltered.push(*byte); } }; - } - } - 2 => { - if last_line.is_empty() { - unfiltered.extend_from_slice(data); } else { - unfiltered.extend(data.iter().zip(last_line.iter()).map(|(cur, last)| { - cur.wrapping_add(*last) - })); + match i.checked_sub(bpp) { + Some(x) => { + let b = unfiltered[x]; + unfiltered.push( + byte.wrapping_add(paeth_predictor(b, last_line[i], last_line[x])), + ); + } + None => { + unfiltered.push(byte.wrapping_add(last_line[i])); + } + }; }; - } - 3 => { - for (i, byte) in data.iter().enumerate() { - if last_line.is_empty() { - match i.checked_sub(bpp) { - Some(x) => { - let b = unfiltered[x]; - unfiltered.push(byte.wrapping_add(b >> 1)); - } - None => { - unfiltered.push(*byte); - } - }; - } else { - match i.checked_sub(bpp) { - Some(x) => { - let b = unfiltered[x]; - unfiltered.push(byte.wrapping_add( - ((b as u16 + last_line[i] as u16) >> 1) as u8, - )); - } - None => { - unfiltered.push(byte.wrapping_add(last_line[i] >> 1)); - } - }; - }; - } - } - 4 => { - for (i, byte) in data.iter().enumerate() { - if last_line.is_empty() { - match i.checked_sub(bpp) { - Some(x) => { - let b = unfiltered[x]; - unfiltered.push(byte.wrapping_add(b)); - } - None => { - unfiltered.push(*byte); - } - }; - } else { - match i.checked_sub(bpp) { - Some(x) => { - let b = unfiltered[x]; - unfiltered.push(byte.wrapping_add( - paeth_predictor(b, last_line[i], last_line[x]), - )); - } - None => { - unfiltered.push(byte.wrapping_add(last_line[i])); - } - }; - }; - } - } + }, _ => unreachable!(), } unfiltered @@ -147,10 +149,10 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V #[inline] fn paeth_predictor(a: u8, b: u8, c: u8) -> u8 { - let p = a as i32 + b as i32 - c as i32; - let pa = (p - a as i32).abs(); - let pb = (p - b as i32).abs(); - let pc = (p - c as i32).abs(); + let p = i32::from(a) + i32::from(b) - i32::from(c); + let pa = (p - i32::from(a)).abs(); + let pb = (p - i32::from(b)).abs(); + let pc = (p - i32::from(c)).abs(); if pa <= pb && pa <= pc { a } else if pb <= pc { diff --git a/src/interlace.rs b/src/interlace.rs index 99384af7..85b410b9 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -41,33 +41,27 @@ pub fn interlace_image(png: &mut PngData) { let bit_vec = BitVec::from_bytes(&line.data); for (i, bit) in bit_vec.iter().enumerate() { // Avoid moving padded 0's into new image - if i >= (png.ihdr_data.width * bits_per_pixel as u32) as usize { + if i >= (png.ihdr_data.width * u32::from(bits_per_pixel)) as usize { break; } // Copy pixels into interlaced passes let pix_modulo = (i / bits_per_pixel as usize) % 8; match index % 8 { - 0 => { - match pix_modulo { - 0 => passes[0].push(bit), - 4 => passes[1].push(bit), - 2 | 6 => passes[3].push(bit), - _ => passes[5].push(bit), - } - } - 4 => { - match pix_modulo { - 0 | 4 => passes[2].push(bit), - 2 | 6 => passes[3].push(bit), - _ => passes[5].push(bit), - } - } - 2 | 6 => { - match pix_modulo % 2 { - 0 => passes[4].push(bit), - _ => passes[5].push(bit), - } - } + 0 => match pix_modulo { + 0 => passes[0].push(bit), + 4 => passes[1].push(bit), + 2 | 6 => passes[3].push(bit), + _ => passes[5].push(bit), + }, + 4 => match pix_modulo { + 0 | 4 => passes[2].push(bit), + 2 | 6 => passes[3].push(bit), + _ => passes[5].push(bit), + }, + 2 | 6 => match pix_modulo % 2 { + 0 => passes[4].push(bit), + _ => passes[5].push(bit), + }, _ => { passes[6].push(bit); } @@ -99,8 +93,8 @@ 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 - pass_constants.x_shift as u32) as f32 / - pass_constants.x_step as f32) + let bits_in_line = ((png.ihdr_data.width - u32::from(pass_constants.x_shift)) as f32 / + f32::from(pass_constants.x_step)) .ceil() as usize * bits_per_pixel as usize; for (i, bit) in bit_vec.iter().enumerate() { // Avoid moving padded 0's into new image @@ -150,62 +144,48 @@ struct InterlacedConstants { fn interlaced_constants(pass: u8) -> InterlacedConstants { match pass { - 1 => { - InterlacedConstants { - x_shift: 0, - y_shift: 0, - x_step: 8, - y_step: 8, - } - } - 2 => { - InterlacedConstants { - x_shift: 4, - y_shift: 0, - x_step: 8, - y_step: 8, - } - } - 3 => { - InterlacedConstants { - x_shift: 0, - y_shift: 4, - x_step: 4, - y_step: 8, - } - } - 4 => { - InterlacedConstants { - x_shift: 2, - y_shift: 0, - x_step: 4, - y_step: 4, - } - } - 5 => { - InterlacedConstants { - x_shift: 0, - y_shift: 2, - x_step: 2, - y_step: 4, - } - } - 6 => { - InterlacedConstants { - x_shift: 1, - y_shift: 0, - x_step: 2, - y_step: 2, - } - } - 7 => { - InterlacedConstants { - x_shift: 0, - y_shift: 1, - x_step: 1, - y_step: 2, - } - } + 1 => InterlacedConstants { + x_shift: 0, + y_shift: 0, + x_step: 8, + y_step: 8, + }, + 2 => InterlacedConstants { + x_shift: 4, + y_shift: 0, + x_step: 8, + y_step: 8, + }, + 3 => InterlacedConstants { + x_shift: 0, + y_shift: 4, + x_step: 4, + y_step: 8, + }, + 4 => InterlacedConstants { + x_shift: 2, + y_shift: 0, + x_step: 4, + y_step: 4, + }, + 5 => InterlacedConstants { + x_shift: 0, + y_shift: 2, + x_step: 2, + y_step: 4, + }, + 6 => InterlacedConstants { + x_shift: 1, + y_shift: 0, + x_step: 2, + y_step: 2, + }, + 7 => InterlacedConstants { + x_shift: 0, + y_shift: 1, + x_step: 1, + y_step: 2, + }, _ => unreachable!(), } } diff --git a/src/lib.rs b/src/lib.rs index 8d58a3ad..feec4d60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ -#![cfg_attr(feature="dev", feature(plugin))] -#![cfg_attr(feature="dev", plugin(clippy))] +#![cfg_attr(feature = "dev", feature(plugin))] +#![cfg_attr(feature = "dev", plugin(clippy))] extern crate bit_vec; extern crate byteorder; @@ -14,13 +14,13 @@ extern crate zopfli; use deflate::Deflaters; pub use error::PngError; -use image::{GenericImage, Pixel, ImageFormat}; +use image::{GenericImage, ImageFormat, Pixel}; use headers::Headers; use png::PngData; use rayon::prelude::*; use std::collections::{HashMap, HashSet}; -use std::fs::{File, copy}; -use std::io::{BufWriter, Write, stdout}; +use std::fs::{copy, File}; +use std::io::{stdout, BufWriter, Write}; use std::path::{Path, PathBuf}; pub mod colors; @@ -360,38 +360,28 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> { let readonly = metadata.permissions().readonly(); out_meta.permissions().set_readonly(readonly); } - Err(_) => { - if opts.verbosity.is_some() { - eprintln!( - "Failed to set permissions on output file" - ); - } - } + Err(_) => if opts.verbosity.is_some() { + eprintln!("Failed to set permissions on output file"); + }, } } } - Err(_) => { - if opts.verbosity.is_some() { - eprintln!("Failed to read permissions on input file"); - } - } - } - } - Err(_) => { - if opts.verbosity.is_some() { - eprintln!("Failed to read permissions on input file"); + Err(_) => if opts.verbosity.is_some() { + eprintln!("Failed to read permissions on input file"); + }, } } + Err(_) => if opts.verbosity.is_some() { + eprintln!("Failed to read permissions on input file"); + }, }; } let mut buffer = BufWriter::new(out_file); match buffer.write_all(&optimized_output) { - Ok(_) => { - if opts.verbosity.is_some() { - eprintln!("Output: {}", opts.out_file.display()); - } - } + Ok(_) => if opts.verbosity.is_some() { + eprintln!("Output: {}", opts.out_file.display()); + }, Err(_) => { return Err(PngError::new(&format!( "Unable to write to file {}", @@ -543,42 +533,41 @@ fn optimize_png( let original_len = original_png.idat_data.len(); let added_interlacing = opts.interlace == Some(1) && original_png.ihdr_data.interlaced == 0; - let best: Option = - results - .into_par_iter() - .with_max_len(1) - .filter_map(|trial| { - let filtered = &filters[&trial.filter]; - let new_idat = if opts.deflate == Deflaters::Zlib { - deflate::deflate( - filtered, - trial.compression, - trial.memory, - trial.strategy, - opts.window, - ) - } else { - deflate::zopfli_deflate(filtered) - }.unwrap(); + let best: Option = results + .into_par_iter() + .with_max_len(1) + .filter_map(|trial| { + let filtered = &filters[&trial.filter]; + let new_idat = if opts.deflate == Deflaters::Zlib { + deflate::deflate( + filtered, + trial.compression, + trial.memory, + trial.strategy, + opts.window, + ) + } else { + deflate::zopfli_deflate(filtered) + }.unwrap(); - if opts.verbosity == Some(1) { - eprintln!( - " zc = {} zm = {} zs = {} f = {} {} bytes", - trial.compression, - trial.memory, - trial.strategy, - trial.filter, - new_idat.len() - ); - } + if opts.verbosity == Some(1) { + eprintln!( + " zc = {} zm = {} zs = {} f = {} {} bytes", + trial.compression, + trial.memory, + trial.strategy, + trial.filter, + new_idat.len() + ); + } - if new_idat.len() < original_len || added_interlacing || opts.force { - Some((trial, new_idat)) - } else { - None - } - }) - .reduce_with(|i, j| if i.1.len() <= j.1.len() { i } else { j }); + if new_idat.len() < original_len || added_interlacing || opts.force { + Some((trial, new_idat)) + } else { + None + } + }) + .reduce_with(|i, j| if i.1.len() <= j.1.len() { i } else { j }); if let Some(better) = best { png.idat_data = better.1; @@ -732,11 +721,9 @@ fn perform_strip(png: &mut png::PngData, opts: &Options) { match opts.strip { // Strip headers Headers::None => (), - Headers::Some(ref hdrs) => { - for hdr in hdrs { - png.aux_headers.remove(hdr); - } - } + Headers::Some(ref hdrs) => for hdr in hdrs { + png.aux_headers.remove(hdr); + }, Headers::Safe => { const PRESERVED_HEADERS: [&'static str; 9] = [ "cHRM", diff --git a/src/main.rs b/src/main.rs index ba19ac96..fa9b81c5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,14 @@ -#![cfg_attr(feature="clippy", feature(plugin))] -#![cfg_attr(feature="clippy", plugin(clippy))] -#![cfg_attr(feature="clippy", warn(enum_glob_use))] -#![cfg_attr(feature="clippy", warn(if_not_else))] -#![cfg_attr(feature="clippy", warn(string_add))] -#![cfg_attr(feature="clippy", warn(string_add_assign))] +#![cfg_attr(feature = "clippy", feature(plugin))] +#![cfg_attr(feature = "clippy", plugin(clippy))] +#![cfg_attr(feature = "clippy", warn(enum_glob_use))] +#![cfg_attr(feature = "clippy", warn(if_not_else))] +#![cfg_attr(feature = "clippy", warn(string_add))] +#![cfg_attr(feature = "clippy", warn(string_add_assign))] #![warn(trivial_casts, trivial_numeric_casts, unused_import_braces)] #![deny(missing_debug_implementations, missing_copy_implementations)] -extern crate oxipng; extern crate clap; +extern crate oxipng; extern crate regex; use clap::{App, Arg, ArgMatches}; @@ -414,8 +414,7 @@ fn parse_opts_into_struct(matches: &ArgMatches) -> Result { if hdrs.contains(&"safe".to_owned()) || hdrs.contains(&"all".to_owned()) { if hdrs.len() > 1 { return Err( - "'safe' or 'all' presets for --strip should be used by themselves" - .to_owned(), + "'safe' or 'all' presets for --strip should be used by themselves".to_owned(), ); } if hdrs[0] == "safe" { @@ -483,11 +482,9 @@ fn parse_numeric_range_opts( items.insert(first); items.insert(second); } - "-" => { - for i in first..second + 1 { - items.insert(i); - } - } + "-" => for i in first..second + 1 { + items.insert(i); + }, _ => unreachable!(), }; diff --git a/src/png.rs b/src/png.rs index c7cf4f5d..0c0f19c4 100644 --- a/src/png.rs +++ b/src/png.rs @@ -1,12 +1,12 @@ use bit_vec::BitVec; use byteorder::{BigEndian, WriteBytesExt}; -use colors::{BitDepth, ColorType, AlphaOptim}; +use colors::{AlphaOptim, BitDepth, ColorType}; use crc::crc32; use deflate; use error::PngError; use filters::*; use headers::*; -use interlace::{interlace_image, deinterlace_image}; +use interlace::{deinterlace_image, interlace_image}; use itertools::Itertools; use reduction::*; use std::collections::{HashMap, HashSet}; @@ -56,8 +56,8 @@ impl<'a> Iterator for ScanLines<'a> { pass.1 = 0; } } - let bits_per_pixel = self.png.ihdr_data.bit_depth.as_u8() as u32 * - self.png.channels_per_pixel() as u32; + let bits_per_pixel = u32::from(self.png.ihdr_data.bit_depth.as_u8()) * + u32::from(self.png.channels_per_pixel()); let y_steps; let pixels_factor; match self.pass { @@ -95,21 +95,15 @@ impl<'a> Iterator for ScanLines<'a> { 1 | 3 | 5 => { pixels_per_line += 1; } - 2 => { - if gap >= 5 { - pixels_per_line += 1; - } - } - 4 => { - if gap >= 3 { - pixels_per_line += 1; - } - } - 6 => { - if gap >= 2 { - pixels_per_line += 1; - } - } + 2 => if gap >= 5 { + pixels_per_line += 1; + }, + 4 => if gap >= 3 { + pixels_per_line += 1; + }, + 6 => if gap >= 2 { + pixels_per_line += 1; + }, _ => (), }; } @@ -324,8 +318,7 @@ impl PngData { // Ancillary headers for (key, header) in self.aux_headers.iter().filter(|&(key, _)| { !(*key == "bKGD" || *key == "hIST" || *key == "tRNS") - }) - { + }) { write_png_block(key.as_bytes(), header, &mut output); } // Palette @@ -340,10 +333,9 @@ impl PngData { write_png_block(b"tRNS", transparency_pixel, &mut output); } // Special ancillary headers that need to come after PLTE but before IDAT - for (key, header) in self.aux_headers.iter().filter(|&(key, _)| { - *key == "bKGD" || *key == "hIST" || *key == "tRNS" - }) - { + for (key, header) in self.aux_headers.iter().filter( + |&(key, _)| *key == "bKGD" || *key == "hIST" || *key == "tRNS", + ) { write_png_block(key.as_bytes(), header, &mut output); } // IDAT data @@ -368,8 +360,8 @@ impl PngData { /// Reverse all filters applied on the image, returning an unfiltered IDAT bytestream pub fn unfilter_image(&self) -> Vec { let mut unfiltered = Vec::with_capacity(self.raw_data.len()); - let bpp = (((self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel()) as f32) / - 8f32) + let bpp = ((f32::from(self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel())) / + 8f32) .ceil() as usize; let mut last_line: Vec = Vec::new(); for line in self.scan_lines() { @@ -390,8 +382,8 @@ impl PngData { /// 5: All (heuristically pick the best filter for each line) pub fn filter_image(&self, filter: u8) -> Vec { let mut filtered = Vec::with_capacity(self.raw_data.len()); - let bpp = (((self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel()) as f32) / - 8f32) + let bpp = ((f32::from(self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel())) / + 8f32) .ceil() as usize; let mut last_line: Vec = Vec::new(); let mut last_pass: Option = None; @@ -400,9 +392,8 @@ impl PngData { 0 | 1 | 2 | 3 | 4 => { if last_pass == line.pass || filter <= 1 { filtered.push(filter); - filtered.extend_from_slice( - &filter_line(filter, bpp, &line.data, &last_line), - ); + filtered + .extend_from_slice(&filter_line(filter, bpp, &line.data, &last_line)); } else { // Avoid vertical filtering on first line of each interlacing pass filtered.push(0); @@ -423,7 +414,7 @@ impl PngData { .min_by_key(|x| { x.1.iter().fold(0u64, |acc, &x| { let signed = x as i8; - acc + (signed as i16).abs() as u64 + acc + i16::from(signed).abs() as u64 }) }) .unwrap(); @@ -452,8 +443,8 @@ impl PngData { // Reduce from 16 to 8 bits per channel per pixel let mut reduced = Vec::with_capacity( - (self.ihdr_data.width * self.ihdr_data.height * self.channels_per_pixel() as u32 + - self.ihdr_data.height) as usize, + (self.ihdr_data.width * self.ihdr_data.height * u32::from(self.channels_per_pixel()) + + self.ihdr_data.height) as usize, ); let mut high_byte = 0; @@ -543,11 +534,9 @@ impl PngData { let mut seen = HashSet::with_capacity(indexed_palette.len()); for line in self.scan_lines() { match self.ihdr_data.bit_depth { - BitDepth::Eight => { - for byte in &line.data { - seen.insert(*byte); - } - } + BitDepth::Eight => for byte in &line.data { + seen.insert(*byte); + }, BitDepth::Four => { let bitvec = BitVec::from_bytes(&line.data); let mut current = 0u8; @@ -628,63 +617,57 @@ impl PngData { for line in self.scan_lines() { new_data.push(line.filter); match self.ihdr_data.bit_depth { - BitDepth::Eight => { - for byte in &line.data { - if let Some(new_idx) = index_map.get(byte) { - new_data.push(*new_idx); - } else { - new_data.push(*byte); - } + BitDepth::Eight => for byte in &line.data { + if let Some(new_idx) = index_map.get(byte) { + new_data.push(*new_idx); + } else { + new_data.push(*byte); } - } - BitDepth::Four => { - for byte in &line.data { - let upper = *byte & 0b11110000; - let lower = *byte & 0b00001111; - let mut new_byte = 0u8; - new_byte |= if let Some(new_idx) = index_map.get(&upper) { - *new_idx << 4 - } else { - upper - }; - new_byte |= if let Some(new_idx) = index_map.get(&lower) { - *new_idx - } else { - lower - }; - new_data.push(new_byte); - } - } - BitDepth::Two => { - for byte in &line.data { - let one = *byte & 0b11000000; - let two = *byte & 0b00110000; - let three = *byte & 0b00001100; - let four = *byte & 0b00000011; - let mut new_byte = 0u8; - new_byte |= if let Some(new_idx) = index_map.get(&one) { - *new_idx << 6 - } else { - one << 6 - }; - new_byte |= if let Some(new_idx) = index_map.get(&two) { - *new_idx << 4 - } else { - two << 4 - }; - new_byte |= if let Some(new_idx) = index_map.get(&three) { - *new_idx << 2 - } else { - three << 2 - }; - new_byte |= if let Some(new_idx) = index_map.get(&four) { - *new_idx - } else { - four - }; - new_data.push(new_byte); - } - } + }, + BitDepth::Four => for byte in &line.data { + let upper = *byte & 0b1111_0000; + let lower = *byte & 0b0000_1111; + let mut new_byte = 0u8; + new_byte |= if let Some(new_idx) = index_map.get(&upper) { + *new_idx << 4 + } else { + upper + }; + new_byte |= if let Some(new_idx) = index_map.get(&lower) { + *new_idx + } else { + lower + }; + new_data.push(new_byte); + }, + BitDepth::Two => for byte in &line.data { + let one = *byte & 0b1100_0000; + let two = *byte & 0b0011_0000; + let three = *byte & 0b0000_1100; + let four = *byte & 0b0000_0011; + let mut new_byte = 0u8; + new_byte |= if let Some(new_idx) = index_map.get(&one) { + *new_idx << 6 + } else { + one << 6 + }; + new_byte |= if let Some(new_idx) = index_map.get(&two) { + *new_idx << 4 + } else { + two << 4 + }; + new_byte |= if let Some(new_idx) = index_map.get(&three) { + *new_idx << 2 + } else { + three << 2 + }; + new_byte |= if let Some(new_idx) = index_map.get(&four) { + *new_idx + } else { + four + }; + new_data.push(new_byte); + }, _ => unreachable!(), } } @@ -774,8 +757,7 @@ impl PngData { pub fn reduce_alpha_channel(&mut self, optim: AlphaOptim) -> bool { let (bpc, bpp) = match self.ihdr_data.color_type { - ColorType::RGBA | - ColorType::GrayscaleAlpha => { + ColorType::RGBA | ColorType::GrayscaleAlpha => { let cpp = self.channels_per_pixel(); let bpc = self.ihdr_data.bit_depth.as_u8() / 8; (bpc as usize, (bpc * cpp) as usize) diff --git a/src/reduction.rs b/src/reduction.rs index fdd59c3f..38f7acb1 100644 --- a/src/reduction.rs +++ b/src/reduction.rs @@ -135,12 +135,11 @@ pub fn reduce_rgba_to_palette(png: &mut PngData) -> bool { } let mut color_palette = Vec::with_capacity( - palette.len() * 3 + - if png.aux_headers.contains_key(&"bKGD".to_string()) { - 6 - } else { - 0 - }, + palette.len() * 3 + if png.aux_headers.contains_key(&"bKGD".to_string()) { + 6 + } else { + 0 + }, ); let mut trans_palette = Vec::with_capacity(palette.len()); for color in &palette { @@ -167,9 +166,9 @@ pub fn reduce_rgba_to_palette(png: &mut PngData) -> bool { .step(2) .cloned() .collect::>(); - if let Some(entry) = color_palette.chunks(3).position( - |x| x == header_pixels.as_slice(), - ) + if let Some(entry) = color_palette + .chunks(3) + .position(|x| x == header_pixels.as_slice()) { *bkgd_header = vec![entry as u8]; } else if color_palette.len() / 3 == 256 { @@ -246,9 +245,9 @@ pub fn reduce_rgb_to_palette(png: &mut PngData) -> bool { .step(2) .cloned() .collect::>(); - if let Some(entry) = color_palette.chunks(3).position( - |x| x == header_pixels.as_slice(), - ) + if let Some(entry) = color_palette + .chunks(3) + .position(|x| x == header_pixels.as_slice()) { *bkgd_header = vec![entry as u8]; } else if color_palette.len() == 255 { diff --git a/tests/reduction.rs b/tests/reduction.rs index 1cab344b..db565376 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -1,6 +1,6 @@ extern crate oxipng; -use oxipng::colors::{BitDepth, ColorType, AlphaOptim}; +use oxipng::colors::{AlphaOptim, BitDepth, ColorType}; use oxipng::png; use std::collections::HashSet; use std::error::Error;