From cc290c0bdb263d843824f3498542c4de1be40c59 Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Tue, 18 Jun 2019 18:04:26 +0100 Subject: [PATCH 1/7] Fixes for grey scale reduction (#171) --- src/reduction/bit_depth.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/src/reduction/bit_depth.rs b/src/reduction/bit_depth.rs index 262357b0..6f04ec86 100644 --- a/src/reduction/bit_depth.rs +++ b/src/reduction/bit_depth.rs @@ -4,24 +4,28 @@ use crate::png::PngImage; use bit_vec::BitVec; const ONE_BIT_PERMUTATIONS: [u8; 2] = [0b0000_0000, 0b1111_1111]; -const TWO_BIT_PERMUTATIONS: [u8; 5] = [ +const TWO_BIT_PERMUTATIONS: [u8; 4] = [ 0b0000_0000, - 0b0000_1111, - 0b0011_1100, - 0b1111_0000, + 0b0101_0101, + 0b1010_1010, 0b1111_1111, ]; -const FOUR_BIT_PERMUTATIONS: [u8; 11] = [ +const FOUR_BIT_PERMUTATIONS: [u8; 16] = [ 0b0000_0000, - 0b0000_0011, - 0b0000_1100, - 0b0011_0000, - 0b1100_0000, - 0b0000_1111, - 0b0011_1100, - 0b1111_0000, - 0b0011_1111, - 0b1111_1100, + 0b0001_0001, + 0b0010_0010, + 0b0011_0011, + 0b0100_0100, + 0b0101_0101, + 0b0110_0110, + 0b0111_0111, + 0b1000_1000, + 0b1001_1001, + 0b1010_1010, + 0b1011_1011, + 0b1100_1100, + 0b1101_1101, + 0b1110_1110, 0b1111_1111, ]; From 5dcfe44ccd6e52a49db7104cfac7f73c1960070c Mon Sep 17 00:00:00 2001 From: Felix Hanau Date: Tue, 18 Jun 2019 18:06:37 +0100 Subject: [PATCH 2/7] Fix info message and typos (#172) --- README.md | 2 +- README.template.md | 2 +- src/lib.rs | 4 ++-- tests/flags.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d4131d89..79937789 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ to give any extra compression gains and is not recommended. PNG interlacing on any images that are processed. `-i 0` will remove interlacing from all processed images. Not specifying either will keep the same interlacing state as the input image. Note: Interlacing can add 25-50% to the size of an optimized image. Only use -it if you believe the benefits outweight the costs for your use case. +it if you believe the benefits outweigh the costs for your use case. * Strip: Used to remove metadata info from processed images. Used via `--strip [safe,all]`. Can save a few kilobytes if you don't need the metadata. "Safe" removes only metadata that will never affect rendering of the image. "All" removes all metadata that is not critical diff --git a/README.template.md b/README.template.md index da8e0934..91343543 100644 --- a/README.template.md +++ b/README.template.md @@ -49,7 +49,7 @@ to give any extra compression gains and is not recommended. PNG interlacing on any images that are processed. `-i 0` will remove interlacing from all processed images. Not specifying either will keep the same interlacing state as the input image. Note: Interlacing can add 25-50% to the size of an optimized image. Only use -it if you believe the benefits outweight the costs for your use case. +it if you believe the benefits outweigh the costs for your use case. * Strip: Used to remove metadata info from processed images. Used via `--strip [safe,all]`. Can save a few kilobytes if you don't need the metadata. "Safe" removes only metadata that will never affect rendering of the image. "All" removes all metadata that is not critical diff --git a/src/lib.rs b/src/lib.rs index 49a0b06f..a9d456ba 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -477,7 +477,7 @@ fn optimize_png( eprintln!( " {} bits/pixel, {} colors in palette", png.raw.ihdr.bit_depth, - palette.len() / 3 + palette.len() ); } else { eprintln!( @@ -824,7 +824,7 @@ fn report_reduction(png: &PngImage) { eprintln!( "Reducing image to {} bits/pixel, {} colors in palette", png.ihdr.bit_depth, - palette.len() / 3 + palette.len() ); } else { eprintln!( diff --git a/tests/flags.rs b/tests/flags.rs index 9f308854..1e9a43f7 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -332,7 +332,7 @@ fn interlacing_1_to_0_small_files() { assert_eq!(png.raw.ihdr.interlaced, 0); assert_eq!(png.raw.ihdr.color_type, ColorType::Indexed); - // the depth can't be asserted reliably, because on such small file different zlib implementaitons pick diferent depth as the best + // the depth can't be asserted reliably, because on such small file different zlib implementations pick different depth as the best remove_file(output).ok(); } From 5b1121c9dd3ab8969390a9abd6ce9263d0042745 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Tue, 18 Jun 2019 13:28:59 -0400 Subject: [PATCH 3/7] Make order of chunks deterministic by sorting chunks Closes #174 --- src/lib.rs | 23 +++++++++++++++-------- src/png/mod.rs | 6 +++--- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a9d456ba..226bdf86 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ use crate::reduction::*; use crc::crc32; use image::{DynamicImage, GenericImageView, ImageFormat, Pixel}; use rayon::prelude::*; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt; use std::fs::{copy, File}; use std::io::{stdin, stdout, BufWriter, Read, Write}; @@ -843,11 +843,15 @@ fn perform_strip(png: &mut PngData, opts: &Options) { // Strip headers Headers::None => (), Headers::Keep(ref hdrs) => { - raw.aux_headers.retain(|chunk, _| { - std::str::from_utf8(chunk) + let keys: Vec<[u8; 4]> = raw.aux_headers.keys().cloned().collect(); + for hdr in &keys { + let preserve = std::str::from_utf8(hdr) .ok() - .map_or(false, |name| hdrs.contains(name)) - }); + .map_or(false, |name| hdrs.contains(name)); + if !preserve { + raw.aux_headers.remove(hdr); + } + } } Headers::Strip(ref hdrs) => { for hdr in hdrs { @@ -859,11 +863,14 @@ fn perform_strip(png: &mut PngData, opts: &Options) { *b"cHRM", *b"gAMA", *b"iCCP", *b"sBIT", *b"sRGB", *b"bKGD", *b"hIST", *b"pHYs", *b"sPLT", ]; - raw.aux_headers - .retain(|hdr, _| PRESERVED_HEADERS.contains(hdr)); + for hdr in &PRESERVED_HEADERS { + if !PRESERVED_HEADERS.contains(hdr) { + raw.aux_headers.remove(hdr); + } + } } Headers::All => { - raw.aux_headers = HashMap::new(); + raw.aux_headers = BTreeMap::new(); } } diff --git a/src/png/mod.rs b/src/png/mod.rs index 6d46670e..2fd5184f 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -8,7 +8,7 @@ use byteorder::{BigEndian, WriteBytesExt}; use crc::crc32; use rgb::ComponentSlice; use rgb::RGBA8; -use std::collections::HashMap; +use std::collections::BTreeMap; use std::fs::File; use std::io::{Read, Seek, SeekFrom}; use std::iter::Iterator; @@ -38,7 +38,7 @@ pub struct PngImage { /// The pixel value that should be rendered as transparent pub transparency_pixel: Option>, /// All non-critical headers from the PNG are stored here - pub aux_headers: HashMap<[u8; 4], Vec>, + pub aux_headers: BTreeMap<[u8; 4], Vec>, } /// Contains all data relevant to a PNG image @@ -97,7 +97,7 @@ impl PngData { } byte_offset += 8; // Read the data headers - let mut aux_headers: HashMap<[u8; 4], Vec> = HashMap::new(); + let mut aux_headers: BTreeMap<[u8; 4], Vec> = BTreeMap::new(); let mut idat_headers: Vec = Vec::new(); while let Some(header) = parse_next_header(byte_data, &mut byte_offset, fix_errors)? { match &header.name { From 3809421de78c22be68babd1194d377465129a97f Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Wed, 19 Jun 2019 15:21:41 -0400 Subject: [PATCH 4/7] Use image 0.21.2 with bugfixes from crates.io --- Cargo.lock | 10 ++++++---- Cargo.toml | 6 +----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 56158ad0..002f8862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "adler32" version = "1.0.3" @@ -149,8 +151,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "image" -version = "0.21.0" -source = "git+https://github.com/PistonDevelopers/image?rev=41dfbae#41dfbaecfa0e702eaef61e4dba156e9be5b2f70d" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -257,7 +259,7 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "cloudflare-zlib 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "image 0.21.0 (git+https://github.com/PistonDevelopers/image?rev=41dfbae)", + "image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -419,7 +421,7 @@ dependencies = [ "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c67353c641dc847124ea1902d69bd753dee9bb3beff9aa3662ecf86c971d1fac" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum image 0.21.0 (git+https://github.com/PistonDevelopers/image?rev=41dfbae)" = "" +"checksum image 0.21.2 (registry+https://github.com/rust-lang/crates.io-index)" = "99198e595d012efccf12abf4abc08da2d97be0b0355a2b08d101347527476ba4" "checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" diff --git a/Cargo.toml b/Cargo.toml index 0095665e..5c24e963 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,11 +55,7 @@ cloudflare-zlib = "^0.2.2" [dependencies.image] default-features = false features = ["png_codec"] -#FIXME: Use upstream version when 0.22 is released -#Contains bugfix for issues 167 and 168 -#version = "^0.21.0" -git = "https://github.com/PistonDevelopers/image" -rev = "41dfbae" +version = "^0.21.2" [features] binary = [ From 458e9f64a7c70da6ebd0b53bf9be6cd9d49ae1d7 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Wed, 19 Jun 2019 15:27:43 -0400 Subject: [PATCH 5/7] Fix --strip safe which was broken in 5b1121c9d --- src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 226bdf86..70ff06ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -863,7 +863,8 @@ fn perform_strip(png: &mut PngData, opts: &Options) { *b"cHRM", *b"gAMA", *b"iCCP", *b"sBIT", *b"sRGB", *b"bKGD", *b"hIST", *b"pHYs", *b"sPLT", ]; - for hdr in &PRESERVED_HEADERS { + let keys: Vec<[u8; 4]> = raw.aux_headers.keys().cloned().collect(); + for hdr in &keys { if !PRESERVED_HEADERS.contains(hdr) { raw.aux_headers.remove(hdr); } From 9d8ce5e4eea4d3ae18b5d514560d2b4d598e15d5 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Thu, 20 Jun 2019 13:38:59 -0400 Subject: [PATCH 6/7] Disable large image test for 32-bit systems Closes #176 --- tests/regression.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/regression.rs b/tests/regression.rs index a8dbe045..ef7ee0bf 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -600,6 +600,7 @@ fn issue_159() { } #[test] +#[cfg(target_pointer_width = "64")] fn issue_167() { test_it_converts( "tests/files/issue-167.png", From c60bd82da7d9bb4f1c4ae07b713841f703fefe8b Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Thu, 20 Jun 2019 14:07:47 -0400 Subject: [PATCH 7/7] Add test case for #171 --- tests/files/issue-171.png | Bin 0 -> 220 bytes tests/regression.rs | 12 ++++++++++++ 2 files changed, 12 insertions(+) create mode 100644 tests/files/issue-171.png diff --git a/tests/files/issue-171.png b/tests/files/issue-171.png new file mode 100644 index 0000000000000000000000000000000000000000..bf83f52be504d4ff57a56396f1b1d42496a2f45a GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^EFjDQBp7;T9b5$Bq&xaLGB9lH=l+w(3gj~-dAqwX z{BQ3+vmeM~FY)wsWq-^jB50yBLvz7)ppby4i(?4K^<o#Nn literal 0 HcmV?d00001 diff --git a/tests/regression.rs b/tests/regression.rs index ef7ee0bf..1b20edee 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -611,3 +611,15 @@ fn issue_167() { BitDepth::Eight, ); } + +#[test] +fn issue_171() { + test_it_converts( + "tests/files/issue-171.png", + None, + ColorType::Grayscale, + BitDepth::Eight, + ColorType::Grayscale, + BitDepth::Eight, + ); +}