From 17a8c79e216a5348da6c9225c8ea5b4297350ab2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 28 Dec 2020 10:20:46 +0000 Subject: [PATCH 01/50] Bump itertools from 0.9.0 to 0.10.0 Bumps [itertools](https://github.com/bluss/rust-itertools) from 0.9.0 to 0.10.0. - [Release notes](https://github.com/bluss/rust-itertools/releases) - [Changelog](https://github.com/rust-itertools/itertools/blob/master/CHANGELOG.md) - [Commits](https://github.com/bluss/rust-itertools/compare/v0.9.0...v0.10.0) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78507913..22ac579a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -273,9 +273,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" +checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" dependencies = [ "either", ] diff --git a/Cargo.toml b/Cargo.toml index dac29f1a..15a57211 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ required-features = ["binary"] bit-vec = "^0.6.3" byteorder = "^1.0.0" crc = "^1.2.0" -itertools = "^0.9.0" +itertools = "^0.10.0" zopfli = { version = "^0.4.0", optional = true } miniz_oxide = "0.4" rgb = "0.8.25" From 1ebe7b01bcaf49cc83b67fa6ea756388aea7f276 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Mon, 4 Jan 2021 16:00:31 -0500 Subject: [PATCH 02/50] Temporarily disable i686 binaries so that amd64 binaries at least will get published --- .github/workflows/deploy.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ec3680a1..01ae14f8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -11,7 +11,10 @@ jobs: strategy: matrix: - conf: [x86_64, i686] + conf: [x86_64] +# Temporarily disable i686 binaries, they are failing on linking libdeflate +# and I don't have a Windows machine set up to experiment with fixing it. +# conf: [x86_64, i686] runs-on: windows-latest From 9b5cd9a1a478511f5d098845634eccc30586e17c Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Mon, 4 Jan 2021 16:12:46 -0500 Subject: [PATCH 03/50] Fix a new clippy lint --- src/reduction/bit_depth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reduction/bit_depth.rs b/src/reduction/bit_depth.rs index 24cb1e3d..49fee066 100644 --- a/src/reduction/bit_depth.rs +++ b/src/reduction/bit_depth.rs @@ -74,7 +74,7 @@ pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option #[must_use] pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option { - assert!(minimum_bits >= 1 && minimum_bits < 8); + assert!((1..8).contains(&minimum_bits)); let mut reduced = BitVec::with_capacity(png.data.len() * 8); let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize; if minimum_bits >= bit_depth { From dea23211ae6259007e068c59ab16929798d00d96 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Mon, 4 Jan 2021 16:12:57 -0500 Subject: [PATCH 04/50] Version 4.0.3 --- CHANGELOG.md | 6 ++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66c8999d..813a9bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +### Version 4.0.3 +- Bump itertools to 0.10.x +- Temporarily disable i686 releases, which were failing due to an odd linker issue, + so that at least amd64 builds will publish successfully + - This only relates to the releases published on Github. You can still manually compile oxipng for any platform. + ### Version 4.0.2 - Includes another update to libdeflater that improves support for targets without a C stdlib, like wasm32. diff --git a/Cargo.lock b/Cargo.lock index 22ac579a..62feb6e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -400,7 +400,7 @@ dependencies = [ [[package]] name = "oxipng" -version = "4.0.2" +version = "4.0.3" dependencies = [ "bit-vec", "byteorder", diff --git a/Cargo.toml b/Cargo.toml index 15a57211..bf8ea479 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ license = "MIT" name = "oxipng" repository = "https://github.com/shssoichiro/oxipng" build = "build.rs" -version = "4.0.2" +version = "4.0.3" [badges] travis-ci = { repository = "shssoichiro/oxipng", branch = "master" } From b45ab40b21af5d3a626df4948e03aa2abdcd7bb7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 Jan 2021 12:30:32 +0000 Subject: [PATCH 05/50] Bump semver-parser from 0.10.1 to 0.10.2 Bumps [semver-parser](https://github.com/steveklabnik/semver-parser) from 0.10.1 to 0.10.2. - [Release notes](https://github.com/steveklabnik/semver-parser/releases) - [Commits](https://github.com/steveklabnik/semver-parser/commits/v0.10.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62feb6e3..201ff207 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "semver-parser" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ef146c2ad5e5f4b037cd6ce2ebb775401729b19a82040c1beac9d36c7d1428" +checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" dependencies = [ "pest", ] From 7ea5c4d38c516905690fb09c4b3ec0bf305d8c30 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 6 Jan 2021 12:42:15 +0000 Subject: [PATCH 06/50] Bump const_fn from 0.4.4 to 0.4.5 Bumps [const_fn](https://github.com/taiki-e/const_fn) from 0.4.4 to 0.4.5. - [Release notes](https://github.com/taiki-e/const_fn/releases) - [Changelog](https://github.com/taiki-e/const_fn/blob/master/CHANGELOG.md) - [Commits](https://github.com/taiki-e/const_fn/compare/v0.4.4...v0.4.5) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 201ff207..115f8e2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,9 +140,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "const_fn" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" +checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" [[package]] name = "crc" From 12f412d9159d9a8532ad1f0fc8ddd9d1ae9b0a7c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 8 Jan 2021 10:58:16 +0000 Subject: [PATCH 07/50] Bump libc from 0.2.81 to 0.2.82 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.81 to 0.2.82. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.81...0.2.82) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 115f8e2a..a364ae27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -288,9 +288,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" [[package]] name = "libdeflate-sys" From 0b4221d7f3179f88eecb6cffe13b908953b7b738 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 11:17:09 +0000 Subject: [PATCH 08/50] Bump stderrlog from 0.5.0 to 0.5.1 Bumps [stderrlog](https://github.com/cardoe/stderrlog-rs) from 0.5.0 to 0.5.1. - [Release notes](https://github.com/cardoe/stderrlog-rs/releases) - [Changelog](https://github.com/cardoe/stderrlog-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/cardoe/stderrlog-rs/compare/v0.5.0...v0.5.1) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a364ae27..1a7e0bb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -512,9 +512,9 @@ dependencies = [ [[package]] name = "stderrlog" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b02f316286ae558d83acc93dd81eaba096e746987a7961d4a9ae026842bae67f" +checksum = "45a53e2eff3e94a019afa6265e8ee04cb05b9d33fe9f5078b14e4e391d155a38" dependencies = [ "atty", "chrono", diff --git a/Cargo.toml b/Cargo.toml index bf8ea479..48c39923 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ rgb = "0.8.25" indexmap = "1.6.1" libdeflater = { version = "0.7.1", optional = true } log = "0.4.11" -stderrlog = { version = "0.5.0", optional = true } +stderrlog = { version = "0.5.1", optional = true } crossbeam-channel = "0.5.0" [dependencies.rayon] From 9d55331980f0bbda0b770d520305f4b014b3f3bc Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 11:27:32 +0000 Subject: [PATCH 09/50] Bump byteorder from 1.3.4 to 1.4.2 Bumps [byteorder](https://github.com/BurntSushi/byteorder) from 1.3.4 to 1.4.2. - [Release notes](https://github.com/BurntSushi/byteorder/releases) - [Changelog](https://github.com/BurntSushi/byteorder/blob/master/CHANGELOG.md) - [Commits](https://github.com/BurntSushi/byteorder/compare/1.3.4...1.4.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a7e0bb2..a3481759 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,9 +64,9 @@ checksum = "41aa2ec95ca3b5c54cf73c91acf06d24f4495d5f1b1c12506ae3483d646177ac" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "cc" diff --git a/Cargo.toml b/Cargo.toml index 48c39923..86f98d25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,7 +30,7 @@ required-features = ["binary"] [dependencies] bit-vec = "^0.6.3" -byteorder = "^1.0.0" +byteorder = "^1.4.2" crc = "^1.2.0" itertools = "^0.10.0" zopfli = { version = "^0.4.0", optional = true } From f71ed29e96fd40e802a708ddd2b8763098b432b1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 11 Jan 2021 11:43:27 +0000 Subject: [PATCH 10/50] Bump log from 0.4.11 to 0.4.13 Bumps [log](https://github.com/rust-lang/log) from 0.4.11 to 0.4.13. - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.11...0.4.13) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3481759..9a97bbce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -312,9 +312,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" dependencies = [ "cfg-if 0.1.10", ] diff --git a/Cargo.toml b/Cargo.toml index 86f98d25..022b2318 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ miniz_oxide = "0.4" rgb = "0.8.25" indexmap = "1.6.1" libdeflater = { version = "0.7.1", optional = true } -log = "0.4.11" +log = "0.4.13" stderrlog = { version = "0.5.1", optional = true } crossbeam-channel = "0.5.0" From 228c43890fe1e11c93f530a0fb435d99f41dfe6c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 12 Jan 2021 10:53:30 +0000 Subject: [PATCH 11/50] Bump rustc_version from 0.3.0 to 0.3.2 Bumps [rustc_version](https://github.com/Kimundi/rustc-version-rs) from 0.3.0 to 0.3.2. - [Release notes](https://github.com/Kimundi/rustc-version-rs/releases) - [Commits](https://github.com/Kimundi/rustc-version-rs/compare/v0.3.0...v0.3.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9a97bbce..744d1167 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,9 +479,9 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c94201b44764d6d1f7e37c15a8289ed55e546c1762c7f1d57f616966e0c181" +checksum = "397d411cfc34097bdb176984180f7d9980eb161aaf1368ceea96c9834d8f8b85" dependencies = [ "semver", ] From 618da006a5b938f2d8447719cf27cfde625caef7 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 14 Jan 2021 10:52:57 +0000 Subject: [PATCH 12/50] Bump bytemuck from 1.4.1 to 1.5.0 Bumps [bytemuck](https://github.com/Lokathor/bytemuck) from 1.4.1 to 1.5.0. - [Release notes](https://github.com/Lokathor/bytemuck/releases) - [Changelog](https://github.com/Lokathor/bytemuck/blob/main/changelog.md) - [Commits](https://github.com/Lokathor/bytemuck/compare/v1.4.1...v1.5.0) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 744d1167..969bc7ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" [[package]] name = "bytemuck" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41aa2ec95ca3b5c54cf73c91acf06d24f4495d5f1b1c12506ae3483d646177ac" +checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0" [[package]] name = "byteorder" From b2bb4e1888fcb5f8717561dddd56bb0374aaf6c2 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 Jan 2021 11:05:15 +0000 Subject: [PATCH 13/50] Bump rustc_version from 0.3.2 to 0.3.3 Bumps [rustc_version](https://github.com/Kimundi/rustc-version-rs) from 0.3.2 to 0.3.3. - [Release notes](https://github.com/Kimundi/rustc-version-rs/releases) - [Commits](https://github.com/Kimundi/rustc-version-rs/compare/v0.3.2...v0.3.3) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 969bc7ba..176f0185 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,9 +479,9 @@ dependencies = [ [[package]] name = "rustc_version" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397d411cfc34097bdb176984180f7d9980eb161aaf1368ceea96c9834d8f8b85" +checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" dependencies = [ "semver", ] From db289689b84c3d332993528b92af1b308d448ea4 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 18 Jan 2021 11:17:46 +0000 Subject: [PATCH 14/50] Bump hermit-abi from 0.1.17 to 0.1.18 Bumps [hermit-abi](https://github.com/hermitcore/libhermit-rs) from 0.1.17 to 0.1.18. - [Release notes](https://github.com/hermitcore/libhermit-rs/releases) - [Commits](https://github.com/hermitcore/libhermit-rs/commits) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 176f0185..d92dfcf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -238,9 +238,9 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] From 17212477c581fcbf6b6dd7b29839e7fd01ca8b14 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 16 Dec 2020 12:03:53 +0000 Subject: [PATCH 15/50] Avoid asserts panicking on broken files --- src/filters.rs | 2 +- src/reduction/alpha.rs | 4 +++- src/reduction/color.rs | 9 +++++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/filters.rs b/src/filters.rs index 54b9bb63..f370778b 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -63,7 +63,7 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: & } pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec) { - assert_eq!(buf.len(), 0); + buf.clear(); buf.reserve(data.len()); match filter { 0 => { diff --git a/src/reduction/alpha.rs b/src/reduction/alpha.rs index cd25a81a..9190672b 100644 --- a/src/reduction/alpha.rs +++ b/src/reduction/alpha.rs @@ -185,7 +185,9 @@ pub fn reduced_alpha_channel(png: &PngImage) -> Option { let channels = png.channels_per_pixel(); let bpp = channels * byte_depth; let bpp_mask = bpp - 1; - assert_eq!(0, bpp & bpp_mask); + if 0 != bpp & bpp_mask { + return None; + } let colored_bytes = bpp - byte_depth; for line in png.scan_lines() { for (i, &byte) in line.data.iter().enumerate() { diff --git a/src/reduction/color.rs b/src/reduction/color.rs index 8be17402..b7c07512 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -12,7 +12,9 @@ pub fn reduce_rgba_to_grayscale_alpha(png: &PngImage) -> Option { let byte_depth = png.ihdr.bit_depth.as_u8() >> 3; let bpp = 4 * byte_depth; let bpp_mask = bpp - 1; - assert_eq!(0, bpp & bpp_mask); + if 0 != bpp & bpp_mask { + return None; + } let colored_bytes = bpp - byte_depth; for line in png.scan_lines() { reduced.push(line.filter); @@ -157,7 +159,10 @@ pub fn reduced_color_to_palette(png: &PngImage) -> Option { let mut aux_headers = png.aux_headers.clone(); if let Some(bkgd_header) = png.aux_headers.get(b"bKGD") { - assert_eq!(bkgd_header.len(), 6); + if bkgd_header.len() != 6 { + // malformed chunk? + return None; + } // In bKGD 16-bit values are used even for 8-bit images let bg = RGBA8::new(bkgd_header[1], bkgd_header[3], bkgd_header[5], 255); let entry = if let Some(&entry) = palette.get(&bg) { From 53ddd721a75b790d2deb517e7e8116555495f131 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 21 Dec 2020 00:15:03 +0000 Subject: [PATCH 16/50] Reject truncated image data instead of panicking --- src/headers.rs | 36 ++++++++++++++++++++++++++++++++++++ src/interlace.rs | 4 ++-- src/png/mod.rs | 5 +++++ src/png/scan_lines.rs | 3 +-- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/headers.rs b/src/headers.rs index 0695bd0e..7a328e7b 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -25,6 +25,42 @@ pub struct IhdrData { pub interlaced: u8, } +impl IhdrData { + /// Bits per pixel + pub fn bpp(&self) -> u8 { + self.bit_depth.as_u8() * self.color_type.channels_per_pixel() + } + + /// Byte length of IDAT that is correct for this IHDR + pub fn raw_data_size(&self) -> usize { + let w = self.width as usize; + let h = self.height as usize; + let bpp = self.bpp(); + + fn bitmap_size(bpp: u8, w: usize, h: usize) -> usize { + (((w / 8) * bpp as usize) + ((w & 7) * bpp as usize + 7) / 8) * h + } + + if self.interlaced == 0 { + bitmap_size(bpp, w, h) + h + } else { + let mut size = bitmap_size(bpp, (w + 7) >> 3, (h + 7) >> 3) + ((h + 7) >> 3); + if w > 4 { + size += bitmap_size(bpp, (w + 3) >> 3, (h + 7) >> 3) + ((h + 7) >> 3); + } + size += bitmap_size(bpp, (w + 3) >> 2, (h + 3) >> 3) + ((h + 3) >> 3); + if w > 2 { + size += bitmap_size(bpp, (w + 1) >> 2, (h + 3) >> 2) + ((h + 3) >> 2); + } + size += bitmap_size(bpp, (w + 1) >> 1, (h + 1) >> 2) + ((h + 1) >> 2); + if w > 1 { + size += bitmap_size(bpp, w >> 1, (h + 1) >> 1) + ((h + 1) >> 1); + } + size + bitmap_size(bpp, w, h >> 1) + (h >> 1) + } + } +} + #[derive(Debug, PartialEq, Clone)] /// Options to use for performing operations on headers (such as stripping) pub enum Headers { diff --git a/src/interlace.rs b/src/interlace.rs index 2d391934..aacf2514 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -5,7 +5,7 @@ use bit_vec::BitVec; #[must_use] pub fn interlace_image(png: &PngImage) -> PngImage { let mut passes: Vec = vec![BitVec::new(); 7]; - let bits_per_pixel = png.ihdr.bit_depth.as_u8() * png.channels_per_pixel(); + let bits_per_pixel = png.ihdr.bpp(); for (index, line) in png.scan_lines().enumerate() { match index % 8 { // Add filter bytes to passes that will be in the output image @@ -95,7 +95,7 @@ pub fn interlace_image(png: &PngImage) -> PngImage { } pub fn deinterlace_image(png: &PngImage) -> PngImage { - let bits_per_pixel = png.ihdr.bit_depth.as_u8() * png.channels_per_pixel(); + let bits_per_pixel = png.ihdr.bpp(); let bits_per_line = 8 + bits_per_pixel as usize * png.ihdr.width as usize; // Initialize each output line with a starting filter byte of 0 // as well as some blank data diff --git a/src/png/mod.rs b/src/png/mod.rs index f2aa30b9..d599a871 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -118,6 +118,11 @@ impl PngData { let ihdr_header = parse_ihdr_header(&ihdr)?; let raw_data = deflate::inflate(idat_headers.as_ref())?; + // Reject files with incorrect width/height or truncated data + if raw_data.len() != ihdr_header.raw_data_size() { + return Err(PngError::TruncatedData); + } + let (palette, transparency_pixel) = Self::palette_to_rgba( ihdr_header.color_type, aux_headers.remove(b"PLTE"), diff --git a/src/png/scan_lines.rs b/src/png/scan_lines.rs index dc923cca..90b92589 100644 --- a/src/png/scan_lines.rs +++ b/src/png/scan_lines.rs @@ -167,8 +167,7 @@ impl Iterator for ScanLineRanges { 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; - assert!(self.left >= len); - self.left -= len; + self.left = self.left.checked_sub(len)?; Some((len, current_pass)) } } From 3163a925946f307c5cc0ed0f475724f5e7a5eddc Mon Sep 17 00:00:00 2001 From: Kornel Date: Fri, 15 Jan 2021 13:50:45 +0000 Subject: [PATCH 17/50] Ignore broken tRNS --- src/reduction/color.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/reduction/color.rs b/src/reduction/color.rs index b7c07512..42d47c9b 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -111,6 +111,7 @@ pub fn reduced_color_to_palette(png: &PngImage) -> Option { let transparency_pixel = png .transparency_pixel .as_ref() + .filter(|t| png.ihdr.color_type == ColorType::RGB && t.len() >= 6) .map(|t| RGB8::new(t[1], t[3], t[5])); for line in png.scan_lines() { raw_data.push(line.filter); From 04010978a01a529f5cf73a87568f33e772370a52 Mon Sep 17 00:00:00 2001 From: Kornel Date: Thu, 17 Dec 2020 14:13:00 +0000 Subject: [PATCH 18/50] Use optimized copy --- src/png/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/png/mod.rs b/src/png/mod.rs index d599a871..eddc44bf 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -100,7 +100,7 @@ impl PngData { let mut idat_headers: Vec = Vec::new(); while let Some(header) = parse_next_header(byte_data, &mut byte_offset, fix_errors)? { match &header.name { - b"IDAT" => idat_headers.extend(header.data), + b"IDAT" => idat_headers.extend_from_slice(header.data), b"acTL" => return Err(PngError::APNGNotSupported), _ => { aux_headers.insert(header.name, header.data.to_owned()); From c73a6b4a83e6c9b8e0b545e2c06a81525ba0c10a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 27 Jan 2021 10:21:02 +0000 Subject: [PATCH 19/50] Bump log from 0.4.13 to 0.4.14 Bumps [log](https://github.com/rust-lang/log) from 0.4.13 to 0.4.14. - [Release notes](https://github.com/rust-lang/log/releases) - [Changelog](https://github.com/rust-lang/log/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/log/compare/0.4.13...0.4.14) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 22 ++++++++-------------- Cargo.toml | 2 +- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d92dfcf7..d9cb6f17 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,12 +74,6 @@ version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -159,7 +153,7 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -168,7 +162,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-utils", ] @@ -178,7 +172,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] @@ -189,7 +183,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "const_fn", "crossbeam-utils", "lazy_static", @@ -204,7 +198,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ "autocfg", - "cfg-if 1.0.0", + "cfg-if", "lazy_static", ] @@ -312,11 +306,11 @@ dependencies = [ [[package]] name = "log" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcf3805d4480bb5b86070dcfeb9e2cb2ebc148adb753c5cca5f884d1d65a42b2" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 022b2318..57111fae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,7 @@ miniz_oxide = "0.4" rgb = "0.8.25" indexmap = "1.6.1" libdeflater = { version = "0.7.1", optional = true } -log = "0.4.13" +log = "0.4.14" stderrlog = { version = "0.5.1", optional = true } crossbeam-channel = "0.5.0" From dddcffb63325c46de417bd311a3ac88236aa57af Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Thu, 28 Jan 2021 10:35:04 +0000 Subject: [PATCH 20/50] Bump libc from 0.2.82 to 0.2.83 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.82 to 0.2.83. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.82...0.2.83) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d9cb6f17..3c7b9757 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,9 +282,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89203f3fba0a3795506acaad8ebce3c80c0af93f994d5a1d7a0b1eeb23271929" +checksum = "7eb0c4e9c72ee9d69b767adebc5f4788462a3b45624acd919475c92597bcaf4f" [[package]] name = "libdeflate-sys" From da78af20ac07bb237916154cbf62ce5ef1deb355 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 29 Jan 2021 10:21:05 +0000 Subject: [PATCH 21/50] Bump libc from 0.2.83 to 0.2.84 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.83 to 0.2.84. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/commits) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3c7b9757..032d7b35 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,9 +282,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0c4e9c72ee9d69b767adebc5f4788462a3b45624acd919475c92597bcaf4f" +checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" [[package]] name = "libdeflate-sys" From 9abb757c31dd0254b1d440b3f15eac5ce26ab68c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 2 Feb 2021 10:36:11 +0000 Subject: [PATCH 22/50] Bump libc from 0.2.84 to 0.2.85 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.84 to 0.2.85. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.84...0.2.85) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 032d7b35..be33cc63 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,9 +282,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.84" +version = "0.2.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cca32fa0182e8c0989459524dc356b8f2b5c10f1b9eb521b7d182c03cf8c5ff" +checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" [[package]] name = "libdeflate-sys" From aaee0a6a2e88d1c509035d1d022f2ac497b8d334 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 5 Feb 2021 10:39:48 +0000 Subject: [PATCH 23/50] Bump image from 0.23.12 to 0.23.13 Bumps [image](https://github.com/image-rs/image) from 0.23.12 to 0.23.13. - [Release notes](https://github.com/image-rs/image/releases) - [Changelog](https://github.com/image-rs/image/blob/master/CHANGES.md) - [Commits](https://github.com/image-rs/image/compare/v0.23.12...v0.23.13) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index be33cc63..09a12fd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -241,9 +241,9 @@ dependencies = [ [[package]] name = "image" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ce04077ead78e39ae8610ad26216aed811996b043d47beed5090db674f9e9b5" +checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d" dependencies = [ "bytemuck", "byteorder", From f8e4a8b1707711582c65f4fe27f0a555b42afb39 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 9 Feb 2021 10:44:49 +0000 Subject: [PATCH 24/50] Bump libc from 0.2.85 to 0.2.86 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.85 to 0.2.86. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.85...0.2.86) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 09a12fd6..fe1b5adb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -282,9 +282,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" [[package]] name = "libdeflate-sys" From 76da6b5468206235f9ae91d2c7a11fa2c86f98a4 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Wed, 24 Feb 2021 13:51:47 -0500 Subject: [PATCH 25/50] Fix Rust 1.50 clippy error --- src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 081d1a60..c43ff623 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -785,10 +785,14 @@ impl Deadline { if let Some(imp) = &self.imp { let elapsed = imp.start.elapsed(); if elapsed > imp.timeout { - if imp - .print_message - .compare_and_swap(true, false, Ordering::SeqCst) - { + if match imp.print_message.compare_exchange( + true, + false, + Ordering::SeqCst, + Ordering::SeqCst, + ) { + Ok(x) | Err(x) => x, + } { warn!("Timed out after {} second(s)", elapsed.as_secs()); } return true; From 5c1e2636c2a11beb31c70fd9e760395728e82e92 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 18:54:53 +0000 Subject: [PATCH 26/50] Bump crossbeam-epoch from 0.9.1 to 0.9.2 Bumps [crossbeam-epoch](https://github.com/crossbeam-rs/crossbeam) from 0.9.1 to 0.9.2. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-epoch-0.9.1...crossbeam-epoch-0.9.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 48 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe1b5adb..7acd25f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,12 +132,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "const_fn" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" - [[package]] name = "crc" version = "1.8.1" @@ -179,14 +173,14 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" +checksum = "d60ab4a8dba064f2fbb5aa270c28da5cf4bbd0e72dae1140a6b0353a779dbe00" dependencies = [ "cfg-if", - "const_fn", "crossbeam-utils", "lazy_static", + "loom", "memoffset", "scopeguard", ] @@ -218,6 +212,19 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "generator" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "winapi", +] + [[package]] name = "glob" version = "0.3.0" @@ -313,6 +320,17 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "loom" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", +] + [[package]] name = "memoffset" version = "0.6.1" @@ -480,6 +498,18 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" + +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "1.1.0" From b0c6c4195e3c932e85483d106d8d105d6580b7ac Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:09:47 +0000 Subject: [PATCH 27/50] Bump crossbeam-utils from 0.8.1 to 0.8.2 Bumps [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) from 0.8.1 to 0.8.2. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-utils-0.8.1...crossbeam-utils-0.8.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7acd25f2..7d920042 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,13 +187,14 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3" dependencies = [ "autocfg", "cfg-if", "lazy_static", + "loom", ] [[package]] From c6337398dfc206a1ccd4f675f1b9fc5c0dad8c2f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:31:49 +0000 Subject: [PATCH 28/50] Bump cc from 1.0.66 to 1.0.67 Bumps [cc](https://github.com/alexcrichton/cc-rs) from 1.0.66 to 1.0.67. - [Release notes](https://github.com/alexcrichton/cc-rs/releases) - [Commits](https://github.com/alexcrichton/cc-rs/compare/1.0.66...1.0.67) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7d920042..ddcaa821 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,9 +70,9 @@ checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "cc" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" +checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd" [[package]] name = "cfg-if" From f44b5aa2d03283d80bff79f120bec427887cf926 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 24 Feb 2021 19:48:49 +0000 Subject: [PATCH 29/50] Bump bytemuck from 1.5.0 to 1.5.1 Bumps [bytemuck](https://github.com/Lokathor/bytemuck) from 1.5.0 to 1.5.1. - [Release notes](https://github.com/Lokathor/bytemuck/releases) - [Changelog](https://github.com/Lokathor/bytemuck/blob/main/changelog.md) - [Commits](https://github.com/Lokathor/bytemuck/compare/v1.5.0...v1.5.1) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ddcaa821..af716892 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,9 +58,9 @@ checksum = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" [[package]] name = "bytemuck" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a4bad0c5981acc24bc09e532f35160f952e35422603f0563cd7a73c2c2e65a0" +checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" [[package]] name = "byteorder" From f2e89140ed26a26886d4dda26a9ab7c55f85a7b8 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 24 Feb 2021 20:48:30 +0000 Subject: [PATCH 30/50] Prevent panics in parse_ihdr_header (#392) --- src/headers.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/headers.rs b/src/headers.rs index 7a328e7b..049ec00c 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -140,6 +140,8 @@ pub fn parse_next_header<'a>( } pub fn parse_ihdr_header(byte_data: &[u8]) -> PngResult { + // This eliminates bounds checks for the rest of the function + let interlaced = byte_data.get(12).copied().ok_or(PngError::TruncatedData)?; let mut rdr = Cursor::new(&byte_data[0..8]); Ok(IhdrData { color_type: match byte_data[9] { @@ -162,6 +164,6 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> PngResult { height: rdr.read_u32::().unwrap(), compression: byte_data[10], filter: byte_data[11], - interlaced: byte_data[12], + interlaced, }) } From 0be36317880792a3769048f36e002e71d4a29d1d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 26 Feb 2021 10:43:12 +0000 Subject: [PATCH 31/50] Bump miniz_oxide from 0.4.3 to 0.4.4 Bumps [miniz_oxide](https://github.com/Frommi/miniz_oxide) from 0.4.3 to 0.4.4. - [Release notes](https://github.com/Frommi/miniz_oxide/releases) - [Changelog](https://github.com/Frommi/miniz_oxide/blob/master/CHANGELOG.md) - [Commits](https://github.com/Frommi/miniz_oxide/commits) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index af716892..21b1acb4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "adler" -version = "0.2.3" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" +checksum = "bedc89c5c7b5550ffb9372eb5c5ffc7f9f705cc3f4a128bd4669b9745f555093" [[package]] name = "adler32" @@ -352,9 +352,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" dependencies = [ "adler", "autocfg", @@ -426,7 +426,7 @@ dependencies = [ "itertools", "libdeflater", "log", - "miniz_oxide 0.4.3", + "miniz_oxide 0.4.4", "rayon", "rgb", "rustc_version", From 6fe1fb39fb7efbfaa6da0d6088990bf6e31ac231 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Fri, 26 Feb 2021 10:55:17 +0000 Subject: [PATCH 32/50] Bump crossbeam-utils from 0.8.2 to 0.8.3 Bumps [crossbeam-utils](https://github.com/crossbeam-rs/crossbeam) from 0.8.2 to 0.8.3. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-utils-0.8.2...crossbeam-utils-0.8.3) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21b1acb4..b9ea089c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,14 +187,13 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bae8f328835f8f5a6ceb6a7842a7f2d0c03692adb5c889347235d59194731fe3" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" dependencies = [ "autocfg", "cfg-if", "lazy_static", - "loom", ] [[package]] From eb7c5be7cc97e57558b6598f9b8df5c0a785cc8c Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 15:19:32 +0000 Subject: [PATCH 33/50] Bump crossbeam-epoch from 0.9.2 to 0.9.3 Bumps [crossbeam-epoch](https://github.com/crossbeam-rs/crossbeam) from 0.9.2 to 0.9.3. - [Release notes](https://github.com/crossbeam-rs/crossbeam/releases) - [Changelog](https://github.com/crossbeam-rs/crossbeam/blob/master/CHANGELOG.md) - [Commits](https://github.com/crossbeam-rs/crossbeam/compare/crossbeam-epoch-0.9.2...crossbeam-epoch-0.9.3) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 41 ++--------------------------------------- 1 file changed, 2 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9ea089c..e8fc8eee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,14 +173,13 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d60ab4a8dba064f2fbb5aa270c28da5cf4bbd0e72dae1140a6b0353a779dbe00" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" dependencies = [ "cfg-if", "crossbeam-utils", "lazy_static", - "loom", "memoffset", "scopeguard", ] @@ -212,19 +211,6 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" -[[package]] -name = "generator" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9fed24fd1e18827652b4d55652899a1e9da8e54d91624dc3437a5bc3a9f9a9c" -dependencies = [ - "cc", - "libc", - "log", - "rustversion", - "winapi", -] - [[package]] name = "glob" version = "0.3.0" @@ -320,17 +306,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "loom" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d44c73b4636e497b4917eb21c33539efa3816741a2d3ff26c6316f1b529481a4" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", -] - [[package]] name = "memoffset" version = "0.6.1" @@ -498,18 +473,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustversion" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb5d2a036dc6d2d8fd16fde3498b04306e29bd193bf306a57427019b823d5acd" - -[[package]] -name = "scoped-tls" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" - [[package]] name = "scopeguard" version = "1.1.0" From 19eff4755b59da321b9b3ffecc2ef4f818fa13b1 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 1 Mar 2021 15:33:22 +0000 Subject: [PATCH 34/50] Bump adler from 1.0.1 to 1.0.2 Bumps [adler](https://github.com/jonas-schievink/adler) from 1.0.1 to 1.0.2. - [Release notes](https://github.com/jonas-schievink/adler/releases) - [Changelog](https://github.com/jonas-schievink/adler/blob/master/CHANGELOG.md) - [Commits](https://github.com/jonas-schievink/adler/compare/v1.0.1...v1.0.2) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8fc8eee..472f0e87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "adler" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bedc89c5c7b5550ffb9372eb5c5ffc7f9f705cc3f4a128bd4669b9745f555093" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "adler32" From 6c7c06766212507231b8b332026204042009cf27 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Tue, 2 Mar 2021 10:39:19 +0000 Subject: [PATCH 35/50] Bump libc from 0.2.86 to 0.2.87 Bumps [libc](https://github.com/rust-lang/libc) from 0.2.86 to 0.2.87. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.86...0.2.87) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 472f0e87..e9782334 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -275,9 +275,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.86" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" +checksum = "265d751d31d6780a3f956bb5b8022feba2d94eeee5a84ba64f4212eedca42213" [[package]] name = "libdeflate-sys" From ef3bb7444b30ba47a4ef9841c09a3fddd6a9a75a Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Wed, 3 Mar 2021 10:35:12 +0000 Subject: [PATCH 36/50] Bump image from 0.23.13 to 0.23.14 Bumps [image](https://github.com/image-rs/image) from 0.23.13 to 0.23.14. - [Release notes](https://github.com/image-rs/image/releases) - [Changelog](https://github.com/image-rs/image/blob/master/CHANGES.md) - [Commits](https://github.com/image-rs/image/compare/v0.23.13...v0.23.14) Signed-off-by: dependabot-preview[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e9782334..213a7f31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,9 +234,9 @@ dependencies = [ [[package]] name = "image" -version = "0.23.13" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293f07a1875fa7e9c5897b51aa68b2d8ed8271b87e1a44cb64b9c3d98aabbc0d" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" dependencies = [ "bytemuck", "byteorder", From 14867c7abc1ce053affe2d796168fb1ade22a788 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 19 May 2021 15:04:31 +0100 Subject: [PATCH 37/50] Clippy lints (#401) --- src/colors.rs | 4 ++++ src/error.rs | 10 +++------ src/headers.rs | 13 ++++++++--- src/lib.rs | 9 ++++---- src/png/mod.rs | 8 +++---- src/png/scan_lines.rs | 2 +- src/rayon.rs | 6 +----- src/reduction/bit_depth.rs | 3 +-- src/reduction/color.rs | 2 +- src/reduction/mod.rs | 44 ++++++++++++++++---------------------- 10 files changed, 49 insertions(+), 52 deletions(-) diff --git a/src/colors.rs b/src/colors.rs index f5fe57ec..ae698dca 100644 --- a/src/colors.rs +++ b/src/colors.rs @@ -101,6 +101,10 @@ impl BitDepth { } } /// Parse a number of bits per channel per pixel into a `BitDepth` + /// + /// # Panics + /// + /// If depth is unsupported #[inline] pub fn from_u8(depth: u8) -> BitDepth { match depth { diff --git a/src/error.rs b/src/error.rs index 0198379f..0f099d5d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -14,15 +14,11 @@ pub enum PngError { Other(Box), } -impl Error for PngError { - // deprecated - fn description(&self) -> &str { - "" - } -} +impl Error for PngError {} impl fmt::Display for PngError { #[inline] + #[cold] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { PngError::DeflatedDataTooLong(_) => f.write_str("deflated data too long"), @@ -40,7 +36,7 @@ impl fmt::Display for PngError { } impl PngError { - #[inline] + #[cold] pub fn new(description: &str) -> PngError { PngError::Other(description.into()) } diff --git a/src/headers.rs b/src/headers.rs index 049ec00c..be0381d9 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -27,11 +27,14 @@ pub struct IhdrData { impl IhdrData { /// Bits per pixel + #[must_use] + #[inline] pub fn bpp(&self) -> u8 { self.bit_depth.as_u8() * self.color_type.channels_per_pixel() } /// Byte length of IDAT that is correct for this IHDR + #[must_use] pub fn raw_data_size(&self) -> usize { let w = self.width as usize; let h = self.height as usize; @@ -134,7 +137,7 @@ pub fn parse_next_header<'a>( ))); } - let mut name = [0u8; 4]; + let mut name = [0_u8; 4]; name.copy_from_slice(chunk_name); Ok(Some(RawHeader { name, data })) } @@ -160,8 +163,12 @@ pub fn parse_ihdr_header(byte_data: &[u8]) -> PngResult { 16 => BitDepth::Sixteen, _ => return Err(PngError::new("Unexpected bit depth in header")), }, - width: rdr.read_u32::().unwrap(), - height: rdr.read_u32::().unwrap(), + width: rdr + .read_u32::() + .map_err(|_| PngError::TruncatedData)?, + height: rdr + .read_u32::() + .map_err(|_| PngError::TruncatedData)?, compression: byte_data[10], filter: byte_data[11], interlaced, diff --git a/src/lib.rs b/src/lib.rs index c43ff623..0b6fc479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ #![warn(clippy::path_buf_push_overwrite)] #![warn(clippy::range_plus_one)] #![allow(clippy::cognitive_complexity)] +#![allow(clippy::upper_case_acronyms)] #![cfg_attr( not(any(feature = "libdeflater", feature = "zopfli")), allow(irrefutable_let_patterns), @@ -97,7 +98,7 @@ impl InFile { pub fn path(&self) -> Option<&Path> { match *self { InFile::Path(ref p) => Some(p.as_path()), - _ => None, + InFile::StdIn => None, } } } @@ -589,7 +590,7 @@ fn optimize_png( ); return None; } - _ => return None, + Err(_) => return None, }; // update best size across all threads @@ -655,14 +656,14 @@ fn optimize_png( " file size = {} bytes ({} bytes = {:.2}% decrease)", output.len(), file_original_size - output.len(), - (file_original_size - output.len()) as f64 / file_original_size as f64 * 100f64 + (file_original_size - output.len()) as f64 / file_original_size as f64 * 100_f64 ); } else { info!( " file size = {} bytes ({} bytes = {:.2}% increase)", output.len(), output.len() - file_original_size, - (output.len() - file_original_size) as f64 / file_original_size as f64 * 100f64 + (output.len() - file_original_size) as f64 / file_original_size as f64 * 100_f64 ); } diff --git a/src/png/mod.rs b/src/png/mod.rs index eddc44bf..e8b6dddc 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -208,10 +208,10 @@ impl PngData { .fold( 0, |prev, (index, px)| { - if px.a != 255 { - index + 1 - } else { + if px.a == 255 { prev + } else { + index + 1 } }, ); @@ -346,7 +346,7 @@ impl PngImage { // Avoid vertical filtering on first line of each interlacing pass for filter in if last_pass == line.pass { 0..5 } else { 0..2 } { filter_line(filter, bpp, &line.data, last_line, &mut f_buf); - let size = f_buf.iter().fold(0u64, |acc, &x| { + let size = f_buf.iter().fold(0_u64, |acc, &x| { let signed = x as i8; acc + i16::from(signed).abs() as u64 }); diff --git a/src/png/scan_lines.rs b/src/png/scan_lines.rs index 90b92589..2a13941f 100644 --- a/src/png/scan_lines.rs +++ b/src/png/scan_lines.rs @@ -1,7 +1,7 @@ use crate::png::PngImage; -#[derive(Debug, Clone)] /// An iterator over the scan lines of a PNG image +#[derive(Debug, Clone)] pub struct ScanLines<'a> { iter: ScanLineRanges, /// A reference to the PNG image being iterated upon diff --git a/src/rayon.rs b/src/rayon.rs index c0ffd8c5..768db04c 100644 --- a/src/rayon.rs +++ b/src/rayon.rs @@ -10,11 +10,7 @@ pub trait ParallelIterator: Iterator + Sized { where OP: Fn(Self::Item, Self::Item) -> Self::Item + Sync, { - if let Some(a) = self.next() { - Some(self.fold(a, op)) - } else { - None - } + self.next().map(|a| self.fold(a, op)) } } diff --git a/src/reduction/bit_depth.rs b/src/reduction/bit_depth.rs index 49fee066..75ad95df 100644 --- a/src/reduction/bit_depth.rs +++ b/src/reduction/bit_depth.rs @@ -123,9 +123,8 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op }; if permutations.iter().any(|perm| *perm == byte) { break; - } else { - minimum_bits <<= 1; } + minimum_bits <<= 1; } } } diff --git a/src/reduction/color.rs b/src/reduction/color.rs index 42d47c9b..11686fc6 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -150,7 +150,7 @@ pub fn reduced_color_to_palette(png: &PngImage) -> Option { } }) .max(); - let trns_size = num_transparent.map(|n| n + 8).unwrap_or(0); + let trns_size = num_transparent.map_or(0, |n| n + 8); let headers_size = palette.len() * 3 + 8 + trns_size; if raw_data.len() + headers_size > png.data.len() { diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index 1b9f7fc7..e6f4bf7d 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -6,9 +6,9 @@ use rgb::RGBA8; use std::borrow::Cow; pub mod alpha; -use crate::alpha::*; +use crate::alpha::reduced_alpha_channel; pub mod bit_depth; -use crate::bit_depth::*; +use crate::bit_depth::reduce_bit_depth_8_or_less; pub mod color; use crate::color::*; @@ -17,7 +17,6 @@ pub(crate) use crate::bit_depth::reduce_bit_depth; /// Attempt to reduce the number of colors in the palette /// Returns `None` if palette hasn't changed -#[must_use] pub fn reduced_palette(png: &PngImage) -> Option { if png.ihdr.color_type != ColorType::Indexed { // Can't reduce if there is no palette @@ -70,14 +69,14 @@ pub fn reduced_palette(png: &PngImage) -> Option { .unwrap_or_else(|| RGBA8::new(0, 0, 0, 255)); ((color.a as i32) << 18) // These are coefficients for standard sRGB to luma conversion - - (color.r as i32) * 299 - - (color.g as i32) * 587 - - (color.b as i32) * 114 + - i32::from(color.r) * 299 + - i32::from(color.g) * 587 + - i32::from(color.b) * 114 }; color_val(a.0).cmp(&color_val(b.0)) }); - let mut next_index = 0u16; + let mut next_index = 0_u16; let mut seen = IndexMap::with_capacity(palette.len()); for (i, used) in used_enumerated.iter().cloned() { if !used { @@ -138,33 +137,33 @@ fn do_palette_reduction(png: &PngImage, palette_map: &[Option; 256]) -> Opti } fn palette_map_to_byte_map(png: &PngImage, palette_map: &[Option; 256]) -> Option<[u8; 256]> { - let len = png.palette.as_ref().map(|p| p.len()).unwrap_or(0); + let len = png.palette.as_ref().map_or(0, |p| p.len()); if (0..len).all(|i| palette_map[i].map_or(true, |to| to == i as u8)) { // No reduction necessary return None; } - let mut byte_map = [0u8; 256]; + let mut byte_map = [0_u8; 256]; // low bit-depths can be pre-computed for every byte value match png.ihdr.bit_depth { BitDepth::Eight => { - for byte in 0..=255 { - byte_map[byte as usize] = palette_map[byte as usize].unwrap_or(0) + for byte in 0..=255usize { + byte_map[byte] = palette_map[byte].unwrap_or(0) } } BitDepth::Four => { - for byte in 0..=255 { - byte_map[byte as usize] = palette_map[(byte & 0x0F) as usize].unwrap_or(0) - | (palette_map[(byte >> 4) as usize].unwrap_or(0) << 4); + for byte in 0..=255usize { + byte_map[byte] = palette_map[(byte & 0x0F)].unwrap_or(0) + | (palette_map[(byte >> 4)].unwrap_or(0) << 4); } } BitDepth::Two => { - for byte in 0..=255 { - byte_map[byte as usize] = palette_map[(byte & 0x03) as usize].unwrap_or(0) - | (palette_map[((byte >> 2) & 0x03) as usize].unwrap_or(0) << 2) - | (palette_map[((byte >> 4) & 0x03) as usize].unwrap_or(0) << 4) - | (palette_map[(byte >> 6) as usize].unwrap_or(0) << 6); + for byte in 0..=255usize { + byte_map[byte] = palette_map[(byte & 0x03)].unwrap_or(0) + | (palette_map[((byte >> 2) & 0x03)].unwrap_or(0) << 2) + | (palette_map[((byte >> 4) & 0x03)].unwrap_or(0) << 4) + | (palette_map[(byte >> 6)].unwrap_or(0) << 6); } } _ => {} @@ -174,12 +173,7 @@ fn palette_map_to_byte_map(png: &PngImage, palette_map: &[Option; 256]) -> O } fn reordered_palette(palette: &[RGBA8], palette_map: &[Option; 256]) -> Vec { - let max_index = palette_map - .iter() - .cloned() - .filter_map(|x| x) - .max() - .unwrap_or(0) as usize; + let max_index = palette_map.iter().cloned().flatten().max().unwrap_or(0) as usize; let mut new_palette = vec![RGBA8::new(0, 0, 0, 255); max_index + 1]; for (&color, &map_to) in palette.iter().zip(palette_map.iter()) { if let Some(map_to) = map_to { From b6cc8e24148f25ed6d06a5ef2f9d263ddf96aa76 Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 19 May 2021 20:16:14 +0100 Subject: [PATCH 38/50] Optimize unfiltering (#400) * Clippy lints * Fewer pushes * Remove special case for empty last line * Zip with last line * Combine bound checks --- src/filters.rs | 97 +++++++++++++++----------------------------------- src/png/mod.rs | 1 + 2 files changed, 30 insertions(+), 68 deletions(-) diff --git a/src/filters.rs b/src/filters.rs index f370778b..0c4d50c0 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -65,88 +65,49 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: & pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec) { buf.clear(); buf.reserve(data.len()); + assert_eq!(data.len(), last_line.len()); match filter { 0 => { buf.extend_from_slice(data); } 1 => { - for (i, byte) in data.iter().enumerate() { - match i.checked_sub(bpp) { - Some(x) => { - let b = buf[x]; - buf.push(byte.wrapping_add(b)); - } - None => { - buf.push(*byte); - } - }; + for (i, &cur) in data.iter().enumerate() { + let prev_byte = i.checked_sub(bpp).and_then(|x| buf.get(x).copied()); + buf.push(match prev_byte { + Some(b) => cur.wrapping_add(b), + None => cur, + }); } } 2 => { - if last_line.is_empty() { - buf.extend_from_slice(data); - } else { - buf.extend( - data.iter() - .zip(last_line.iter()) - .map(|(cur, last)| cur.wrapping_add(*last)), - ); - }; + buf.extend( + data.iter() + .zip(last_line) + .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 = buf[x]; - buf.push(byte.wrapping_add(b >> 1)); - } - None => { - buf.push(*byte); - } - }; - } else { - match i.checked_sub(bpp) { - Some(x) => { - let b = buf[x]; - buf.push(byte.wrapping_add( - ((u16::from(b) + u16::from(last_line[i])) >> 1) as u8, - )); - } - None => { - buf.push(byte.wrapping_add(last_line[i] >> 1)); - } - }; - }; + for (i, (&cur, &last)) in data.iter().zip(last_line).enumerate() { + let prev_byte = i.checked_sub(bpp).and_then(|x| buf.get(x).copied()); + buf.push(match prev_byte { + Some(b) => cur.wrapping_add(((u16::from(b) + u16::from(last)) >> 1) as u8), + None => cur.wrapping_add(last >> 1), + }); } } 4 => { - for (i, byte) in data.iter().enumerate() { - if last_line.is_empty() { - match i.checked_sub(bpp) { - Some(x) => { - let b = buf[x]; - buf.push(byte.wrapping_add(b)); + for (i, (&cur, &up)) in data.iter().zip(last_line).enumerate() { + buf.push( + match i + .checked_sub(bpp) + .map(|x| (buf.get(x).copied(), last_line.get(x).copied())) + { + Some((Some(left), Some(left_up))) => { + cur.wrapping_add(paeth_predictor(left, up, left_up)) } - None => { - buf.push(*byte); - } - }; - } else { - match i.checked_sub(bpp) { - Some(x) => { - let b = buf[x]; - buf.push(byte.wrapping_add(paeth_predictor( - b, - last_line[i], - last_line[x], - ))); - } - None => { - buf.push(byte.wrapping_add(last_line[i])); - } - }; - }; + _ => cur.wrapping_add(up), + }, + ); } } _ => unreachable!(), diff --git a/src/png/mod.rs b/src/png/mod.rs index e8b6dddc..a3601ffa 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -294,6 +294,7 @@ impl PngImage { last_pass = pass; } } + last_line.resize(line.data.len(), 0); unfilter_line( line.filter, bpp, From a38b2fd94305f2546634e5b1e6a8fa25c2d0cfb8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 May 2021 03:45:08 -0400 Subject: [PATCH 39/50] Bump hosted-git-info from 2.5.0 to 2.8.9 (#402) Bumps [hosted-git-info](https://github.com/npm/hosted-git-info) from 2.5.0 to 2.8.9. - [Release notes](https://github.com/npm/hosted-git-info/releases) - [Changelog](https://github.com/npm/hosted-git-info/blob/v2.8.9/CHANGELOG.md) - [Commits](https://github.com/npm/hosted-git-info/compare/v2.5.0...v2.8.9) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d65199e..8bf4cf35 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,9 +85,9 @@ "dev": true }, "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, "indent-string": { From d2cebc3c2d8796544a9b023270504ed576fd034f Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 15 Jun 2021 14:07:32 +0100 Subject: [PATCH 40/50] Don't allocate reduced buffer until needed --- src/reduction/bit_depth.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/reduction/bit_depth.rs b/src/reduction/bit_depth.rs index 75ad95df..aef295cf 100644 --- a/src/reduction/bit_depth.rs +++ b/src/reduction/bit_depth.rs @@ -75,7 +75,6 @@ pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option #[must_use] pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option { assert!((1..8).contains(&minimum_bits)); - let mut reduced = BitVec::with_capacity(png.data.len() * 8); let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize; if minimum_bits >= bit_depth { return None; @@ -130,6 +129,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op } } + let mut reduced = BitVec::with_capacity(png.data.len() * 8); for line in png.scan_lines() { reduced.extend(BitVec::from_bytes(&[line.filter])); let bit_vec = BitVec::from_bytes(&line.data); From f8bb4fa63715349aa893407df4b57de10cafa1fe Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 15 Jun 2021 12:33:03 +0100 Subject: [PATCH 41/50] Fix tests without default features --- tests/flags.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/flags.rs b/tests/flags.rs index 69d79f6a..6da0ac62 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -494,6 +494,7 @@ fn fix_errors() { } #[test] +#[cfg(feature = "zopfli")] fn zopfli_mode() { let input = PathBuf::from("tests/files/zopfli_mode.png"); let (output, mut opts) = get_opts(&input); @@ -511,6 +512,7 @@ fn zopfli_mode() { } #[test] +#[cfg(feature = "libdeflater")] fn libdeflater_mode() { let input = PathBuf::from("tests/files/zopfli_mode.png"); let (output, mut opts) = get_opts(&input); From dac408627b97f05c7b6e5224fb9979ca78784c03 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 15 Jun 2021 14:10:38 +0100 Subject: [PATCH 42/50] bit-vec is too slow for debug mode --- Cargo.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 57111fae..5a5f19a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,7 +78,12 @@ parallel = ["rayon", "indexmap/rayon"] [lib] name = "oxipng" path = "src/lib.rs" + [profile.dev] opt-level = 2 + [profile.release] lto = "thin" + +[profile.dev.package.bit-vec] +opt-level = 3 From 3e996a0f8266aefc82bf0b2111fe2f6cfe20ccf4 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 15 Jun 2021 13:04:38 +0100 Subject: [PATCH 43/50] Make sure passes clear last line --- src/png/mod.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/png/mod.rs b/src/png/mod.rs index a3601ffa..2c181b36 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -285,14 +285,12 @@ impl PngImage { let mut unfiltered = Vec::with_capacity(self.data.len()); let bpp = ((self.ihdr.bit_depth.as_u8() * self.channels_per_pixel() + 7) / 8) as usize; let mut last_line: Vec = Vec::new(); - let mut last_pass = 1; + let mut last_pass = None; let mut unfiltered_buf = Vec::new(); for line in self.scan_lines() { - if let Some(pass) = line.pass { - if pass != last_pass { - last_line.clear(); - last_pass = pass; - } + if last_pass != line.pass { + last_line.clear(); + last_pass = line.pass; } last_line.resize(line.data.len(), 0); unfilter_line( @@ -325,6 +323,9 @@ impl PngImage { let mut f_buf = Vec::new(); for line in self.scan_lines() { f_buf.clear(); + if last_pass != line.pass { + last_line = &[]; + } match filter { 0 | 1 | 2 | 3 | 4 => { let filter = if last_pass == line.pass || filter <= 1 { From c4910709d98f6a6cb8b8182890abbdc45ce86b50 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 15 Jun 2021 12:24:04 +0100 Subject: [PATCH 44/50] Assertions --- src/filters.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/filters.rs b/src/filters.rs index 0c4d50c0..8b85ca17 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -1,4 +1,6 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec) { + assert!(data.len() >= bpp); + assert!(last_line.is_empty() || data.len() == last_line.len()); buf.reserve(data.len()); match filter { 0 => { @@ -17,6 +19,7 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: & if last_line.is_empty() { buf.extend_from_slice(data); } else { + assert_eq!(data.len(), last_line.len()); buf.extend( data.iter() .zip(last_line.iter()) @@ -65,6 +68,7 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: & pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec) { buf.clear(); buf.reserve(data.len()); + assert!(data.len() >= bpp); assert_eq!(data.len(), last_line.len()); match filter { 0 => { From 91a18ebe972cbbc012f38c52c2ed14c54e7a6ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lauzier?= Date: Tue, 22 Jun 2021 23:08:02 -0400 Subject: [PATCH 45/50] Fix some clippy warnings --- src/interlace.rs | 4 +-- src/png/mod.rs | 12 ++----- src/reduction/bit_depth.rs | 4 +-- tests/filters.rs | 8 +++-- tests/flags.rs | 30 +++++++++--------- tests/interlaced.rs | 8 +++-- tests/lib.rs | 2 -- tests/reduction.rs | 16 +++++----- tests/regression.rs | 64 ++++++++++++-------------------------- 9 files changed, 62 insertions(+), 86 deletions(-) diff --git a/src/interlace.rs b/src/interlace.rs index aacf2514..81928c7d 100644 --- a/src/interlace.rs +++ b/src/interlace.rs @@ -40,7 +40,7 @@ pub fn interlace_image(png: &PngImage) -> PngImage { passes[6].extend(BitVec::from_elem(8, false)); } } - let bit_vec = BitVec::from_bytes(&line.data); + 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.width * u32::from(bits_per_pixel)) as usize { @@ -105,7 +105,7 @@ pub fn deinterlace_image(png: &PngImage) -> PngImage { let mut pass_constants = interlaced_constants(current_pass); 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 bit_vec = BitVec::from_bytes(line.data); let bits_in_line = ((png.ihdr.width - u32::from(pass_constants.x_shift) + u32::from(pass_constants.x_step) - 1) diff --git a/src/png/mod.rs b/src/png/mod.rs index 2c181b36..4df7169b 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -293,13 +293,7 @@ impl PngImage { last_pass = line.pass; } last_line.resize(line.data.len(), 0); - unfilter_line( - line.filter, - bpp, - &line.data, - &last_line, - &mut unfiltered_buf, - ); + unfilter_line(line.filter, bpp, line.data, &last_line, &mut unfiltered_buf); unfiltered.push(0); unfiltered.extend_from_slice(&unfiltered_buf); std::mem::swap(&mut last_line, &mut unfiltered_buf); @@ -334,7 +328,7 @@ impl PngImage { 0 }; filtered.push(filter); - filter_line(filter, bpp, &line.data, last_line, &mut f_buf); + filter_line(filter, bpp, line.data, last_line, &mut f_buf); filtered.extend_from_slice(&f_buf); } 5 => { @@ -347,7 +341,7 @@ impl PngImage { // Avoid vertical filtering on first line of each interlacing pass for filter in if last_pass == line.pass { 0..5 } else { 0..2 } { - filter_line(filter, bpp, &line.data, last_line, &mut f_buf); + filter_line(filter, bpp, line.data, last_line, &mut f_buf); let size = f_buf.iter().fold(0_u64, |acc, &x| { let signed = x as i8; acc + i16::from(signed).abs() as u64 diff --git a/src/reduction/bit_depth.rs b/src/reduction/bit_depth.rs index aef295cf..12c837f6 100644 --- a/src/reduction/bit_depth.rs +++ b/src/reduction/bit_depth.rs @@ -108,7 +108,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op } } } else { - let bit_vec = BitVec::from_bytes(&line.data); + let bit_vec = BitVec::from_bytes(line.data); for byte in bit_vec.to_bytes() { while minimum_bits < bit_depth { let permutations: &[u8] = if minimum_bits == 1 { @@ -132,7 +132,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op let mut reduced = BitVec::with_capacity(png.data.len() * 8); for line in png.scan_lines() { reduced.extend(BitVec::from_bytes(&[line.filter])); - let bit_vec = BitVec::from_bytes(&line.data); + let bit_vec = BitVec::from_bytes(line.data); for (i, bit) in bit_vec.iter().enumerate() { let bit_index = bit_depth - (i % bit_depth); if bit_index <= minimum_bits { diff --git a/tests/filters.rs b/tests/filters.rs index 124baed4..2f482e9b 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -6,14 +6,16 @@ use std::path::Path; use std::path::PathBuf; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options::default(); - options.force = true; + let mut options = oxipng::Options { + force: true, + ..Default::default() + }; let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; ( - OutFile::Path(Some(input.with_extension("out.png").to_owned())), + OutFile::Path(Some(input.with_extension("out.png"))), options, ) } diff --git a/tests/flags.rs b/tests/flags.rs index 6da0ac62..466e16f4 100644 --- a/tests/flags.rs +++ b/tests/flags.rs @@ -6,14 +6,16 @@ use std::path::Path; use std::path::PathBuf; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options::default(); - options.force = true; + let mut options = oxipng::Options { + force: true, + ..Default::default() + }; let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; ( - OutFile::Path(Some(input.with_extension("out.png").to_owned())), + OutFile::Path(Some(input.with_extension("out.png"))), options, ) } @@ -32,7 +34,7 @@ fn test_it_converts( assert_eq!(png.raw.ihdr.color_type, color_type_in); assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in); - match oxipng::optimize(&InFile::Path(input), &output, &opts) { + match oxipng::optimize(&InFile::Path(input), output, opts) { Ok(_) => (), Err(x) => panic!("{}", x), }; @@ -163,7 +165,7 @@ fn strip_headers_list() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -197,7 +199,7 @@ fn strip_headers_safe() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -231,7 +233,7 @@ fn strip_headers_all() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -265,7 +267,7 @@ fn strip_headers_none() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -297,7 +299,7 @@ fn interlacing_0_to_1() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -327,7 +329,7 @@ fn interlacing_1_to_0() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -359,7 +361,7 @@ fn interlacing_0_to_1_small_files() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -393,7 +395,7 @@ fn interlacing_1_to_0_small_files() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -428,7 +430,7 @@ fn interlaced_0_to_1_other_filter_mode() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -478,7 +480,7 @@ fn fix_errors() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, false) { + let png = match PngData::new(output, false) { Ok(x) => x, Err(x) => { remove_file(output).ok(); diff --git a/tests/interlaced.rs b/tests/interlaced.rs index b7f15afc..65cc0ac2 100644 --- a/tests/interlaced.rs +++ b/tests/interlaced.rs @@ -6,14 +6,16 @@ use std::path::Path; use std::path::PathBuf; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options::default(); - options.force = true; + let mut options = oxipng::Options { + force: true, + ..Default::default() + }; let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; ( - OutFile::Path(Some(input.with_extension("out.png").to_owned())), + OutFile::Path(Some(input.with_extension("out.png"))), options, ) } diff --git a/tests/lib.rs b/tests/lib.rs index cce5520e..8f5e28d1 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,5 +1,3 @@ -use oxipng; - use oxipng::Headers; use oxipng::OutFile; use std::default::Default; diff --git a/tests/reduction.rs b/tests/reduction.rs index 1431c586..0951c628 100644 --- a/tests/reduction.rs +++ b/tests/reduction.rs @@ -6,14 +6,16 @@ use std::path::Path; use std::path::PathBuf; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options::default(); - options.force = true; + let mut options = oxipng::Options { + force: true, + ..Default::default() + }; let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; ( - OutFile::Path(Some(input.with_extension("out.png").to_owned())), + OutFile::Path(Some(input.with_extension("out.png"))), options, ) } @@ -711,7 +713,7 @@ fn small_files() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(&output).ok(); @@ -743,7 +745,7 @@ fn palette_should_be_reduced_with_dupes() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(&output).ok(); @@ -776,7 +778,7 @@ fn palette_should_be_reduced_with_unused() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(&output).ok(); @@ -809,7 +811,7 @@ fn palette_should_be_reduced_with_both() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(&output).ok(); diff --git a/tests/regression.rs b/tests/regression.rs index 2085741f..17a60f25 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -6,14 +6,16 @@ use std::path::Path; use std::path::PathBuf; fn get_opts(input: &Path) -> (OutFile, oxipng::Options) { - let mut options = oxipng::Options::default(); - options.force = true; + let mut options = oxipng::Options { + force: true, + ..Default::default() + }; let mut filter = IndexSet::new(); filter.insert(0); options.filter = filter; ( - OutFile::Path(Some(input.with_extension("out.png").to_owned())), + OutFile::Path(Some(input.with_extension("out.png"))), options, ) } @@ -99,7 +101,7 @@ fn issue_42() { let output = output.path().unwrap(); assert!(output.exists()); - let png = match PngData::new(&output, opts.fix_errors) { + let png = match PngData::new(output, opts.fix_errors) { Ok(x) => x, Err(x) => { remove_file(output).ok(); @@ -287,12 +289,10 @@ fn issue_92_filter_5() { let input = "tests/files/issue-92.png"; let (_, mut opts) = get_opts(Path::new(input)); opts.filter = [5].iter().cloned().collect(); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-f5-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-f5-out.png"))); test_it_converts( - &input, + input, Some((output, opts)), ColorType::Grayscale, BitDepth::Eight, @@ -308,9 +308,7 @@ fn issue_113_white() { opts.interlace = Some(1); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Black); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-white-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-white-out.png"))); test_it_converts( input, Some((output, opts)), @@ -328,9 +326,7 @@ fn issue_113_black() { opts.interlace = Some(1); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Black); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-black-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-black-out.png"))); test_it_converts( input, Some((output, opts)), @@ -348,9 +344,7 @@ fn issue_113_right() { opts.interlace = Some(1); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Right); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-right-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-right-out.png"))); test_it_converts( input, Some((output, opts)), @@ -368,9 +362,7 @@ fn issue_113_left() { opts.interlace = Some(1); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Left); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-left-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-left-out.png"))); test_it_converts( input, Some((output, opts)), @@ -388,9 +380,7 @@ fn issue_113_up() { opts.interlace = Some(1); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Up); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-up-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-up-out.png"))); test_it_converts( input, Some((output, opts)), @@ -408,9 +398,7 @@ fn issue_113_down() { opts.interlace = Some(1); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Down); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-down-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-down-out.png"))); test_it_converts( input, Some((output, opts)), @@ -440,9 +428,7 @@ fn issue_133_black() { let (_, mut opts) = get_opts(Path::new(input)); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Black); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-black-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-black-out.png"))); test_it_converts( input, Some((output, opts)), @@ -459,9 +445,7 @@ fn issue_133_white() { let (_, mut opts) = get_opts(Path::new(input)); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::White); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-white-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-white-out.png"))); test_it_converts( input, Some((output, opts)), @@ -478,9 +462,7 @@ fn issue_133_up() { let (_, mut opts) = get_opts(Path::new(input)); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Up); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-up-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-up-out.png"))); test_it_converts( input, Some((output, opts)), @@ -497,9 +479,7 @@ fn issue_133_down() { let (_, mut opts) = get_opts(Path::new(input)); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Down); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-down-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-down-out.png"))); test_it_converts( input, Some((output, opts)), @@ -516,9 +496,7 @@ fn issue_133_right() { let (_, mut opts) = get_opts(Path::new(input)); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Right); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-right-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-right-out.png"))); test_it_converts( input, Some((output, opts)), @@ -535,9 +513,7 @@ fn issue_133_left() { let (_, mut opts) = get_opts(Path::new(input)); opts.alphas = IndexSet::new(); opts.alphas.insert(AlphaOptim::Left); - let output = OutFile::Path(Some( - Path::new(input).with_extension("-left-out.png").to_owned(), - )); + let output = OutFile::Path(Some(Path::new(input).with_extension("-left-out.png"))); test_it_converts( input, Some((output, opts)), From 286aaffa31e90586041007d7765d64dfd30b8730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Lauzier?= Date: Thu, 24 Jun 2021 16:21:37 -0400 Subject: [PATCH 46/50] small fix --- src/atomicmin.rs | 4 ++-- src/png/mod.rs | 2 +- tests/filters.rs | 2 +- tests/regression.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/atomicmin.rs b/src/atomicmin.rs index af2287a9..73c3d997 100644 --- a/src/atomicmin.rs +++ b/src/atomicmin.rs @@ -9,13 +9,13 @@ pub struct AtomicMin { impl AtomicMin { pub fn new(init: Option) -> Self { Self { - val: AtomicUsize::new(init.unwrap_or(usize::max_value())), + val: AtomicUsize::new(init.unwrap_or(usize::MAX)), } } pub fn get(&self) -> Option { let val = self.val.load(SeqCst); - if val == usize::max_value() { + if val == usize::MAX { None } else { Some(val) diff --git a/src/png/mod.rs b/src/png/mod.rs index 4df7169b..44bfded4 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -337,7 +337,7 @@ impl PngImage { // http://www.libpng.org/pub/png/book/chapter09.html let mut best_filter = 0; let mut best_line = Vec::new(); - let mut best_size = std::u64::MAX; + let mut best_size = u64::MAX; // Avoid vertical filtering on first line of each interlacing pass for filter in if last_pass == line.pass { 0..5 } else { 0..2 } { diff --git a/tests/filters.rs b/tests/filters.rs index 2f482e9b..4da00a8c 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -57,7 +57,7 @@ fn test_it_converts( if let Some(palette) = png.raw.palette.as_ref() { assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize)); } else { - assert!(png.raw.ihdr.color_type != ColorType::Indexed); + assert_ne!(png.raw.ihdr.color_type, ColorType::Indexed); } remove_file(output).ok(); diff --git a/tests/regression.rs b/tests/regression.rs index 17a60f25..f4524c3a 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -64,7 +64,7 @@ fn test_it_converts( if let Some(palette) = png.raw.palette.as_ref() { assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize)); } else { - assert!(png.raw.ihdr.color_type != ColorType::Indexed); + assert_ne!(png.raw.ihdr.color_type, ColorType::Indexed); } remove_file(output).ok(); From ea75f6ccc1528270542d172d7bf40f796d36a555 Mon Sep 17 00:00:00 2001 From: Kornel Date: Mon, 12 Jul 2021 04:07:18 +0100 Subject: [PATCH 47/50] Handle files with invalid filters (#410) The bad filter case is reachable, and can happen when the PNG file is corrupted. --- src/filters.rs | 13 +++++++++++-- src/png/mod.rs | 8 ++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/filters.rs b/src/filters.rs index 8b85ca17..c0c10b10 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -1,3 +1,5 @@ +use crate::error::PngError; + pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec) { assert!(data.len() >= bpp); assert!(last_line.is_empty() || data.len() == last_line.len()); @@ -65,7 +67,13 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: & } } -pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: &mut Vec) { +pub fn unfilter_line( + filter: u8, + bpp: usize, + data: &[u8], + last_line: &[u8], + buf: &mut Vec, +) -> Result<(), PngError> { buf.clear(); buf.reserve(data.len()); assert!(data.len() >= bpp); @@ -114,8 +122,9 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8], buf: ); } } - _ => unreachable!(), + _ => return Err(PngError::InvalidData), } + Ok(()) } fn paeth_predictor(a: u8, b: u8, c: u8) -> u8 { diff --git a/src/png/mod.rs b/src/png/mod.rs index 44bfded4..2ae3b116 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -136,7 +136,7 @@ impl PngData { transparency_pixel, aux_headers, }; - raw.data = raw.unfilter_image(); + raw.data = raw.unfilter_image()?; // Return the PngData Ok(Self { idat_data: idat_headers, @@ -281,7 +281,7 @@ impl PngImage { } /// Reverse all filters applied on the image, returning an unfiltered IDAT bytestream - fn unfilter_image(&self) -> Vec { + fn unfilter_image(&self) -> Result, PngError> { let mut unfiltered = Vec::with_capacity(self.data.len()); let bpp = ((self.ihdr.bit_depth.as_u8() * self.channels_per_pixel() + 7) / 8) as usize; let mut last_line: Vec = Vec::new(); @@ -293,13 +293,13 @@ impl PngImage { last_pass = line.pass; } last_line.resize(line.data.len(), 0); - unfilter_line(line.filter, bpp, line.data, &last_line, &mut unfiltered_buf); + unfilter_line(line.filter, bpp, line.data, &last_line, &mut unfiltered_buf)?; unfiltered.push(0); unfiltered.extend_from_slice(&unfiltered_buf); std::mem::swap(&mut last_line, &mut unfiltered_buf); unfiltered_buf.clear(); } - unfiltered + Ok(unfiltered) } /// Apply the specified filter type to all rows in the image From 06e3feeee169d4d0ec9490e6251c6a5e911d1983 Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Sun, 11 Jul 2021 23:10:42 -0400 Subject: [PATCH 48/50] Use separate file for issue_182 test Closes #412 --- tests/files/issue-182.png | Bin 0 -> 71 bytes tests/regression.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tests/files/issue-182.png diff --git a/tests/files/issue-182.png b/tests/files/issue-182.png new file mode 100644 index 0000000000000000000000000000000000000000..10d480005ddd55a1220067a84a00d73a1c5af6a6 GIT binary patch literal 71 zcmeAS@N?(olHy`uVBq!ia0vp^Od!k%Bp7v1F~|dHK2I0N5RU7~83`E)77Pq5#~2U# TTM3;3$}o7k`njxgN@xNAnO_bW literal 0 HcmV?d00001 diff --git a/tests/regression.rs b/tests/regression.rs index f4524c3a..539ec88f 100644 --- a/tests/regression.rs +++ b/tests/regression.rs @@ -611,7 +611,7 @@ fn issue_175() { #[test] fn issue_182() { - let input = "tests/files/issue-175.png"; + let input = "tests/files/issue-182.png"; let (output, mut opts) = get_opts(Path::new(input)); opts.interlace = Some(0); From c4e46b2f3e0763cff3531d93eb4ac684e7fa52fb Mon Sep 17 00:00:00 2001 From: Josh Holmer Date: Sun, 11 Jul 2021 23:12:32 -0400 Subject: [PATCH 49/50] Update npm packages (used for the benchmark script) --- package-lock.json | 1429 +++++++++++++++++++++++++++++++++++++-------- package.json | 2 +- 2 files changed, 1191 insertions(+), 240 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8bf4cf35..f45ccc43 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,386 +1,1337 @@ { "name": "oxipng", "version": "1.0.0", - "lockfileVersion": 1, + "lockfileVersion": 2, "requires": true, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "packages": { + "": { + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "strip-ansi-cli": "^3.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "builtin-modules": { + "node_modules/ansi-regex": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.0.tgz", + "integrity": "sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/function-bind": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/map-obj": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", + "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", + "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.0.tgz", + "integrity": "sha512-UhDTSnGF1dc0DRbUqr1aXwNoY3RgVkSWG8BrpnuFIxhP57IqbS7IRta2Gfiavds4yCxc5+fEAVVOgBZWnYkvzg==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cli": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi-cli/-/strip-ansi-cli-3.0.1.tgz", + "integrity": "sha512-iLTUGQ0XT0QM/MsG5MJzl91C48/NekgP1M5K41rDG+z1zvgsaXgwYnL0i7+a3JixnGmjWsqa9JpFY3q/Zn92Rg==", + "dev": true, + "dependencies": { + "get-stdin": "^9.0.0", + "meow": "^9.0.0", + "strip-ansi": "^7.0.0" + }, + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=12.17" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi-cli?sponsor=1" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "ansi-regex": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.0.tgz", + "integrity": "sha512-tAaOSrWCHF+1Ear1Z4wnJCXA9GGox4K6Ic85a5qalES2aeEwQGr7UC93mwef49536PkCYjzkp0zIxfFvexJ6zQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, "camelcase": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true }, "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { - "array-find-index": "^1.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-stdin": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", + "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", + "dev": true + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true - }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", "dev": true, "requires": { - "repeating": "^2.0.0" + "lru-cache": "^6.0.0" } }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", "dev": true, "requires": { - "builtin-modules": "^1.0.0" + "has": "^1.0.3" } }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", "dev": true }, - "load-json-file": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "p-locate": "^4.1.0" } }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" + "yallist": "^4.0.0" } }, "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.2.1.tgz", + "integrity": "sha512-+WA2/1sPmDj1dlvvJmB5G6JKfY9dpn7EVBUL06+y6PoljPkh+6V1QihwxNkbcGxCRjt2b0F9K0taiCuo7MbdFQ==", "dev": true }, "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "normalize-package-data": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.2.tgz", + "integrity": "sha512-6CdZocmfGaKnIHPVFhJJZ3GuR8SsLKvDANFp47Jmy51aKIr8akjAWTSxtpI+MBgBFdSMRyo4hMpDlT6dTffgZg==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "resolve": "^1.20.0", + "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" } }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "requires": { - "error-ex": "^1.2.0" + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" } }, "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true }, "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } } }, "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } } }, "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" } }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", "dev": true, "requires": { - "is-finite": "^1.0.0" + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" } }, "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", "dev": true, "requires": { - "spdx-license-ids": "^1.0.2" + "lru-cache": "^6.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.9.tgz", + "integrity": "sha512-Ki212dKK4ogX+xDo4CtOZBVIwhsKBEfsEEcwmJfLQzirgc2jIWdzg40Unxz/HzEUqM1WFzVlQSMF9kZZ2HboLQ==", "dev": true }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.0.tgz", + "integrity": "sha512-UhDTSnGF1dc0DRbUqr1aXwNoY3RgVkSWG8BrpnuFIxhP57IqbS7IRta2Gfiavds4yCxc5+fEAVVOgBZWnYkvzg==", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^6.0.0" } }, "strip-ansi-cli": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi-cli/-/strip-ansi-cli-2.0.0.tgz", - "integrity": "sha1-D91Cq86DJTm/cv+ROSpxqzVGIIw=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi-cli/-/strip-ansi-cli-3.0.1.tgz", + "integrity": "sha512-iLTUGQ0XT0QM/MsG5MJzl91C48/NekgP1M5K41rDG+z1zvgsaXgwYnL0i7+a3JixnGmjWsqa9JpFY3q/Zn92Rg==", "dev": true, "requires": { - "meow": "^3.7.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" + "get-stdin": "^9.0.0", + "meow": "^9.0.0", + "strip-ansi": "^7.0.0" } }, "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "min-indent": "^1.0.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" } }, "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", "dev": true }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "spdx-correct": "~1.0.0", - "spdx-expression-parse": "~1.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true } } } diff --git a/package.json b/package.json index 59339f1b..7b2d35f6 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,6 @@ }, "homepage": "https://github.com/shssoichiro/oxipng#readme", "devDependencies": { - "strip-ansi-cli": "^2.0.0" + "strip-ansi-cli": "^3.0.0" } } From 491d753edc4a5e77e99a54327035e5a842498574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= Date: Mon, 12 Jul 2021 05:21:38 +0200 Subject: [PATCH 50/50] Add option to skip grayscale reduction of RGB(A) images (#409) For RGB(A) images that contain gray colors, this reduction can achieve significant space savings. However, in the absence of gamma correction data, some PNG decoders assume more exotic color spaces for grayscale images instead of the ubiquitous sRGB. This results in gamma miscorrection, and for the end user this means that colors will look wrong, like "washed-out". Java's ImageIO class, which is popular in the JVM world to read PNG files, uses rather unconventional defaults, as explained in this StackOverflow question: https://stackoverflow.com/questions/31312645/java-imageio-grayscale-png-issue Gamma miscorrection problems aside, OxiPNG currently tries hard to reduce RGB(A) images to grayscale, because it expects that reduction to be quite effective. However, in some cases, OxiPNG generates smaller PNG files when reducing grasycale RGB(A) images to paletted color than actual grayscale color. For example, let's say that "~/gray.png" is a 256x256 RGBA image entirely filled with (119, 119, 119, 255) pixels. OxiPNG, by default, reduces this image to grayscale and achieves a 68.23% decrease: $ cargo build --release && target/release/oxipng -omax --out ~/out.png ~/gray.png Processing: /home/user/gray.png 256x256 pixels, PNG format 4x8 bits/pixel, RGBA IDAT size = 604 bytes File size = 661 bytes Reducing image to 1x4 bits/pixel, Grayscale Trying: 144 combinations Found better combination: zc = 6 zs = 0 f = 0 153 bytes IDAT size = 153 bytes (451 bytes decrease) file size = 210 bytes (451 bytes = 68.23% decrease) Output: /home/user/out.png However, if the --ng option that this commit adds is used to skip the grayscale reduction step, OxiPNG reduces to a single color palette instead, which is much more efficient, achieving a 84.42% decrease: $ cargo build --release && target/release/oxipng -omax --ng --out ~/out.png ~/gray.png Processing: /home/alejandro/gray.png 256x256 pixels, PNG format 4x8 bits/pixel, RGBA IDAT size = 604 bytes File size = 661 bytes Reducing image to 1 bits/pixel, 1 colors in palette Trying: 144 combinations Found better combination: zc = 3 zs = 3 f = 0 31 bytes IDAT size = 31 bytes (573 bytes decrease) file size = 103 bytes (558 bytes = 84.42% decrease) Output: /home/alejandro/out.png While OxiPNG should arguably be made smarter to better handle these cases, in the meantime, adding an option to manually skip that grayscale reduction can't hurt. In fact, it may even help users achieving the most out of current versions of OxiPNG, and developers reasoning about what makes a grayscale-like RGB(A) image compress better with a color palette. Due to the reasons stated above, this adds a simple "grayscale_reduction" option to the Options struct, and a "no-grayscale-reduction" command line switch, that makes OxiPNG not try this problematic grayscale reduction on RGB(A) images. --- benches/reductions.rs | 20 ++++++++++---------- src/lib.rs | 7 ++++++- src/main.rs | 8 ++++++++ src/reduction/mod.rs | 18 +++++++++++++----- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/benches/reductions.rs b/benches/reductions.rs index e94d8280..30eebe17 100644 --- a/benches/reductions.rs +++ b/benches/reductions.rs @@ -80,7 +80,7 @@ fn reductions_rgba_to_rgb_16(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_16_should_be_rgb_16.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -88,7 +88,7 @@ fn reductions_rgba_to_rgb_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_rgb_8.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -98,7 +98,7 @@ fn reductions_rgba_to_grayscale_alpha_16(b: &mut Bencher) { )); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -108,7 +108,7 @@ fn reductions_rgba_to_grayscale_alpha_8(b: &mut Bencher) { )); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -118,7 +118,7 @@ fn reductions_rgba_to_grayscale_16(b: &mut Bencher) { )); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -128,7 +128,7 @@ fn reductions_rgba_to_grayscale_8(b: &mut Bencher) { )); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -138,7 +138,7 @@ fn reductions_rgb_to_grayscale_16(b: &mut Bencher) { )); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -146,7 +146,7 @@ fn reductions_rgb_to_grayscale_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_grayscale_8.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -154,7 +154,7 @@ fn reductions_rgba_to_palette_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_palette_8.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] @@ -162,7 +162,7 @@ fn reductions_rgb_to_palette_8(b: &mut Bencher) { let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_palette_8.png")); let png = PngData::new(&input, false).unwrap(); - b.iter(|| reduce_color_type(&png.raw)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] diff --git a/src/lib.rs b/src/lib.rs index 0b6fc479..239968de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,6 +169,10 @@ pub struct Options { /// /// Default: `true` pub palette_reduction: bool, + /// Whether to attempt grayscale reduction + /// + /// Default: `true` + pub grayscale_reduction: bool, /// Whether to perform IDAT recoding /// /// If any type of reduction is performed, IDAT recoding will be performed @@ -305,6 +309,7 @@ impl Default for Options { bit_depth_reduction: true, color_type_reduction: true, palette_reduction: true, + grayscale_reduction: true, idat_recoding: true, strip: Headers::None, deflate: Deflaters::Zlib { @@ -741,7 +746,7 @@ fn perform_reductions( } if opts.color_type_reduction { - if let Some(reduced) = reduce_color_type(&png) { + if let Some(reduced) = reduce_color_type(&png, opts.grayscale_reduction) { png = Arc::new(reduced); eval.try_image(png.clone()); report_reduction(&png); diff --git a/src/main.rs b/src/main.rs index 20c8f16b..1a269dd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -184,6 +184,9 @@ fn main() { .arg(Arg::with_name("no-palette-reduction") .help("No palette reduction") .long("np")) + .arg(Arg::with_name("no-grayscale-reduction") + .help("No grayscale reduction") + .long("ng")) .arg(Arg::with_name("no-reductions") .help("No reductions") .long("nx")) @@ -433,10 +436,15 @@ fn parse_opts_into_struct( opts.palette_reduction = false; } + if matches.is_present("no-grayscale-reduction") { + opts.grayscale_reduction = false; + } + if matches.is_present("no-reductions") { opts.bit_depth_reduction = false; opts.color_type_reduction = false; opts.palette_reduction = false; + opts.grayscale_reduction = false; } if matches.is_present("no-recoding") { diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index e6f4bf7d..6b89b839 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -185,15 +185,19 @@ fn reordered_palette(palette: &[RGBA8], palette_map: &[Option; 256]) -> Vec< /// Attempt to reduce the color type of the image /// Returns true if the color type was reduced, false otherwise -pub fn reduce_color_type(png: &PngImage) -> Option { +pub fn reduce_color_type(png: &PngImage, grayscale_reduction: bool) -> Option { let mut should_reduce_bit_depth = false; let mut reduced = Cow::Borrowed(png); // Go down one step at a time // Maybe not the most efficient, but it's safe if reduced.ihdr.color_type == ColorType::RGBA { - if let Some(r) = - reduce_rgba_to_grayscale_alpha(&reduced).or_else(|| reduced_alpha_channel(&reduced)) + if let Some(r) = if grayscale_reduction { + reduce_rgba_to_grayscale_alpha(&reduced) + } else { + None + } + .or_else(|| reduced_alpha_channel(&reduced)) { reduced = Cow::Owned(r); } else if let Some(r) = reduced_color_to_palette(&reduced) { @@ -210,8 +214,12 @@ pub fn reduce_color_type(png: &PngImage) -> Option { } if reduced.ihdr.color_type == ColorType::RGB { - if let Some(r) = - reduce_rgb_to_grayscale(&reduced).or_else(|| reduced_color_to_palette(&reduced)) + if let Some(r) = if grayscale_reduction { + reduce_rgb_to_grayscale(&reduced) + } else { + None + } + .or_else(|| reduced_color_to_palette(&reduced)) { reduced = Cow::Owned(r); should_reduce_bit_depth = true;