From 65c0a85889e14b7bf3e7c634c866cc6a0334ad7a Mon Sep 17 00:00:00 2001 From: hal8174 Date: Tue, 17 Sep 2024 16:57:06 +0200 Subject: [PATCH] Add image output --- Cargo.lock | 679 +++++++++++++++++++++++++++++++++- Cargo.toml | 1 + examples/layout.rs | 3 +- examples/solve_belt.rs | 2 +- src/common/visualize/image.rs | 377 +++++++++++++++++++ src/common/visualize/mod.rs | 48 ++- src/common/visualize/print.rs | 2 +- src/layout/mod.rs | 6 +- 8 files changed, 1092 insertions(+), 26 deletions(-) create mode 100644 src/common/visualize/image.rs diff --git a/Cargo.lock b/Cargo.lock index 13eb6a1..6360c5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned-vec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" + [[package]] name = "anstream" version = "0.6.13" @@ -65,6 +71,35 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + [[package]] name = "atty" version = "0.2.14" @@ -82,36 +117,110 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "av1-grain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "876c75a42f6364451a033496a14c44bffe41f5f4a8236f697391f11024e596d2" +dependencies = [ + "arrayvec", +] + [[package]] name = "base64" version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "bit_field" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" + [[package]] name = "bitflags" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitstream-io" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" + +[[package]] +name = "built" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "236e6289eda5a812bc6b53c3b024039382a2895fbbeef2d748b2931546d392c4" + [[package]] name = "bumpalo" version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +[[package]] +name = "bytemuck" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" + [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "cast" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "cc" +version = "1.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -169,6 +278,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colorchoice" version = "1.0.0" @@ -195,7 +310,7 @@ dependencies = [ "clap 2.34.0", "criterion-plot", "csv", - "itertools", + "itertools 0.10.5", "lazy_static", "num-traits", "oorandom", @@ -217,7 +332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" dependencies = [ "cast", - "itertools", + "itertools 0.10.5", ] [[package]] @@ -245,6 +360,12 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "csv" version = "1.3.0" @@ -278,6 +399,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +[[package]] +name = "exr" +version = "1.72.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" +dependencies = [ + "bit_field", + "flume", + "half 2.4.1", + "lebe", + "miniz_oxide", + "rayon-core", + "smallvec", + "zune-inflate", +] + [[package]] name = "factorio_blueprint" version = "0.1.0" @@ -286,6 +423,7 @@ dependencies = [ "clap 4.5.3", "criterion", "flate2", + "image", "rand", "serde", "serde_json", @@ -293,6 +431,15 @@ dependencies = [ "termcolor", ] +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + [[package]] name = "flate2" version = "1.0.28" @@ -303,6 +450,15 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "spin", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -314,12 +470,32 @@ dependencies = [ "wasi", ] +[[package]] +name = "gif" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" +dependencies = [ + "color_quant", + "weezl", +] + [[package]] name = "half" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.14.5" @@ -341,6 +517,45 @@ dependencies = [ "libc", ] +[[package]] +name = "image" +version = "0.25.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" + [[package]] name = "indexmap" version = "2.4.0" @@ -351,6 +566,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "itertools" version = "0.10.5" @@ -360,12 +586,36 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + [[package]] name = "js-sys" version = "0.3.69" @@ -381,24 +631,75 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lebe" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" + [[package]] name = "libc" version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "libfuzzer-sys" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" +dependencies = [ + "arbitrary", + "cc", + "once_cell", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" +dependencies = [ + "imgref", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", +] + [[package]] name = "memchr" version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -406,6 +707,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", + "simd-adler32", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", ] [[package]] @@ -429,6 +794,18 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + [[package]] name = "plotters" version = "0.3.5" @@ -457,6 +834,19 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "png" +version = "0.17.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +dependencies = [ + "bitflags", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + [[package]] name = "ppv-lite86" version = "0.2.20" @@ -475,6 +865,40 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" version = "1.0.35" @@ -514,6 +938,55 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rav1e" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" +dependencies = [ + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.12.1", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "once_cell", + "paste", + "profiling", + "rand", + "rand_chacha", + "simd_helpers", + "system-deps", + "thiserror", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.11.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f0bfd976333248de2078d350bfdf182ff96e168a24d23d2436cef320dd4bdd" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rgb", +] + [[package]] name = "rayon" version = "1.9.0" @@ -563,6 +1036,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "rgb" +version = "0.8.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" +dependencies = [ + "bytemuck", +] + [[package]] name = "ryu" version = "1.0.17" @@ -578,6 +1060,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.197" @@ -593,7 +1081,7 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half", + "half 1.8.3", "serde", ] @@ -619,6 +1107,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "serde_yaml" version = "0.9.34+deprecated" @@ -632,6 +1129,42 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + [[package]] name = "strsim" version = "0.11.0" @@ -649,6 +1182,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "termcolor" version = "1.4.1" @@ -667,6 +1219,37 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -677,6 +1260,40 @@ dependencies = [ "serde_json", ] +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -701,6 +1318,23 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +[[package]] +name = "v_frame" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + +[[package]] +name = "version-compare" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" + [[package]] name = "walkdir" version = "2.5.0" @@ -781,6 +1415,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" + [[package]] name = "winapi" version = "0.3.9" @@ -878,6 +1518,15 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +[[package]] +name = "winnow" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -898,3 +1547,27 @@ dependencies = [ "quote", "syn", ] + +[[package]] +name = "zune-core" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index 9fc7820..8eebfce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ harness = false base64 = "0.21.5" clap = { version = "4.4.8", features = ["derive"] } flate2 = "1.0.28" +image = "0.25.2" rand = { version = "0.8.5", features = ["small_rng"] } serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" diff --git a/examples/layout.rs b/examples/layout.rs index 1d3d667..617c6b5 100644 --- a/examples/layout.rs +++ b/examples/layout.rs @@ -1,7 +1,7 @@ use clap::Parser; use factorio_blueprint::{ common::visualize::Visualize, - layout::{genetic_algorithm2, GeneticAlgorithm, PathLayout}, + layout::{genetic_algorithm2, PathLayout}, }; use rand::{rngs::SmallRng, SeedableRng}; @@ -36,6 +36,7 @@ fn main() { let g = genetic_algorithm2(&p, 10, 320, &mut rng); g.print_visualization(); + g.png_visualization("test.png"); if m.as_ref().is_none_or(|m| g.score() < m.score()) { m = Some(g); } diff --git a/examples/solve_belt.rs b/examples/solve_belt.rs index a144b65..4ddb73a 100644 --- a/examples/solve_belt.rs +++ b/examples/solve_belt.rs @@ -1,6 +1,6 @@ use clap::{Parser, ValueEnum}; use factorio_blueprint::belt_finding::{conflict_avoidance::ConflictAvoidance, problems, Problem}; -use std::{io, path::PathBuf}; +use std::io; #[derive(ValueEnum, Clone)] enum Mode { diff --git a/src/common/visualize/image.rs b/src/common/visualize/image.rs new file mode 100644 index 0000000..45fb9ec --- /dev/null +++ b/src/common/visualize/image.rs @@ -0,0 +1,377 @@ +use super::Visualization; +use crate::{common::visualize::Symbol, prelude::Direction}; +use image::{GenericImage, Rgba}; + +pub(super) fn draw>>(v: Visualization, image: &mut I) { + assert_eq!( + (v.size.x as u32 * 10, v.size.y as u32 * 10), + image.dimensions() + ); + + for (pos, (symbol, fg, bg)) in &v.symbols { + match symbol { + Symbol::Arrow(dir) => { + if let Some(c) = bg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 0..10 { + for y in 0..10 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + if let Some(c) = fg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for p in rotate_iter(*dir, arrow()) { + image.put_pixel((pos.x * 10) as u32 + p.0, (pos.y * 10) as u32 + p.1, rgba); + } + } + } + Symbol::ArrowEnter(dir) => { + if let Some(c) = bg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 0..10 { + for y in 0..10 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + if let Some(c) = fg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for p in rotate_iter(*dir, arrow_enter()) { + image.put_pixel((pos.x * 10) as u32 + p.0, (pos.y * 10) as u32 + p.1, rgba); + } + } + } + Symbol::ArrowExit(dir) => { + if let Some(c) = bg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 0..10 { + for y in 0..10 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + if let Some(c) = fg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for p in rotate_iter(*dir, arrow_exit()) { + image.put_pixel((pos.x * 10) as u32 + p.0, (pos.y * 10) as u32 + p.1, rgba); + } + } + } + Symbol::Char(ch) => { + if let Some(c) = bg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 0..10 { + for y in 0..10 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + + if let Some(c) = fg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for p in char(*ch) { + image.put_pixel((pos.x * 10) as u32 + p.0, (pos.y * 10) as u32 + p.1, rgba); + } + } + } + Symbol::Block => { + if let Some(c) = fg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 1..9 { + for y in 1..9 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + if let Some(c) = bg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 0..10 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10) as u32, rgba); + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + 9) as u32, rgba); + } + for y in 1..9 { + image.put_pixel((pos.x * 10) as u32, (pos.y * 10 + y) as u32, rgba); + image.put_pixel((pos.x * 10 + 9) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + Symbol::Space => { + if let Some(c) = bg.as_ref() { + let rgba = Rgba::from([c.r, c.g, c.b, 255]); + for x in 0..10 { + for y in 0..10 { + image.put_pixel((pos.x * 10 + x) as u32, (pos.y * 10 + y) as u32, rgba); + } + } + } + } + } + } +} + +fn rotate(dir: Direction, pos: (u32, u32)) -> (u32, u32) { + match dir { + Direction::Up => pos, + Direction::Right => (9 - pos.1, pos.0), + Direction::Down => (9 - pos.0, 9 - pos.1), + Direction::Left => (pos.1, 9 - pos.0), + } +} + +fn rotate_iter( + dir: Direction, + iter: impl Iterator, +) -> impl Iterator { + iter.map(move |p| rotate(dir, p)) +} + +fn arrow() -> impl Iterator { + [ + (4, 1), + (5, 1), + (3, 2), + (4, 2), + (5, 2), + (6, 2), + (2, 3), + (3, 3), + (4, 3), + (5, 3), + (6, 3), + (7, 3), + (1, 4), + (2, 4), + (4, 4), + (5, 4), + (7, 4), + (8, 4), + (4, 5), + (5, 5), + (4, 6), + (5, 6), + (4, 7), + (5, 7), + (4, 8), + (5, 8), + ] + .into_iter() +} + +fn arrow_enter() -> impl Iterator { + [ + (2, 1), + (3, 1), + (4, 1), + (5, 1), + (6, 1), + (7, 1), + (3, 2), + (4, 2), + (5, 2), + (6, 2), + (2, 3), + (3, 3), + (4, 3), + (5, 3), + (6, 3), + (7, 3), + (1, 4), + (2, 4), + (4, 4), + (5, 4), + (7, 4), + (8, 4), + (4, 5), + (5, 5), + (4, 6), + (5, 6), + (4, 7), + (5, 7), + (4, 8), + (5, 8), + ] + .into_iter() +} + +fn arrow_exit() -> impl Iterator { + [ + (4, 1), + (5, 1), + (3, 2), + (4, 2), + (5, 2), + (6, 2), + (2, 3), + (3, 3), + (4, 3), + (5, 3), + (6, 3), + (7, 3), + (1, 4), + (2, 4), + (4, 4), + (5, 4), + (7, 4), + (8, 4), + (4, 5), + (5, 5), + (4, 6), + (5, 6), + (2, 7), + (3, 7), + (4, 7), + (5, 7), + (6, 7), + (7, 7), + ] + .into_iter() +} + +static CHARDATA: [[u8; 8]; 128] = [ + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0000 (nul) + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0001 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0002 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0003 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0004 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0005 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0006 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0007 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0008 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0009 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+000A + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+000B + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+000C + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+000D + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+000E + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+000F + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0010 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0011 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0012 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0013 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0014 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0015 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0016 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0017 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0018 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0019 + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+001A + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+001B + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+001C + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+001D + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+001E + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+001F + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0020 (space) + [0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00], // U+0021 (!) + [0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0022 (") + [0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00], // U+0023 (#) + [0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00], // U+0024 ($) + [0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00], // U+0025 (%) + [0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00], // U+0026 (&) + [0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0027 (') + [0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00], // U+0028 (() + [0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00], // U+0029 ()) + [0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00], // U+002A (*) + [0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00], // U+002B (+) + [0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06], // U+002C (,) + [0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00], // U+002D (-) + [0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00], // U+002E (.) + [0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00], // U+002F (/) + [0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00], // U+0030 (0) + [0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00], // U+0031 (1) + [0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00], // U+0032 (2) + [0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00], // U+0033 (3) + [0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00], // U+0034 (4) + [0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00], // U+0035 (5) + [0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00], // U+0036 (6) + [0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00], // U+0037 (7) + [0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00], // U+0038 (8) + [0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00], // U+0039 (9) + [0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00], // U+003A (:) + [0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06], // U+003B (;) + [0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00], // U+003C (<) + [0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00], // U+003D (=) + [0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00], // U+003E (>) + [0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00], // U+003F (?) + [0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00], // U+0040 (@) + [0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00], // U+0041 (A) + [0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00], // U+0042 (B) + [0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00], // U+0043 (C) + [0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00], // U+0044 (D) + [0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00], // U+0045 (E) + [0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00], // U+0046 (F) + [0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00], // U+0047 (G) + [0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00], // U+0048 (H) + [0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], // U+0049 (I) + [0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00], // U+004A (J) + [0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00], // U+004B (K) + [0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00], // U+004C (L) + [0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00], // U+004D (M) + [0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00], // U+004E (N) + [0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00], // U+004F (O) + [0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00], // U+0050 (P) + [0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00], // U+0051 (Q) + [0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00], // U+0052 (R) + [0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00], // U+0053 (S) + [0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], // U+0054 (T) + [0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00], // U+0055 (U) + [0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00], // U+0056 (V) + [0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00], // U+0057 (W) + [0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00], // U+0058 (X) + [0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00], // U+0059 (Y) + [0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00], // U+005A (Z) + [0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00], // U+005B ([) + [0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00], // U+005C (\) + [0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00], // U+005D (]) + [0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00], // U+005E (^) + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF], // U+005F (_) + [0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00], // U+0060 (`) + [0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00], // U+0061 (a) + [0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00], // U+0062 (b) + [0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00], // U+0063 (c) + [0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00], // U+0064 (d) + [0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00], // U+0065 (e) + [0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00], // U+0066 (f) + [0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F], // U+0067 (g) + [0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00], // U+0068 (h) + [0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], // U+0069 (i) + [0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E], // U+006A (j) + [0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00], // U+006B (k) + [0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00], // U+006C (l) + [0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00], // U+006D (m) + [0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00], // U+006E (n) + [0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00], // U+006F (o) + [0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F], // U+0070 (p) + [0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78], // U+0071 (q) + [0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00], // U+0072 (r) + [0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00], // U+0073 (s) + [0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00], // U+0074 (t) + [0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00], // U+0075 (u) + [0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00], // U+0076 (v) + [0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00], // U+0077 (w) + [0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00], // U+0078 (x) + [0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F], // U+0079 (y) + [0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00], // U+007A (z) + [0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00], // U+007B ([) + [0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00], // U+007C (|) + [0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00], // U+007D (]) + [0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+007E (~) + [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], // U+007F +]; + +fn char(c: char) -> impl Iterator { + let id = c as usize; + CHARDATA[id] + .iter() + .enumerate() + .flat_map(|(y, &d)| { + (0..8).filter_map(move |x: u32| { + if (d >> x) & 1 == 1 { + Some((x, y as u32)) + } else { + None + } + }) + }) + .map(|(x, y)| (x + 1, y + 1)) +} diff --git a/src/common/visualize/mod.rs b/src/common/visualize/mod.rs index 883042d..c98dbed 100644 --- a/src/common/visualize/mod.rs +++ b/src/common/visualize/mod.rs @@ -1,7 +1,10 @@ +mod image; mod print; use std::collections::HashMap; +use ::image::RgbaImage; + use crate::prelude::*; pub trait Visualize { @@ -11,41 +14,52 @@ pub trait Visualize { let v = self.visualize(); print::print(v); } + + fn png_visualization(&self, file: impl AsRef) { + let v = self.visualize(); + + let mut img = RgbaImage::new((v.size.x * 10) as u32, (v.size.y * 10) as u32); + + image::draw(v, &mut img); + + let mut f = std::fs::File::create(file).unwrap(); + let _ = img.write_to(&mut f, ::image::ImageFormat::Png); + } } pub enum Symbol { Arrow(Direction), ArrowEnter(Direction), ArrowExit(Direction), - Char(&'static str), + Char(char), Block, Space, } impl Symbol { - fn get_str(&self) -> &'static str { + fn get_char(&self) -> char { match self { Symbol::Arrow(dir) => match dir { - Direction::Up => "↑", - Direction::Right => "→", - Direction::Down => "↓", - Direction::Left => "←", + Direction::Up => '↑', + Direction::Right => '→', + Direction::Down => '↓', + Direction::Left => '←', }, Symbol::ArrowEnter(dir) => match dir { - Direction::Up => "↟", - Direction::Right => "↠", - Direction::Down => "↡", - Direction::Left => "↞", + Direction::Up => '↟', + Direction::Right => '↠', + Direction::Down => '↡', + Direction::Left => '↞', }, Symbol::ArrowExit(dir) => match dir { - Direction::Up => "↥", - Direction::Right => "↦", - Direction::Down => "↧", - Direction::Left => "↤", + Direction::Up => '↥', + Direction::Right => '↦', + Direction::Down => '↧', + Direction::Left => '↤', }, - Symbol::Char(c) => c.split_at(1).0, - Symbol::Block => "#", - Symbol::Space => " ", + Symbol::Char(c) => *c, + Symbol::Block => '#', + Symbol::Space => ' ', } } diff --git a/src/common/visualize/print.rs b/src/common/visualize/print.rs index a24905f..84fea4c 100644 --- a/src/common/visualize/print.rs +++ b/src/common/visualize/print.rs @@ -45,7 +45,7 @@ pub(super) fn print(v: Visualization) { c.set_fg(fg.as_ref().map(|c| termcolor::Color::Rgb(c.r, c.g, c.b))); c.set_bg(bg.as_ref().map(|c| termcolor::Color::Rgb(c.r, c.g, c.b))); stdout.set_color(&c).unwrap(); - write!(stdout, "{:1}", s.get_str()).unwrap(); + write!(stdout, "{:1}", s.get_char()).unwrap(); stdout.reset().unwrap(); } else { write!(stdout, " ").unwrap(); diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 2cd5def..8c6524a 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -588,18 +588,18 @@ impl<'a> Visualize for Layout<'a> { let pos = Self::transform(*p, *d, Position::new(0, 0)); - v.add_symbol(pos, Symbol::Char("X"), Some(c), None); + v.add_symbol(pos, Symbol::Char('X'), Some(c), None); for input in &b.input { let pos = Self::transform(*p, *d, input.offset); - v.add_symbol(pos, Symbol::Char("i"), Some(c), None); + v.add_symbol(pos, Symbol::Char('i'), Some(c), None); } for output in &b.output { let pos = Self::transform(*p, *d, output.offset); - v.add_symbol(pos, Symbol::Char("o"), Some(c), None); + v.add_symbol(pos, Symbol::Char('o'), Some(c), None); } }