diff --git a/Cargo.lock b/Cargo.lock index bb5779f..817ad3a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,559 +1,327 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adler32" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" [[package]] -name = "ansi_term" -version = "0.11.0" -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 = "atty" -version = "0.2.13" +name = "autocfg" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" -version = "0.1.7" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bytemuck" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439989e6b8c38d1b6570a384ef1e49c8848128f5a97f3914baef02920842712f" [[package]] name = "byteorder" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (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)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "textwrap", + "unicode-width", ] [[package]] name = "color_quant" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.1" -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)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "deflate" -version = "0.7.20" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" dependencies = [ - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "either" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "gif" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", + "byteorder", ] [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ - "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "hermit-abi" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" dependencies = [ - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "image" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "gif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)", - "jpeg-decoder 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "png 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "inflate" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "jpeg-decoder" -version = "0.1.16" +version = "0.23.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytemuck", + "byteorder", + "color_quant", + "num-iter", + "num-rational", + "num-traits", + "png", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" version = "0.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" [[package]] -name = "lzw" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.5.3" +name = "miniz_oxide" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", ] [[package]] name = "multiman" -version = "0.1.0" +version = "0.2.0" dependencies = [ - "image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "image", + "num-complex", + "num_cpus", + "structopt", ] [[package]] name = "num-complex" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-derive" -version = "0.2.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits", ] [[package]] name = "num-integer" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "num-traits", ] [[package]] name = "num-iter" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "num-integer", + "num-traits", ] [[package]] name = "num-rational" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", + "num-integer", + "num-traits", ] [[package]] name = "num-traits" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.1", ] [[package]] name = "num_cpus" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ - "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] [[package]] name = "png" -version = "0.15.1" +version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)", - "inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide", ] [[package]] name = "proc-macro-error" -version = "0.2.6" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", ] [[package]] -name = "proc-macro2" -version = "0.4.30" +name = "proc-macro-error-attr" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "version_check", ] [[package]] name = "proc-macro2" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid", ] [[package]] name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rayon-core" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", ] -[[package]] -name = "scoped_threadpool" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "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 = "structopt" -version = "0.3.3" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "lazy_static", + "structopt-derive", ] [[package]] name = "structopt-derive" -version = "0.3.3" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "syn" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tiff" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "unicode-segmentation" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" [[package]] name = "unicode-width" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] -name = "vec_map" -version = "0.8.1" +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[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.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum color_quant 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -"checksum deflate 0.7.20 (registry+https://github.com/rust-lang/crates.io-index)" = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum gif 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" -"checksum image 0.22.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4be8aaefbe7545dc42ae925afb55a0098f226a3fe5ef721872806f44f57826" -"checksum inflate 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff" -"checksum jpeg-decoder 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "c1aae18ffeeae409c6622c3b6a7ee49792a7e5a062eea1b135fbb74e301792ba" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8" -"checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" -"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" -"checksum num-traits 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "443c53b3c3531dfcbfa499d8893944db78474ad7a1d87fa2d94d1a2231693ac6" -"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" -"checksum png 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f00ec9242f8e01119e83117dbadf34c5228ac2f1c4ddcd92bffa340d52291de" -"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" -"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 rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"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 strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4f66a4c0ddf7aee4677995697366de0749b0139057342eccbb609b12d0affc" -"checksum structopt-derive 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8fe0c13e476b4e21ff7f5c4ace3818b6d7bdc16897c31c73862471bc1663acae" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum tiff 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b7c2cfc4742bd8a32f2e614339dd8ce30dbcf676bb262bd63a2327bc5df57d" -"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"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-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/Cargo.toml b/Cargo.toml index 59c434f..ec0a537 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,15 @@ [package] name = "multiman" -version = "0.1.0" +version = "0.2.0" authors = ["Jan Trefil <8711792+htrefil@users.noreply.github.com>"] edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - [dependencies] -structopt = "0.3.3" -num-complex = "0.2.3" -image = "0.22.3" -num_cpus = "1.11.1" +structopt = { version = "0.3.26", default_features = false } +num-complex = "0.4.0" +num_cpus = "1.13.1" + +[dependencies.image] +version = "0.23.14" +default_features = false +features = ["png", "pnm", "webp", "bmp"] diff --git a/README.md b/README.md index a3d20ac..1bf2168 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,46 @@ # multiman A parallel Mandelbrot and Julia set-style fractal renderer supporting custom user expressions. -It leverages all available CPU cores to render images in parallel. +It leverages automatic differentiation and a distance estimate to make the details less noisy. +All available CPU cores are used to render images in parallel. ## Usage ``` -multiman 0.1.0 +multiman 0.2.0 USAGE: - multiman + multiman FLAGS: -h, --help Prints help information -V, --version Prints version information ARGS: - Initialization expression + Initialization expression (the value of the pixel) + Start of the iteration Iteration expression Width of the image Height of the image Path of the resulting image ``` +In the expressions, the following variables are available: +``` +w The width of the image +h The height of the image +x The current x coordinate +y The current y coordinate +c The initial complex value of the current pixel +z The value of the previous iteration +``` +They can be combined using arithmetic operations and exponentiation (using the symbol `^`). + ## Examples ``` -multiman "(X / WIDTH * 2 - 1) + (Y / HEIGHT * 2 - 1.0) * i" "Z * Z + (0.1 + 0.65i)" 500 500 examples/1.png +multiman "(x / w * 2 - 1) + (y / h * 2 - 1.0) * i" "c" "z * z + (0.1 + 0.65i)" 1000 1000 examples/1.png ``` ![1](examples/1.png) ``` -multiman "0i" "Z * Z + (X * 2 / WIDTH - 1.5 + (Y * 2 / HEIGHT - 1) * i)" 500 500 examples/2.png +multiman "x * 2 / w - 1.5 + (y * 2 / h - 1) * i" "0" "z * z + c" 1000 1000 examples/2.png ``` -![2](examples/2.png) \ No newline at end of file +![2](examples/2.png) diff --git a/examples/1.png b/examples/1.png index f4e2763..8c5edeb 100644 Binary files a/examples/1.png and b/examples/1.png differ diff --git a/examples/2.png b/examples/2.png index 7159a73..2f84038 100644 Binary files a/examples/2.png and b/examples/2.png differ diff --git a/src/ast.rs b/src/ast.rs index 57b938b..bffb19a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Debug, Formatter}; #[derive(Clone, Debug, PartialEq)] pub enum ExprKind { Bin(BinOp, Box, Box), - Var(String), + Var(u8), Real(f64), Imag(f64), } @@ -27,6 +27,7 @@ pub enum BinOp { Sub, Mul, Div, + Pow, } impl BinOp { @@ -36,6 +37,7 @@ impl BinOp { TokenKind::Sub => BinOp::Sub, TokenKind::Mul => BinOp::Mul, TokenKind::Div => BinOp::Div, + TokenKind::Pow => BinOp::Pow, _ => return None, }; @@ -45,7 +47,7 @@ impl BinOp { pub fn precedence(&self) -> u32 { match self { BinOp::Add | BinOp::Sub => 1, - BinOp::Mul | BinOp::Div => 2, + BinOp::Mul | BinOp::Div | BinOp::Pow => 2, } } } diff --git a/src/eval.rs b/src/eval.rs index 0e3c170..5cb72b7 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,26 +1,34 @@ use crate::ast::{BinOp, Expr, ExprKind}; use crate::error::Error; use num_complex::Complex; -use std::collections::HashMap; use std::ops::{Add, Div, Mul, Sub}; +#[derive(Default)] pub struct Context { - vars: HashMap<&'static str, Value>, + pub width: f64, + pub height: f64, + pub x: f64, + pub y: f64, + pub c: Value, + pub z: Value, } impl Context { - pub fn new() -> Context { - Context { - vars: HashMap::new(), - } - } - - pub fn set(&mut self, name: &'static str, value: impl Into) { - self.vars.insert(name, value.into()); + pub fn new() -> Self { + Default::default() } - pub fn update(&mut self, name: &str, value: impl Into) { - *self.vars.get_mut(name).unwrap() = value.into(); + #[inline] + fn get(&self, name: u8) -> Option { + match name { + b'w' => Some(self.width.into()), + b'h' => Some(self.height.into()), + b'x' => Some(self.x.into()), + b'y' => Some(self.y.into()), + b'c' => Some(self.c.into()), + b'z' => Some(self.z.into()), + _ => None, + } } pub fn eval(&self, expr: &Expr) -> Result { @@ -34,12 +42,7 @@ impl Context { BinOp::Sub => Ok(left - right), BinOp::Mul => Ok(left * right), BinOp::Div => { - let zero = match right { - Value::Real(num) => num == 0.0, - Value::Complex(num) => num.re == 0.0 && num.im == 0.0, - }; - - if zero { + if right.v == 0.0.into() { return Err(Error { message: "Divide by zero", position: expr.position, @@ -48,33 +51,61 @@ impl Context { Ok(left / right) } + BinOp::Pow => { + if right.v == 0.0.into() { + return Err(Error { + message: "Power by zero", + position: expr.position, + }); + } + + Ok(left.pow(right)) + } } } - ExprKind::Var(ref var) => self.vars.get(var.as_str()).cloned().ok_or_else(|| Error { + ExprKind::Var(var) => self.get(var).ok_or_else(|| Error { message: "Undefined variable", position: expr.position, }), - ExprKind::Real(num) => Ok(Value::Real(num)), - ExprKind::Imag(num) => Ok(Value::Complex(Complex { re: 0.0, im: num })), + ExprKind::Real(num) => Ok(num.into()), + ExprKind::Imag(num) => Ok(Complex { re: 0.0, im: num }.into()), } } } -#[derive(Clone, Copy, Debug)] -pub enum Value { - Real(f64), - Complex(Complex), +#[derive(Clone, Copy, Debug, Default)] +pub struct Value { + /// Value of the expression + pub v: Complex, + /// Derivative of the expression + pub d: Complex, +} + +impl Value { + fn pow(self, other: Value) -> Self { + let v = self.v.powc(other.v); + Value { + v, + d: (other.v * self.d / self.v + other.d * self.v.ln()) * v, + } + } } impl From for Value { fn from(value: f64) -> Value { - Value::Real(value) + Value { + v: value.into(), + d: 0.0.into(), + } } } impl From> for Value { fn from(value: Complex) -> Value { - Value::Complex(value) + Value { + v: value, + d: 0.0.into(), + } } } @@ -82,12 +113,9 @@ impl Add for Value { type Output = Value; fn add(self, other: Value) -> Value { - match (self, other) { - (Value::Real(a), Value::Real(b)) => Value::Real(a + b), - (Value::Complex(a), Value::Complex(b)) => Value::Complex(a + b), - (Value::Real(a), Value::Complex(b)) | (Value::Complex(b), Value::Real(a)) => { - Value::Complex(a + b) - } + Value { + v: self.v + other.v, + d: self.d + other.d, } } } @@ -96,12 +124,9 @@ impl Sub for Value { type Output = Value; fn sub(self, other: Value) -> Value { - match (self, other) { - (Value::Real(a), Value::Real(b)) => Value::Real(a - b), - (Value::Complex(a), Value::Complex(b)) => Value::Complex(a - b), - (Value::Real(a), Value::Complex(b)) | (Value::Complex(b), Value::Real(a)) => { - Value::Complex(a - b) - } + Value { + v: self.v - other.v, + d: self.d - other.d, } } } @@ -110,12 +135,9 @@ impl Mul for Value { type Output = Value; fn mul(self, other: Value) -> Value { - match (self, other) { - (Value::Real(a), Value::Real(b)) => Value::Real(a * b), - (Value::Complex(a), Value::Complex(b)) => Value::Complex(a * b), - (Value::Real(a), Value::Complex(b)) | (Value::Complex(b), Value::Real(a)) => { - Value::Complex(a * b) - } + Value { + v: self.v * other.v, + d: self.v * other.d + other.v * self.d, } } } @@ -124,12 +146,9 @@ impl Div for Value { type Output = Value; fn div(self, other: Value) -> Value { - match (self, other) { - (Value::Real(a), Value::Real(b)) => Value::Real(a / b), - (Value::Complex(a), Value::Complex(b)) => Value::Complex(a / b), - (Value::Real(a), Value::Complex(b)) | (Value::Complex(b), Value::Real(a)) => { - Value::Complex(a / b) - } + Value { + v: self.v / other.v, + d: (self.d * other.v - other.d * self.v) / (other.d * other.d), } } } diff --git a/src/lex.rs b/src/lex.rs index af21c03..41ced32 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -14,74 +14,60 @@ pub enum TokenKind { Sub, Mul, Div, - Ident(String), + Pow, + Ident(u8), Real(f64), Imag(f64), } pub fn tokenize(input: &str) -> Result, Error> { let mut tokens = Vec::new(); - let mut chars = input.chars().enumerate().map(|(i, c)| (i + 1, c)); + let mut chars = input.as_bytes().iter().enumerate(); let mut last = None; while let Some((i, c)) = last.take().or_else(|| chars.next()) { let kind = match c { - '(' => TokenKind::LParen, - ')' => TokenKind::RParen, - '+' => TokenKind::Add, - '-' => TokenKind::Sub, - '*' => TokenKind::Mul, - '/' => TokenKind::Div, - 'a'..='z' | 'A'..='Z' | '_' => { - let mut data = c.to_string(); - - while let Some((i, c)) = chars.next() { - match c { - 'a'..='z' | 'A'..='Z' | '_' | '0'..='9' => data.push(c), - _ => { - last = Some((i, c)); - break; - } - } - } - - if data == "i" { - TokenKind::Imag(1.0) - } else { - TokenKind::Ident(data) - } - } - '0'..='9' => { + b'(' => TokenKind::LParen, + b')' => TokenKind::RParen, + b'+' => TokenKind::Add, + b'-' => TokenKind::Sub, + b'*' => TokenKind::Mul, + b'/' => TokenKind::Div, + b'^' => TokenKind::Pow, + b'w' | b'h' | b'x' | b'y' | b'c' | b'z' => TokenKind::Ident(*c), + b'i' => TokenKind::Imag(1.0), + b'0'..=b'9' => { let mut dot = false; let mut complex = false; - let mut data = c.to_string(); + let mut end = i + 1; while let Some((i, c)) = chars.next() { match c { - '.' => { + b'.' => { if dot { last = Some((i, c)); break; } dot = true; - data.push(c); } - 'i' => { + b'i' => { complex = true; + end = i; break; } - '0'..='9' => data.push(c), + b'0'..=b'9' => continue, _ => { last = Some((i, c)); + end = i; break; } } } - let n = data.parse::().map_err(|_| Error { + let n = input[i..end].parse::().map_err(|_| Error { message: "Invalid floating point literal", - position: i, + position: i + 1, })?; if complex { @@ -90,18 +76,18 @@ pub fn tokenize(input: &str) -> Result, Error> { TokenKind::Real(n) } } - ' ' | '\t' => continue, + b' ' | b'\t' => continue, _ => { return Err(Error { message: "Unexpected character", - position: i, + position: i + 1, }); } }; tokens.push(Token { kind: kind, - position: i, + position: i + 1, }); } diff --git a/src/main.rs b/src/main.rs index 1fadcfa..b72d399 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ -#![feature(process_exitcode_placeholder)] mod ast; mod error; mod eval; @@ -6,24 +5,23 @@ mod lex; mod parser; use error::Error; -use eval::{Context, Value}; +use eval::Context; use image::{Rgb, RgbImage}; use num_complex::Complex; use std::cmp; use std::env; use std::num::NonZeroU32; use std::path::PathBuf; -use std::process::ExitCode; use std::str::FromStr; use std::sync::Arc; use std::thread; use structopt::StructOpt; -const ITERATIONS: u32 = 200; +const ITERATIONS: u32 = 201; #[derive(StructOpt)] struct Args { - #[structopt(help = "Initialization expression")] + #[structopt(help = "Initialization expression (the value of the pixel)")] init: Expr, #[structopt(help = "Iteration expression")] iter: Expr, @@ -53,6 +51,7 @@ fn abs(num: Complex) -> f64 { fn work( init: &ast::Expr, + first: &ast::Expr, iter: &ast::Expr, start: u32, length: u32, @@ -60,61 +59,50 @@ fn work( height: u32, ) -> Result>, Error> { let mut context = Context::new(); - context.set("WIDTH", width as f64); - context.set("HEIGHT", height as f64); - context.set("X", 0.0); - context.set("Y", 0.0); - context.set("Z", 0.0); + context.width = width as f64; + context.height = height as f64; let mut pixels = Vec::with_capacity(length as usize); for (x, y) in (start..start + length).map(|n| (n % width, n / height)) { - context.update("X", x as f64); - context.update("Y", y as f64); - - let mut z = match context.eval(&init)? { - Value::Complex(z) => z, - _ => { - return Err(Error { - message: "Init did not evaluate to a complex number", - position: init.position, - }); - } - }; - - let mut pixel = Rgb([0, 0, 0]); - for i in 0..ITERATIONS { - context.update("Z", z); - - z = match context.eval(&iter)? { - Value::Complex(z) => z, - _ => { - return Err(Error { - message: "Iter did not evaluate to a complex number", - position: init.position, - }); - } - }; - - if abs(z) >= 2.0 { - let pv = (i as f64 / ITERATIONS as f64 * 255.0) as u8; - - pixel = Rgb([pv, 0, 0]); + context.x = x as f64; + context.y = y as f64; + + let mut init = context.eval(&init)?; + init.d = 1.0.into(); + context.c = init; + + let mut z = context.eval(&first)?; + for _ in 0..ITERATIONS { + context.z = z; + + z = context.eval(&iter)?; + + if abs(z.v) >= 2.0 { break; } } - pixels.push(pixel); + let (r, dr) = (abs(z.v), abs(z.d)); + let distance = width as f64 * 0.8 * f64::ln(r) * r / dr; + let pv = std::cmp::min(f64::floor(255.0 * distance) as u8, 255); + pixels.push(Rgb([pv, pv, pv])); } Ok(pixels) } -fn render(init: ast::Expr, iter: ast::Expr, width: u32, height: u32) -> Result { +fn render( + init: ast::Expr, + first: ast::Expr, + iter: ast::Expr, + width: u32, + height: u32, +) -> Result { let total = width * height; let length = total / num_cpus::get() as u32; let pixels = if length != 0 { - let exprs = Arc::new((init, iter)); + let exprs = Arc::new((init, first, iter)); let mut threads = Vec::new(); let mut position = 0; while position < total { @@ -122,7 +110,9 @@ fn render(init: ast::Expr, iter: ast::Expr, width: u32, height: u32) -> Result Result Result ExitCode { +fn main() { let args = match Args::from_iter_safe(env::args()) { Ok(args) => args, Err(err) => { println!("{}", err); - return ExitCode::FAILURE; + return; } }; let image = match render( args.init.0, + args.first.0, args.iter.0, args.width.into(), args.height.into(), @@ -161,14 +152,12 @@ fn main() -> ExitCode { Ok(image) => image, Err(err) => { println!("Error: {}", err); - return ExitCode::FAILURE; + return; } }; if let Err(err) = image.save(&args.output_path) { println!("Error saving image: {}", err); - return ExitCode::FAILURE; + return; } - - ExitCode::SUCCESS } diff --git a/src/parser.rs b/src/parser.rs index 8043a2b..72b58cd 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -52,7 +52,7 @@ impl<'a> Parser<'a> { } TokenKind::Real(num) => ExprKind::Real(num), TokenKind::Imag(num) => ExprKind::Imag(num), - TokenKind::Ident(ref ident) => ExprKind::Var(ident.clone()), + TokenKind::Ident(ident) => ExprKind::Var(ident), _ => return Err(self.error("Unexpected token")), };