Switch to standard logging library (#218)
This allows to configure or compile away logging in the library from a single place in Rust apps. For the CLI side, the usage and output remained the same, except it's now colour-coded. Fixes #217.
This commit is contained in:
parent
3b754bfa09
commit
23ae9c302f
12 changed files with 353 additions and 332 deletions
136
Cargo.lock
generated
136
Cargo.lock
generated
|
|
@ -15,11 +15,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
|
@ -63,13 +63,23 @@ name = "cfg-if"
|
|||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "2.33.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
@ -217,6 +227,11 @@ dependencies = [
|
|||
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
|
|
@ -235,6 +250,14 @@ dependencies = [
|
|||
"cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "maybe-uninit"
|
||||
version = "2.0.0"
|
||||
|
|
@ -302,6 +325,11 @@ dependencies = [
|
|||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "numtoa"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "oxipng"
|
||||
version = "2.3.0"
|
||||
|
|
@ -315,9 +343,11 @@ dependencies = [
|
|||
"indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libdeflater 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rgb 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"stderrlog 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wild 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"zopfli 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
|
@ -355,6 +385,19 @@ dependencies = [
|
|||
"num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "redox_termios"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rgb"
|
||||
version = "0.8.16"
|
||||
|
|
@ -386,11 +429,42 @@ name = "semver-parser"
|
|||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "stderrlog"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "termcolor"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termion"
|
||||
version = "1.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.11.0"
|
||||
|
|
@ -399,6 +473,25 @@ dependencies = [
|
|||
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "1.7.0"
|
||||
|
|
@ -409,11 +502,24 @@ name = "unicode-width"
|
|||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "wild"
|
||||
version = "2.0.2"
|
||||
|
|
@ -436,6 +542,14 @@ name = "winapi-i686-pc-windows-gnu"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-util"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
|
|
@ -455,7 +569,7 @@ dependencies = [
|
|||
[metadata]
|
||||
"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
||||
"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652"
|
||||
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||
"checksum bit-vec 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a4523a10839ffae575fb08aa3423026c8cb4687eef43952afb956229d4f246f7"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
|
|
@ -464,6 +578,7 @@ dependencies = [
|
|||
"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum cloudflare-zlib 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f5ed63a019d55bacd15cadcbcb96bf41b16281417fff393bdb55fa84255fe4b9"
|
||||
"checksum cloudflare-zlib-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7e195cb274a0d6ee87e718838a09baecd7cbc9f6075dac256a84cb5842739c06"
|
||||
|
|
@ -481,9 +596,11 @@ dependencies = [
|
|||
"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292"
|
||||
"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
|
||||
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
|
||||
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018"
|
||||
"checksum libdeflater 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "66dca08b13369865b2f6dca1dd05f833985cbe6c12a676b04d55f78b85e80246"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||
"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9"
|
||||
"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5"
|
||||
|
|
@ -492,21 +609,32 @@ dependencies = [
|
|||
"checksum num-rational 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "da4dc79f9e6c81bef96148c8f6b8e72ad4541caa4a24373e900a36da07de03a3"
|
||||
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
|
||||
"checksum num_cpus 1.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
|
||||
"checksum png 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "46060468187c21c00ffa2a920690b29997d7fd543f5a4d400461e4a7d4fccde8"
|
||||
"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098"
|
||||
"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9"
|
||||
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum rgb 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)" = "5ec4ab2cf0b27e111e266e161cf7f9efd20125a161190da1c0945c4a4408fef3"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum stderrlog 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "32e5ee9b90a5452c570a0b0ac1c99ae9498db7e56e33d74366de7f2a7add7f25"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
|
||||
"checksum termion 1.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c22cec9d8978d906be5ac94bceb5a010d885c626c4c8855721a4dbd20e3ac905"
|
||||
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
|
||||
"checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
"checksum typed-arena 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b2228007eba4120145f785df0f6c92ea538f5a3635a612ecf4e334c8c1446d"
|
||||
"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
|
||||
"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
"checksum wild 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "97d34fecce28871e5c0e059deae21ef7f7d13b98a5964b24c58b3735c8052fc8"
|
||||
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
|
||||
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
"checksum winapi-util 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fa515c5163a99cc82bab70fd3bfdd36d827be85de63737b40fcef2ce084a436e"
|
||||
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
"checksum zopfli 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4079b79464426ade2a1b0177fb0ce8396ba6b4084267407e333573c666073964"
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ miniz_oxide = "0.3"
|
|||
rgb = "0.8.11"
|
||||
indexmap = { version = "1.3.2", features = ["rayon"] }
|
||||
libdeflater = "0.2.0"
|
||||
log = "0.4.8"
|
||||
stderrlog = { version = "0.4.3", optional = true }
|
||||
|
||||
[dependencies.rayon]
|
||||
optional = true
|
||||
|
|
@ -50,18 +52,19 @@ version = "^2.10.0"
|
|||
optional = true
|
||||
version = "2.0.0"
|
||||
|
||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
||||
cloudflare-zlib = "^0.2.2"
|
||||
|
||||
[dependencies.image]
|
||||
default-features = false
|
||||
features = ["png"]
|
||||
version = "0.23"
|
||||
|
||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
||||
cloudflare-zlib = "^0.2.2"
|
||||
|
||||
[features]
|
||||
binary = [
|
||||
"clap",
|
||||
"wild",
|
||||
"stderrlog",
|
||||
]
|
||||
default = ["binary", "parallel"]
|
||||
parallel = ["rayon"]
|
||||
|
|
|
|||
|
|
@ -16,14 +16,7 @@ fn deflate_16_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
0,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 0, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -34,14 +27,7 @@ fn deflate_8_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
0,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 0, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -54,14 +40,7 @@ fn deflate_4_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
0,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 0, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -74,14 +53,7 @@ fn deflate_2_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
0,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 0, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -94,14 +66,7 @@ fn deflate_1_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
0,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 0, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -112,14 +77,7 @@ fn deflate_16_bits_strategy_1(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
1,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 1, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -130,14 +88,7 @@ fn deflate_8_bits_strategy_1(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
1,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 1, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -150,14 +101,7 @@ fn deflate_4_bits_strategy_1(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
1,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 1, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -170,14 +114,7 @@ fn deflate_2_bits_strategy_1(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
1,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 1, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -190,14 +127,7 @@ fn deflate_1_bits_strategy_1(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
1,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 1, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -208,14 +138,7 @@ fn deflate_16_bits_strategy_2(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
2,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 2, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -226,14 +149,7 @@ fn deflate_8_bits_strategy_2(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
2,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 2, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -246,14 +162,7 @@ fn deflate_4_bits_strategy_2(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
2,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 2, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -266,14 +175,7 @@ fn deflate_2_bits_strategy_2(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
2,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 2, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -286,14 +188,7 @@ fn deflate_1_bits_strategy_2(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
2,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 2, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -304,14 +199,7 @@ fn deflate_16_bits_strategy_3(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
3,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 3, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -322,14 +210,7 @@ fn deflate_8_bits_strategy_3(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
3,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 3, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -342,14 +223,7 @@ fn deflate_4_bits_strategy_3(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
3,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 3, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -362,14 +236,7 @@ fn deflate_2_bits_strategy_3(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
3,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 3, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -382,14 +249,7 @@ fn deflate_1_bits_strategy_3(b: &mut Bencher) {
|
|||
|
||||
b.iter(|| {
|
||||
let min = AtomicMin::new(None);
|
||||
deflate(
|
||||
png.raw.data.as_ref(),
|
||||
9,
|
||||
3,
|
||||
15,
|
||||
&min,
|
||||
&Deadline::new(None, false),
|
||||
)
|
||||
deflate(png.raw.data.as_ref(), 9, 3, 15, &min, &Deadline::new(None))
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ fn compress_test() {
|
|||
Z_DEFAULT_STRATEGY as u8,
|
||||
15,
|
||||
&AtomicMin::new(None),
|
||||
&Deadline::new(None, false),
|
||||
&Deadline::new(None),
|
||||
)
|
||||
.unwrap();
|
||||
let res = crate::deflate::inflate(&vec).unwrap();
|
||||
|
|
|
|||
217
src/lib.rs
217
src/lib.rs
|
|
@ -27,6 +27,7 @@ use crate::png::PngImage;
|
|||
use crate::reduction::*;
|
||||
use crc::crc32;
|
||||
use image::{DynamicImage, GenericImageView, ImageFormat, Pixel};
|
||||
use log::{debug, error, info, warn};
|
||||
use rayon::prelude::*;
|
||||
use std::fmt;
|
||||
use std::fs::{copy, File};
|
||||
|
|
@ -139,10 +140,6 @@ pub struct Options {
|
|||
///
|
||||
/// Default: `false`
|
||||
pub preserve_attrs: bool,
|
||||
/// How verbose the console logging should be (`None` for quiet, `Some(0)` for normal, `Some(1)` for verbose)
|
||||
///
|
||||
/// Default: `Some(0)`
|
||||
pub verbosity: Option<u8>,
|
||||
/// Which filters to try on the file (0-5)
|
||||
///
|
||||
/// Default: `0,5`
|
||||
|
|
@ -289,7 +286,6 @@ impl Default for Options {
|
|||
fix_errors: false,
|
||||
force: false,
|
||||
preserve_attrs: false,
|
||||
verbosity: Some(0),
|
||||
filter,
|
||||
interlace: None,
|
||||
alphas,
|
||||
|
|
@ -312,11 +308,9 @@ impl Default for Options {
|
|||
/// Perform optimization on the input file using the options provided
|
||||
pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<()> {
|
||||
// Read in the file and try to decode as PNG.
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!("Processing: {}", input);
|
||||
}
|
||||
info!("Processing: {}", input);
|
||||
|
||||
let deadline = Arc::new(Deadline::new(opts.timeout, opts.verbosity.is_some()));
|
||||
let deadline = Arc::new(Deadline::new(opts.timeout));
|
||||
|
||||
let in_data = match *input {
|
||||
InFile::Path(ref input_path) => PngData::read_file(input_path)?,
|
||||
|
|
@ -335,9 +329,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
|||
let mut optimized_output = optimize_png(&mut png, &in_data, opts, deadline)?;
|
||||
|
||||
if is_fully_optimized(in_data.len(), optimized_output.len(), opts) {
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!("File already optimized");
|
||||
}
|
||||
info!("File already optimized");
|
||||
match (output, input) {
|
||||
// if p is None, it also means same as the input path
|
||||
(&OutFile::Path(ref p), &InFile::Path(ref input_path))
|
||||
|
|
@ -352,9 +344,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
|||
}
|
||||
|
||||
if opts.pretend {
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!("Running in pretend mode, no output");
|
||||
}
|
||||
info!("Running in pretend mode, no output");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
|
|
@ -382,7 +372,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
|||
})?;
|
||||
if opts.preserve_attrs {
|
||||
if let Some(input_path) = input.path() {
|
||||
copy_permissions(input_path, &out_file, opts.verbosity);
|
||||
copy_permissions(input_path, &out_file);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -394,9 +384,7 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
|||
e
|
||||
))
|
||||
})?;
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!("Output: {}", output_path.display());
|
||||
}
|
||||
info!("Output: {}", output_path.display());
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -406,11 +394,9 @@ pub fn optimize(input: &InFile, output: &OutFile, opts: &Options) -> PngResult<(
|
|||
/// loaded in-memory
|
||||
pub fn optimize_from_memory(data: &[u8], opts: &Options) -> PngResult<Vec<u8>> {
|
||||
// Read in the file and try to decode as PNG.
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!("Processing from memory");
|
||||
}
|
||||
info!("Processing from memory");
|
||||
|
||||
let deadline = Arc::new(Deadline::new(opts.timeout, opts.verbosity.is_some()));
|
||||
let deadline = Arc::new(Deadline::new(opts.timeout));
|
||||
|
||||
let original_size = data.len();
|
||||
let mut png = PngData::from_slice(data, opts.fix_errors)?;
|
||||
|
|
@ -419,7 +405,7 @@ pub fn optimize_from_memory(data: &[u8], opts: &Options) -> PngResult<Vec<u8>> {
|
|||
let optimized_output = optimize_png(&mut png, data, opts, deadline)?;
|
||||
|
||||
if is_fully_optimized(original_size, optimized_output.len(), opts) {
|
||||
eprintln!("Image already optimized");
|
||||
info!("Image already optimized");
|
||||
Ok(data.to_vec())
|
||||
} else {
|
||||
Ok(optimized_output)
|
||||
|
|
@ -448,28 +434,26 @@ fn optimize_png(
|
|||
// Print png info
|
||||
let file_original_size = original_data.len();
|
||||
let idat_original_size = png.idat_data.len();
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!(
|
||||
" {}x{} pixels, PNG format",
|
||||
png.raw.ihdr.width, png.raw.ihdr.height
|
||||
info!(
|
||||
" {}x{} pixels, PNG format",
|
||||
png.raw.ihdr.width, png.raw.ihdr.height
|
||||
);
|
||||
if let Some(ref palette) = png.raw.palette {
|
||||
info!(
|
||||
" {} bits/pixel, {} colors in palette",
|
||||
png.raw.ihdr.bit_depth,
|
||||
palette.len()
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
" {}x{} bits/pixel, {:?}",
|
||||
png.raw.channels_per_pixel(),
|
||||
png.raw.ihdr.bit_depth,
|
||||
png.raw.ihdr.color_type
|
||||
);
|
||||
if let Some(ref palette) = png.raw.palette {
|
||||
eprintln!(
|
||||
" {} bits/pixel, {} colors in palette",
|
||||
png.raw.ihdr.bit_depth,
|
||||
palette.len()
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
" {}x{} bits/pixel, {:?}",
|
||||
png.raw.channels_per_pixel(),
|
||||
png.raw.ihdr.bit_depth,
|
||||
png.raw.ihdr.color_type
|
||||
);
|
||||
}
|
||||
eprintln!(" IDAT size = {} bytes", idat_original_size);
|
||||
eprintln!(" File size = {} bytes", file_original_size);
|
||||
}
|
||||
info!(" IDAT size = {} bytes", idat_original_size);
|
||||
info!(" File size = {} bytes", file_original_size);
|
||||
|
||||
let mut filter = opts.filter.clone();
|
||||
let mut strategies = match &opts.deflate {
|
||||
|
|
@ -548,9 +532,7 @@ fn optimize_png(
|
|||
}
|
||||
}
|
||||
|
||||
if opts.verbosity.is_some() {
|
||||
eprintln!("Trying: {} combinations", results.len());
|
||||
}
|
||||
info!("Trying: {} combinations", results.len());
|
||||
|
||||
let filters: IndexMap<u8, Vec<u8>> = filter
|
||||
.par_iter()
|
||||
|
|
@ -586,8 +568,8 @@ fn optimize_png(
|
|||
|
||||
let new_idat = match new_idat {
|
||||
Ok(n) => n,
|
||||
Err(PngError::DeflatedDataTooLong(max)) if opts.verbosity == Some(1) => {
|
||||
eprintln!(
|
||||
Err(PngError::DeflatedDataTooLong(max)) => {
|
||||
debug!(
|
||||
" zc = {} zs = {} f = {} >{} bytes",
|
||||
trial.compression, trial.strategy, trial.filter, max,
|
||||
);
|
||||
|
|
@ -600,15 +582,13 @@ fn optimize_png(
|
|||
let new_size = new_idat.len();
|
||||
best_size.set_min(new_size);
|
||||
|
||||
if opts.verbosity == Some(1) {
|
||||
eprintln!(
|
||||
" zc = {} zs = {} f = {} {} bytes",
|
||||
trial.compression,
|
||||
trial.strategy,
|
||||
trial.filter,
|
||||
new_idat.len()
|
||||
);
|
||||
}
|
||||
debug!(
|
||||
" zc = {} zs = {} f = {} {} bytes",
|
||||
trial.compression,
|
||||
trial.strategy,
|
||||
trial.filter,
|
||||
new_idat.len()
|
||||
);
|
||||
|
||||
if new_size < original_len || added_interlacing || opts.force {
|
||||
Some((trial, new_idat))
|
||||
|
|
@ -624,19 +604,16 @@ fn optimize_png(
|
|||
}
|
||||
});
|
||||
|
||||
if let Some(better) = best {
|
||||
png.idat_data = better.1;
|
||||
if opts.verbosity.is_some() {
|
||||
let opts = better.0;
|
||||
eprintln!("Found better combination:");
|
||||
eprintln!(
|
||||
" zc = {} zs = {} f = {} {} bytes",
|
||||
opts.compression,
|
||||
opts.strategy,
|
||||
opts.filter,
|
||||
png.idat_data.len()
|
||||
);
|
||||
}
|
||||
if let Some((opts, idat_data)) = best {
|
||||
png.idat_data = idat_data;
|
||||
info!("Found better combination:");
|
||||
info!(
|
||||
" zc = {} zs = {} f = {} {} bytes",
|
||||
opts.compression,
|
||||
opts.strategy,
|
||||
opts.filter,
|
||||
png.idat_data.len()
|
||||
);
|
||||
} else if reduction_occurred {
|
||||
*png = original_png;
|
||||
}
|
||||
|
|
@ -646,35 +623,33 @@ fn optimize_png(
|
|||
|
||||
let output = png.output();
|
||||
|
||||
if opts.verbosity.is_some() {
|
||||
if idat_original_size >= png.idat_data.len() {
|
||||
eprintln!(
|
||||
" IDAT size = {} bytes ({} bytes decrease)",
|
||||
png.idat_data.len(),
|
||||
idat_original_size - png.idat_data.len()
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
" IDAT size = {} bytes ({} bytes increase)",
|
||||
png.idat_data.len(),
|
||||
png.idat_data.len() - idat_original_size
|
||||
);
|
||||
}
|
||||
if file_original_size >= output.len() {
|
||||
eprintln!(
|
||||
" 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
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
" 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
|
||||
);
|
||||
}
|
||||
if idat_original_size >= png.idat_data.len() {
|
||||
info!(
|
||||
" IDAT size = {} bytes ({} bytes decrease)",
|
||||
png.idat_data.len(),
|
||||
idat_original_size - png.idat_data.len()
|
||||
);
|
||||
} else {
|
||||
info!(
|
||||
" IDAT size = {} bytes ({} bytes increase)",
|
||||
png.idat_data.len(),
|
||||
png.idat_data.len() - idat_original_size
|
||||
);
|
||||
}
|
||||
if file_original_size >= output.len() {
|
||||
info!(
|
||||
" 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
|
||||
);
|
||||
} 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
|
||||
);
|
||||
}
|
||||
|
||||
let (old_png, new_png) = rayon::join(
|
||||
|
|
@ -695,7 +670,7 @@ fn optimize_png(
|
|||
}
|
||||
}
|
||||
|
||||
eprintln!(
|
||||
error!(
|
||||
"The resulting image is corrupted and will not be outputted.\nThis is a bug! Please report it at https://github.com/shssoichiro/oxipng/issues"
|
||||
);
|
||||
Err(PngError::new("The resulting image is corrupted"))
|
||||
|
|
@ -722,9 +697,7 @@ fn perform_reductions(
|
|||
if let Some(reduced) = reduced_palette(&png) {
|
||||
png = Arc::new(reduced);
|
||||
eval.try_image(png.clone());
|
||||
if opts.verbosity == Some(1) {
|
||||
report_reduction(&png);
|
||||
}
|
||||
report_reduction(&png);
|
||||
}
|
||||
if deadline.passed() {
|
||||
return;
|
||||
|
|
@ -745,9 +718,7 @@ fn perform_reductions(
|
|||
eval.try_image(Arc::new(reduced));
|
||||
}
|
||||
}
|
||||
if opts.verbosity == Some(1) {
|
||||
report_reduction(&png);
|
||||
}
|
||||
report_reduction(&png);
|
||||
}
|
||||
if deadline.passed() {
|
||||
return;
|
||||
|
|
@ -758,9 +729,7 @@ fn perform_reductions(
|
|||
if let Some(reduced) = reduce_color_type(&png) {
|
||||
png = Arc::new(reduced);
|
||||
eval.try_image(png.clone());
|
||||
if opts.verbosity == Some(1) {
|
||||
report_reduction(&png);
|
||||
}
|
||||
report_reduction(&png);
|
||||
}
|
||||
if deadline.passed() {
|
||||
return;
|
||||
|
|
@ -785,12 +754,12 @@ pub struct Deadline {
|
|||
}
|
||||
|
||||
impl Deadline {
|
||||
pub fn new(timeout: Option<Duration>, verbose: bool) -> Self {
|
||||
pub fn new(timeout: Option<Duration>) -> Self {
|
||||
Self {
|
||||
imp: timeout.map(|timeout| DeadlineImp {
|
||||
start: Instant::now(),
|
||||
timeout,
|
||||
print_message: AtomicBool::new(verbose),
|
||||
print_message: AtomicBool::new(true),
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
@ -802,9 +771,11 @@ impl Deadline {
|
|||
if let Some(imp) = &self.imp {
|
||||
let elapsed = imp.start.elapsed();
|
||||
if elapsed > imp.timeout {
|
||||
if imp.print_message.load(Ordering::Relaxed) {
|
||||
imp.print_message.store(false, Ordering::Relaxed);
|
||||
eprintln!("Timed out after {} second(s)", elapsed.as_secs());
|
||||
if imp
|
||||
.print_message
|
||||
.compare_and_swap(true, false, Ordering::SeqCst)
|
||||
{
|
||||
warn!("Timed out after {} second(s)", elapsed.as_secs());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -816,13 +787,13 @@ impl Deadline {
|
|||
/// Display the status of the image data after a reduction has taken place
|
||||
fn report_reduction(png: &PngImage) {
|
||||
if let Some(ref palette) = png.palette {
|
||||
eprintln!(
|
||||
info!(
|
||||
"Reducing image to {} bits/pixel, {} colors in palette",
|
||||
png.ihdr.bit_depth,
|
||||
palette.len()
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
info!(
|
||||
"Reducing image to {}x{} bits/pixel, {}",
|
||||
png.channels_per_pixel(),
|
||||
png.ihdr.bit_depth,
|
||||
|
|
@ -947,7 +918,7 @@ fn perform_backup(input_path: &Path) -> PngResult<()> {
|
|||
}
|
||||
|
||||
#[cfg(not(unix))]
|
||||
fn copy_permissions(input_path: &Path, out_file: &File, verbosity: Option<u8>) {
|
||||
fn copy_permissions(input_path: &Path, out_file: &File) {
|
||||
if let Ok(f) = File::open(input_path) {
|
||||
if let Ok(metadata) = f.metadata() {
|
||||
if let Ok(out_meta) = out_file.metadata() {
|
||||
|
|
@ -957,13 +928,11 @@ fn copy_permissions(input_path: &Path, out_file: &File, verbosity: Option<u8>) {
|
|||
}
|
||||
}
|
||||
};
|
||||
if verbosity.is_some() {
|
||||
eprintln!("Failed to set permissions on output file");
|
||||
}
|
||||
warn!("Failed to set permissions on output file");
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn copy_permissions(input_path: &Path, out_file: &File, verbosity: Option<u8>) {
|
||||
fn copy_permissions(input_path: &Path, out_file: &File) {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
if let Ok(f) = File::open(input_path) {
|
||||
|
|
@ -975,9 +944,7 @@ fn copy_permissions(input_path: &Path, out_file: &File, verbosity: Option<u8>) {
|
|||
}
|
||||
}
|
||||
};
|
||||
if verbosity.is_some() {
|
||||
eprintln!("Failed to set permissions on output file");
|
||||
}
|
||||
warn!("Failed to set permissions on output file");
|
||||
}
|
||||
|
||||
/// Compares images pixel by pixel for equivalent content
|
||||
|
|
|
|||
21
src/main.rs
21
src/main.rs
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||
use indexmap::IndexSet;
|
||||
use log::{error, warn};
|
||||
use oxipng::AlphaOptim;
|
||||
use oxipng::Deflaters;
|
||||
use oxipng::Headers;
|
||||
|
|
@ -241,7 +242,7 @@ fn main() {
|
|||
let (out_file, out_dir, opts) = match parse_opts_into_struct(&matches) {
|
||||
Ok(x) => x,
|
||||
Err(x) => {
|
||||
eprintln!("{}", x);
|
||||
error!("{}", x);
|
||||
exit(1)
|
||||
}
|
||||
};
|
||||
|
|
@ -264,7 +265,7 @@ fn main() {
|
|||
.collect();
|
||||
|
||||
if let Err(e) = res {
|
||||
eprintln!("{}", e);
|
||||
error!("{}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -289,7 +290,7 @@ fn collect_files(
|
|||
.collect();
|
||||
in_out_pairs.extend(collect_files(files, out_dir, out_file, recursive, false));
|
||||
} else {
|
||||
eprintln!("{} is a directory, skipping", input.display());
|
||||
warn!("{} is a directory, skipping", input.display());
|
||||
}
|
||||
continue;
|
||||
};
|
||||
|
|
@ -396,13 +397,13 @@ fn parse_opts_into_struct(
|
|||
opts.preserve_attrs = true;
|
||||
}
|
||||
|
||||
if matches.is_present("quiet") {
|
||||
opts.verbosity = None;
|
||||
}
|
||||
|
||||
if matches.is_present("verbose") {
|
||||
opts.verbosity = Some(1);
|
||||
}
|
||||
stderrlog::new()
|
||||
.module(module_path!())
|
||||
.quiet(matches.is_present("quiet"))
|
||||
.verbosity(if matches.is_present("verbose") { 3 } else { 2 })
|
||||
.show_level(false)
|
||||
.init()
|
||||
.unwrap();
|
||||
|
||||
if matches.is_present("no-bit-reduction") {
|
||||
opts.bit_depth_reduction = false;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::path::PathBuf;
|
|||
|
||||
fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = IndexSet::new();
|
||||
filter.insert(0);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::path::PathBuf;
|
|||
|
||||
fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = IndexSet::new();
|
||||
filter.insert(0);
|
||||
|
|
@ -56,19 +55,92 @@ fn test_it_converts(
|
|||
|
||||
#[test]
|
||||
fn verbose_mode() {
|
||||
let input = PathBuf::from("tests/files/verbose_mode.png");
|
||||
let (output, mut opts) = get_opts(&input);
|
||||
opts.verbosity = Some(1);
|
||||
use log::{set_logger, set_max_level, Level, LevelFilter, Log, Metadata, Record};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::mpsc::{sync_channel, SyncSender};
|
||||
|
||||
test_it_converts(
|
||||
input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
// Rust runs tests in parallel by default.
|
||||
// We want to make sure that we verify only logs from our test.
|
||||
//
|
||||
// For that, we store an Option in a thread-local variable and
|
||||
// initialise it with Some(sender) only on threads spawned within
|
||||
// our test.
|
||||
thread_local! {
|
||||
static VERBOSE_LOGS: RefCell<Option<SyncSender<String>>> = RefCell::new(None);
|
||||
}
|
||||
|
||||
struct LogTester;
|
||||
|
||||
impl Log for LogTester {
|
||||
fn enabled(&self, metadata: &Metadata) -> bool {
|
||||
metadata.level() <= Level::Debug
|
||||
}
|
||||
|
||||
fn log(&self, record: &Record) {
|
||||
if record.level() == Level::Debug {
|
||||
VERBOSE_LOGS.with(|logs| {
|
||||
// If current thread has a storage for logs, add our line.
|
||||
// Otherwise our handler is invoked from an unrelated test.
|
||||
if let Some(logs) = logs.borrow().as_ref() {
|
||||
logs.send(record.args().to_string()).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn flush(&self) {}
|
||||
}
|
||||
|
||||
set_logger(&LogTester).unwrap();
|
||||
set_max_level(LevelFilter::Debug);
|
||||
|
||||
let input = PathBuf::from("tests/files/verbose_mode.png");
|
||||
let (output, opts) = get_opts(&input);
|
||||
|
||||
let (sender, receiver) = sync_channel(4);
|
||||
|
||||
let thread_init = move || {
|
||||
// Initialise logs storage for all threads within our test.
|
||||
VERBOSE_LOGS.with(|logs| *logs.borrow_mut() = Some(sender.clone()));
|
||||
};
|
||||
let thread_exec = move || {
|
||||
test_it_converts(
|
||||
input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
};
|
||||
|
||||
#[cfg(feature = "rayon")]
|
||||
rayon::ThreadPoolBuilder::new()
|
||||
.start_handler(move |_| thread_init())
|
||||
.build()
|
||||
.unwrap()
|
||||
.install(move || rayon::spawn(thread_exec));
|
||||
|
||||
#[cfg(not(feature = "rayon"))]
|
||||
std::thread::spawn(move || {
|
||||
thread_init();
|
||||
thread_exec();
|
||||
});
|
||||
|
||||
let mut logs: Vec<_> = receiver.into_iter().collect();
|
||||
assert_eq!(logs.len(), 4);
|
||||
logs.sort();
|
||||
for (i, log) in logs.into_iter().enumerate() {
|
||||
let expected_prefix = format!(" zc = 9 zs = {} f = 0 ", i);
|
||||
assert!(
|
||||
log.starts_with(&expected_prefix),
|
||||
"logs[{}] = {:?} doesn't start with {:?}",
|
||||
i,
|
||||
log,
|
||||
expected_prefix
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::path::PathBuf;
|
|||
|
||||
fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = IndexSet::new();
|
||||
filter.insert(0);
|
||||
|
|
|
|||
18
tests/lib.rs
18
tests/lib.rs
|
|
@ -13,8 +13,7 @@ fn optimize_from_memory() {
|
|||
let mut in_file_buf: Vec<u8> = Vec::new();
|
||||
in_file.read_to_end(&mut in_file_buf).unwrap();
|
||||
|
||||
let mut opts: oxipng::Options = Default::default();
|
||||
opts.verbosity = Some(1);
|
||||
let opts: oxipng::Options = Default::default();
|
||||
|
||||
let result = oxipng::optimize_from_memory(&in_file_buf, &opts);
|
||||
assert!(result.is_ok());
|
||||
|
|
@ -26,8 +25,7 @@ fn optimize_from_memory_corrupted() {
|
|||
let mut in_file_buf: Vec<u8> = Vec::new();
|
||||
in_file.read_to_end(&mut in_file_buf).unwrap();
|
||||
|
||||
let mut opts: oxipng::Options = Default::default();
|
||||
opts.verbosity = Some(1);
|
||||
let opts: oxipng::Options = Default::default();
|
||||
|
||||
let result = oxipng::optimize_from_memory(&in_file_buf, &opts);
|
||||
assert!(result.is_err());
|
||||
|
|
@ -39,8 +37,7 @@ fn optimize_from_memory_apng() {
|
|||
let mut in_file_buf: Vec<u8> = Vec::new();
|
||||
in_file.read_to_end(&mut in_file_buf).unwrap();
|
||||
|
||||
let mut opts: oxipng::Options = Default::default();
|
||||
opts.verbosity = Some(1);
|
||||
let opts: oxipng::Options = Default::default();
|
||||
|
||||
let result = oxipng::optimize_from_memory(&in_file_buf, &opts);
|
||||
assert!(result.is_err());
|
||||
|
|
@ -48,8 +45,7 @@ fn optimize_from_memory_apng() {
|
|||
|
||||
#[test]
|
||||
fn optimize() {
|
||||
let mut opts: oxipng::Options = Default::default();
|
||||
opts.verbosity = Some(1);
|
||||
let opts: oxipng::Options = Default::default();
|
||||
|
||||
let result = oxipng::optimize(
|
||||
&"tests/files/fully_optimized.png".into(),
|
||||
|
|
@ -61,8 +57,7 @@ fn optimize() {
|
|||
|
||||
#[test]
|
||||
fn optimize_corrupted() {
|
||||
let mut opts: oxipng::Options = Default::default();
|
||||
opts.verbosity = Some(1);
|
||||
let opts: oxipng::Options = Default::default();
|
||||
|
||||
let result = oxipng::optimize(
|
||||
&"tests/files/corrupted_header.png".into(),
|
||||
|
|
@ -74,8 +69,7 @@ fn optimize_corrupted() {
|
|||
|
||||
#[test]
|
||||
fn optimize_apng() {
|
||||
let mut opts: oxipng::Options = Default::default();
|
||||
opts.verbosity = Some(1);
|
||||
let opts: oxipng::Options = Default::default();
|
||||
|
||||
let result = oxipng::optimize(
|
||||
&"tests/files/apng_file.png".into(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::path::PathBuf;
|
|||
|
||||
fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = IndexSet::new();
|
||||
filter.insert(0);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ use std::path::PathBuf;
|
|||
|
||||
fn get_opts(input: &Path) -> (OutFile, oxipng::Options) {
|
||||
let mut options = oxipng::Options::default();
|
||||
options.verbosity = None;
|
||||
options.force = true;
|
||||
let mut filter = IndexSet::new();
|
||||
filter.insert(0);
|
||||
|
|
|
|||
Loading…
Reference in a new issue