jp2a ripoff
bendn 2023-06-11
commit cb4b982
-rw-r--r--.gitignore1
-rw-r--r--Cargo.lock588
-rw-r--r--Cargo.toml25
-rw-r--r--README.md8
-rw-r--r--arc.pngbin0 -> 285 bytes
-rw-r--r--cat.jpgbin0 -> 10296 bytes
-rw-r--r--output.ansi83
-rw-r--r--src/main.rs19
-rw-r--r--src/picture.rs75
9 files changed, 799 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..046753a
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,588 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
+[[package]]
+name = "anstream"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is-terminal",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+dependencies = [
+ "anstyle",
+ "windows-sys",
+]
+
+[[package]]
+name = "anyhow"
+version = "1.0.71"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bytemuck"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "4.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca8f255e4b8027970e78db75e78831229c9815fdbfa67eb1a1b777a62e24b4a0"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+ "once_cell",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acd4f3c17c83b0ba34ffbc4f8bbd74f079413f747f84a6f89292f138057e36ab"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "bitflags",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
+
+[[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"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+[[package]]
+name = "crc32fast"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "either"
+version = "1.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
+
+[[package]]
+name = "errno"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
+[[package]]
+name = "fdeflate"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d329bdeac514ee06249dabc27877490f17f5d371ec693360768b838e19f3ae10"
+dependencies = [
+ "simd-adler32",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.26"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "heck"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
+[[package]]
+name = "image"
+version = "0.24.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "527909aa81e20ac3a44803521443a765550f09b5130c2c2fa1ea59c2f8f50a3a"
+dependencies = [
+ "bytemuck",
+ "byteorder",
+ "color_quant",
+ "jpeg-decoder",
+ "num-rational",
+ "num-traits",
+ "png",
+]
+
+[[package]]
+name = "io-lifetimes"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "is-terminal"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
+dependencies = [
+ "hermit-abi 0.3.1",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "jpeg-decoder"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e"
+dependencies = [
+ "rayon",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.146"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
+
+[[package]]
+name = "memoffset"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "miniz_oxide"
+version = "0.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+dependencies = [
+ "adler",
+ "simd-adler32",
+]
+
+[[package]]
+name = "num-integer"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+dependencies = [
+ "autocfg",
+ "num-traits",
+]
+
+[[package]]
+name = "num-rational"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
+dependencies = [
+ "autocfg",
+ "num-integer",
+ "num-traits",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+
+[[package]]
+name = "pascii"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "clap",
+ "image",
+ "rayon",
+ "rgb2ansi256",
+]
+
+[[package]]
+name = "png"
+version = "0.17.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaeebc51f9e7d2c150d3f3bfeb667f2aa985db5ef1e3d212847bdedb488beeaa"
+dependencies = [
+ "bitflags",
+ "crc32fast",
+ "fdeflate",
+ "flate2",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rayon"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "rgb2ansi256"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ebca96b1c05912d531790498048bab5b7b97a756a7bb9df71fa4ef7ef9814e1"
+
+[[package]]
+name = "rustix"
+version = "0.37.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f"
+
+[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
+name = "syn"
+version = "2.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+
+[[package]]
+name = "utf8parse"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..36582e6
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,25 @@
+[package]
+name = "pascii"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.71"
+clap = { version = "4.3.3", features = ["derive"] }
+image = { version = "0.24.6", features = [
+ "png",
+ "jpeg_rayon",
+], default-features = false }
+rayon = { version = "1.7.0", optional = true }
+rgb2ansi256 = "0.1.1"
+
+[profile.release]
+lto = true
+opt-level = 3
+strip = true
+
+[features]
+rayon = ["dep:rayon"]
+default = []
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..93b6601
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+# pascii
+
+is a ripoff of jp2a that does two things:
+
+- is very fast: 2ms for 32x32 images with full color (enable rayon feature for images > 4000px)
+- doesnt repeat ansi escape sequences (no `\e[34;5mc\e[34;5md\e[34;5me`, just `\e[34;5mcde`)
+
+see [output.ansi](https://github.com/bend-n/pascii/blob/master/output.ansi) for a example. \ No newline at end of file
diff --git a/arc.png b/arc.png
new file mode 100644
index 0000000..106963a
--- /dev/null
+++ b/arc.png
Binary files differ
diff --git a/cat.jpg b/cat.jpg
new file mode 100644
index 0000000..a0b9aaf
--- /dev/null
+++ b/cat.jpg
Binary files differ
diff --git a/output.ansi b/output.ansi
new file mode 100644
index 0000000..5d2f806
--- /dev/null
+++ b/output.ansi
@@ -0,0 +1,83 @@
+..,,,,....................,,,,,,,,.........................................................,....:cloll:,....................,:ccllooooooodddddddxxxxxxxxxxxxkkkkxkkkkkkkkkkkkkkkkkkkkkkxxxxxxdddddooollllllllllllllllcccllllllllllllllllllllllllllllllllll
+..,,,,..................,,,,,,,,,..............................................................,,cloolc:...................,:cclooodddddddddxxxxxxxxxxxxxxxxkkkkkkkkkkkkkkkkkkkkkxxxxxxdddooooollllllllllllllllcccccllllccccclllllllllllllllllllllllllllll
+.....................,,,,,,,,,,,..............................................................,,,:clollc,.................,:clooodddddddddxxxxxxxxxxxxxxkkkkkkkkkkkkkkkkkkxxxxxxdddooollllllllllllllllllllllccccccccclllllllllllllllllllllllllllllllllllll
+..................,,,,::,,,,,,..............................................................,,:,,,,cllllc,..............,:clooddddddddxxxxxxxxxxxxxxkkkkkkkkkkxxxxxxxxxxddddoooollllllccccclllllcccccccccccccccccccccclllllllllllllllllllllllllllloooooooo
+...............,,,:::::::,,,................................................................:::::,.,clllc:,...........,:ccooddddxxxxxxxxxxxxxxxxxkkkkkkkxxxxxxxddddooooollllllllccccclllcccccccccccccccccccccccccccllllclllllloooooooooooooooooooooooooodd
+............,,,:::::::::,,..................................................................,:::,...:loool:,.........,:cloddxxxxxxxxxxxxxxxxxkkkkkkxxxxxddddooolllcccccccccccccccccccccccccccccccccccccccccccclllllllllllllllooooooooooooooooooooooooooooo
+..........,,,::::::::,,,,...................................................................,,::,...:looolc:,......,,clooddxxxxxxxxxxxxxxxxxkkxxxxddddoolllllcccccccccccc:::cccccccccccccccccccccccllllllllllllllllllllllllloooooooooooollllllllllllllllll
+........,,:::::::::,,,,.......................................................................,,,...,:lllllc,,...,,:coodxxxxxxxxxxxxxxxxxxxxxxdddoollllccccccccccc::cccc:::::cccccccccccccllllllllllllllllllllllllllllllclllllllllllllllllllllllllllllllll
+.....,,,,::::::::,,,............................................................................,,....,:cccc:,,..:clodxxxxxxxxxxxxdddddodooddooolcccclccccc::cccccccccccc:::cccccccclllcllllllllllllllllllllllllllllllllllloooooolooooolllllllllllllllllll
+....,,,:::::::::,,..............................................................................,,......,::cc:,,:clodxxxxxxxxddddooollllclllollccccccccccc:::ccccccccccclcccccccccclllllllllllllccllllllllllllllllllllllloooooooollloolllllllllllllllllloo
+,,,,,,,::::::,,,,.............................................................................,,::,......,:ccccclodddxddddooolllcccc::::cllollc:::ccccccccccccccccccccllllccccclllllllllllllllllllllllllllllllllllllloooooooooooooollllllllllllllllllloooo
+,,,,,,,,,,,,,,...............................................................................,::::,.......,:ccloooddooolllcc:::::::::::clllllc::::::ccccllcccccccccccllllllccllodoolllllllllllllllllllllllllooooooooddxxxxxxxxddoooooolllllllllolllloooooo
+cc::,,,,,,,,..................................................................................,::,,......,:ccllooollcc::::::::::::::::cclllc::::,::::cclcccccccccclllllclcclloddddolllllllllloolllllllloloooddxxkkOOO00000OOkxddoooooooooooooooolooooooooo
+kkxdollllc:,...................................................................................,,,,,,,:::::cccllcc::,,::::,,,,,,,,,,:ccllcc:::::::::ccccccccccclllllollollllldxxxxolllllllllooolloooooddxxkOO000KKKKKKKK00Okxdoooooooooooolooooooooooooooo
+OOOOkkkkkxddolc::,,............................................................................,,,:::::::::::::::,,,,,,,,,,,,,,,::,,:looolc::cloxdollllllllllodxkk0K0kkkxdoodxxxxdooooooooooooddxxkOO000KKKKKKXKXXXXXKK0Okxdoooooooooooooooooooooooooooooo
+kkkkkkkkkkkkOkkxdolc:,,....................................................................,,,,,,::::,,,,,,,,,,,,,,,,,,,:,,,,:cccloodxOOkkO0KXMMMMMMXXK0O00KKXMMMMMMMMMMMMXXKK0OkxooooddxxkOO0KKKKKXXXXXXXXXXXXXXXXXKK0Oxxdooooooooooooloooooooooooooooooo
+kkxxxxxkkkkOOOOOOOkkxdolccc:,........................................................,,,,,,,,,,,,,:,,,......,,,,,c,,::cccloxkkO00KK0KKK00KKKKKXXKXMMXMMMMMMMXXXXXKKXXXXXXXXXXXXMKOkxk0KXXXXXXXXXMMXXXXXXXXXXXXXXXXXKKOkxoooooooolooooooooooooooooooooddddd
+xxxxxxxxxxkkkkOOOOOO0OOOkkxdl:,.....................................................,,,,,,,,,,:::::,,,,,...,::codxddxkOOOO000KK0KOkOkxxOkOOOO000K00XMMXXMXK000K0000K00OOOOkO0000KKKXXXXXMMMMMMMMMMMMMXXXXXXXXXXXXK0Okxdoooooooooooooooooooooooooooooddxxxx
+kkkkxxxxxxxxxkOOOOOO000000OOkdoc,,....................,,,,.................................,,:clcc::,...,:coxkkxxxxxkkxkOkkxxxdodddoollldddddxxkOOOO0KXXXK000000kOO00KKOkxdxxkkkkkO000KXXXXXXXXMMMMMMMXXMMMMMXXX00kxdoooooooooooooooooooooddooooodxkO00K0K
+dxxkkkkkOkkkkkkOOOO00000000000Oxol:,..................,,,,,....,,,.........................,:ccccccllldddkkkxxddoooloolllc:ccccc,,::ccccccccclldddxxxkO0K0KKK0OOkkxddddxkkkkkxkkO0KKKKKKK00O0KXMMMMMMMXXMXXXXXK0OkdoooooooooooooooooodddxxxxdddddxkO0KKKKK
+xxxxkkkOOkkkkOOOO00000OOO00KKKKKOkdl:,................,,::,,,,.............................,:ccldxxxxxxxxddoollcc::ccc::cc:,,:c::,.,:::,,::::cccllllodddxkOxxoodxkxddxdddxxkkkkk00KKKKKKXXXXXMMMMMMMMMMXMXXXKKOkxddddddddoooooodxxxkkOOO00OkxdooodxkO0KKKK
+xxxxxkkkkkkxkkkOOOOOOOOOO000KKKKKK0Oxl:..............,,,,,,..............................,,,ldxxxxxdddoddollcccc:,,,,,:,,,.,:::::::,,,:::::::::c:::cloooddocllddxxxollooddxkkkOO00KKXXXXMMMMMMMMMMXXXMMXXXXXK0kxxxxxxxxdddxxxkOOOO000OOOOOkdolllodxkO00O00
+ddddddxxxxxxddxxxxkkkOOOOOO0KKKXXXXXKOo:,............,,,,,..............................,:cldxxxddddddddlllcc:::::,..,,,,,,,,::,,,,,,:,,,,,:::,,:::cllooodoodxxdddollloddxxxxk0KKKKKXXMMMMMMMMMMMXMMMMMMXXKK0kxxxxxxxxxxxkkkOOOOOkkxxdddoollcllooxkOOOOOkk
+oooooooooddddddddxxxxkkkkOO00KKKXXXXXKkl:,........,,,,,,................................,ldxxxdddoddooocllccc::,...,,,,..,,,,........,,,,:::::,,,,,:cclolllodxddoooooodxkkkkkkkk0KXXXXMMMMMMMMMMMMMMMMXXKKOkkxxxddddddxxkkxxxxddoooooooolllcllodxkO00000KK
+oodxxkkO00000KKKKKXXKKKK000KKKKKXXXXXX0koc,,....,,::::,,.......................,......,cxxxxdddxddlcc:cc:,,,,,::,,,......,,,,,.....,,,,.,,,,,,:c:,,,,,:ccccoddooooodxkkkkxxxxxk0KXXXXMMMMMMMMMMMMMMMXXXKOkxxxxxddddoooodooooooooooodddolllcllooxkO00KKKXXX
+O0KXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXMXKOxl::,,::::::,,,,........................,,..:ldxdddddddoollccccc:::,,,.,..........,,............,::,,,,cc:.,,:,:ccllloooddxxxxdxddddxk0XMMMMMMMMMMMMMMMMMXXXK0OxxddddddddooooooooooodddxkkOOkdollcclodkKXXXXXKXXX
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXKOdllllccc:::,,......................,,,,,:coddddddoooollllcc:::::::,,,.....,,,...,,...,,..........,:::.,:c:,,,,:clllloooooddddodoodddx0XMMMMMMMMMMMMMMMXX0OkxddddoodddddooodddxxkOO0000KKKK0xollccloxOXMMXXKKXKK
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXKOkxoolc:,,,..............,::llllllcc::cldxxxdollooooollccc::,,,,:::::::,,,,....,,,,,,,..,,.........,,,.,::,..,::cccccclooddddxdddddxxOKXMMMMMMMMMMMXK0OxxdddooddddxxxkkkOO00KKKKKKXXXXKKK0xolllclodOKXKKK00KKK
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXKOdol:,..,...,...:llccclllllcllllllclodddooddoooolcc::,:,,::::cl::::,,,,,,......,...,,,....,,........,,....,:cclloodkxxOkkkkkkxxddxxkKMMMMMMMXKKOkdddxxxxkkOO000KKKKKXXXXXXXXXXXXXXXK0Odooddoldx000kxddxkO
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXKKkdlc::,.,lollloodooddoodddooooooolcccoddlcc::::,...,,,::ccc:,,,,,..........,,,.................,:c:,.,::ccoxxdkOkkOOO00000OOxdxOKMMMMXXK0kkkkkO000KKKKXXXXXXXXXXXXXXXXXXXXKKKXKKOxxkOOOkxxxxxdollllo
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXKKKK0OO0000Okdlcclollodddodoooooooloooooooooollcloooodxxdl:,...,::,:,,,,,,,..,........::,.................,::,...:loddxxkkO00KKKKKK0KK0Okxk0KXXK00KKKKKKKXXXXXXXXXXKXXXXXXXXXXXXXXXXKXXXK0kddkOOOOOkkdolllcll
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXK0Okxxxxxxxxxxxddoddocloddddooooolooolllllooollooolllooolllllldddoc:,.,....,::::,:::,,....,,,.................,:ccccclddxkkkOKKKXXXXXXXKKXXXKOkk0XXXKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXK0xdodxxkOOO0Okxdooo
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXX0kxxddodddddddoolooooclodoooolllloollclllllllllllooollllllllcccccccllooddddolc::,::c:::,....,:,...........,....,cc:,,,:ldxk00KXXXXXXXXXXXXXXXXKkO0KXKXXXXXXXXXXXXXXXXXXXXXXXXXKKXXXXXXXXXXXXXK0kdddxxxxxkOO000OO
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXK0Oxddodolloodddoooolloclodolllclloolccllllllllllccccclcccccc::::::,,,,,,,:cloooocc::::,c:,..............,.......,:cllc:,:odxO0KKXXXXXXXXXMMMMMXMKKOOXXXXXXXXXXXXXXXXXXXXXXXKKXXKKKXKKXXXXXXXXXXXK0kxdxxxxxxxxkk00
+MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXKOkxxxdoddolclloollcllloolooolllccllccccccccccc::ccccllcccccc::::,,,,,......,,,::,,:,:,,.,.................,,...,ccclooodocldxkOKKXXMMMXMXMMXMMMXXXX0OKXKXXXXXXXXXXXXKKKXXXXXXXKKKKXXXXXXXXXXXXXXXXXK0kxxkkOOkkxxxx
+MMMMMMMMMMMMMMMMXXXXXXXMMMMMMMMMMMXXXXK0xdoodooollllooololllclolllolllcccccccc:::::,,::::cclccc:cc:::,,,:,,...........,,,,..........,..............,,...,,,,clc:,codxkkO00KXMMMMMMMMXMMXXKK000KXXXXXXXXXXXKKKKKKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXK00OOkOOkkxxx
+MMMMMMMMMMXMMMMMMMXXXXXMXXMMMMMMMMMXXKOxdolllclooolloolcccclllloccllllcccc::::,,,,,,,:cccc::::c::::::,::,,.....,.,,,,::,,,.................,,..:::,.,.....,,,,c:..:odxkkO00KXXXMMMMXMXK0Ok0KKKKXKKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKXKKK0Okxddd
+MMMXXXXXKKKKKKXXXXXMMXXMMMMMMMMMMMXXK0kdoollllllollcclcccccllllllccllccllllc:,,,,,,,,,,,,......:::::::,,,.,,,,,:cc::::,....................,...,,cc,:::::.....,ll:,:oxxkkkkO0KKXXXXXX0kxocx0KKXKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXK0Okxxdd
+XXK000OOOkxxkO00K000KXXXXXMMMMXXMXK0kdolcccclcccccccclc:cccccllodol:::c:ccc::,.............,:c:,::::::,,,...,,:::::,,,..........,,,.....,,,,..,.,:c,,,c:,:,....,ldl:cdxkOOkkkkO0KKKKOooxO,:kKKKKKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKK00Okxxxddd
+XXKK0OkxxkOO0KKXXXXXXXXXXXMMMMXXXK0Okdlcc:,,::c:::::::cc::cllloooool:,,,::,,,,.........,c:,,,,,,:,,,,,,,,,,,,:::::,,,,,......,,,..,:::,,,.,,,,,,:::...,.::::....:lolcldxkkOkxddkOOkxolldd,ck000K0KKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKK0Okkkxxxxxdd
+XXK0kkOOOO00KXXXXXXXXK00KKXXXKKX0Oxxdolccc:::::::,:cc::::cloolloooool:,,:,,,,,............,,...:..,,,,,,:::::::::,,,,,.....,::,,,:,.,::.,,.,.c,,::,,.....,::c,..,codoloxkkkOkoodkxlcllccc.,dO00OOKKKXXKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKK0000OOkkkxxxxxxx
+xxddddddxk000O00KKKKK000O0OOkxxdxddolccc:ccc:ccllccllccccllollloooooolcccc:::,..............,,:,,,,,,,,:,,:::,,,,,,,,,....,:::,,:,,::::c:,:,:c:,.,:::c:,...,,,:,...:odddxxxkxddxxc:lolcc,,cxOkxk0KKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKK0000OOOkkkxxxxxx
+kxooodkOOOOkxdxkxxxkkOOO0K0kxxxxooooolccc:,,:cllc::cloddollccc:::ccclol:::::,,............,,,,,,,,,,,,,:,:::::,,,,,,,,,,,,::::::c::::::clcc,,,:,...,:cccc,,...::,,..:ldxxxxxxxxdlccc:::..,cxkook0KXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKK00000OOOkkkkkxx
+ooodxOOOkxxkkxdoxxkkkkkOOO00Okxdxdoolllc::::::::cccllooooolllcc::c::cllc:::,,...............,,,,::,,,,,::::,,,,,,,,,,,,::::ccccccccccccccclc:,,,..,,:::::c:,,,,:,,:,:coodxxxxxoc,cc,,....cdxoodx0KXXXXXXXXXXXXXXXXXXXXXXXKKKKKKKKKKKKKKKKKKKKKKK00000OOOkk
+cccllollloodxxolcodxxddddxkO0Okdoooolccc::::,,,,.,::cllllccccccc:cccllollcc:...............,,..,,,,,,,,,,,,,,,,,,,,,,,:::::ccccccccllcllllol:......,,::ccccc::cc:cc:.,cloddxkd:.........:ldlclod0KKKXXXXXXXXXXXXXXXXXXXXKKKKKKKKXXXXXXKKKKKKXXXXXXK00000OO
+:clddolcloooolllcclodk0000OO0KK0Okdolcccc:,,,,,,::::ccc::::::,,,,:cllolllllc,...............,,,:,,,,,,,,,,,,,,,,,,,:::::cccccllcccccc::clooooc,....,,,:ccccccc:,,:c:,,,codddxd:......,cllccccodxOKXXXXXXXXXXXXXXXXXXXXKKXKKKXXXKXXXXXXXXKXXXMMMMMMMMXKKK00
+loodol::,:looooloooloxO0O0KKKK0OOkdlc:,,,..,,::,,,::::::ccc::,,:ccccllllllllc:...............,,,:::,,,,,,,,,,,,,,,::::::cccccccclllcccloooooooc:....,::::ccc::::,:,,:,,:coddddl..,:cllool:coxxxk0KXXXXKXXXXXXXXXXXXXXXXXXXXXXXXKXXXXXXXXXXMMMMMMMMMMMMXKKK
+lccc::,,::clolllloddoododxkkkkO0Oxoc:,,,.,,,,,:::::::,,,:,,,,:clccclllcccloooc,,............,,,,,,,,,,,,,,,,,,,,::::::::ccccclcccccccccclooooooc:,....,:::::,,,,,,,::,,:ccodddo:.,:lodolc:ldkOO00KXXXXXMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMMMXKK
+c:,,,::::clcclodxkxxxxollldxxkO0Oxl:,...,,,,,::clcc::,,,..,:cclllccccccccloolc,................,.,,,,,.....,,,,::::::::c:cccccccccclllcccclodoollc:,,,:::::::,,,,,::,,,,,:codddoc::codol:ldkkxxk0KXXMMXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMXXXMMMM
+::,,,,,:::clodxxdddddddolox0KK0kdoc,...,,.,,::::cc::,...,,::::::ccclccccloooolc:............................,,,::::::::c::cccccclllllllllooooooollc:::cccc:::,,,,,,,,,,,,::codddo:,:llloloooddxk0XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMXXXXXMMMMM
+:::,,,:cclodxkkOkxdddxxxxxk0KKOdc:,....,,,.,::::::,,...,:::::::ccccccclloodoolc:,...............,,,,.........,,,::::::::::ccccclllloooooooolllc::::::cclc::::,,,,,,,,,,,,,::cdxkdoc::cloodxxxxkOXXKKXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMXXXXXMMMMMM
+,,..,:loodxkkxxxkkkkkkOO000OOkdl,..........,::::,,....,::cc::ccccc:ccclloooooolcc,............,,:,..,.,,.,,.,,,,::::::::::cccclloollcc:,,...,,..........,,,:::,,.,,,,,,,,,,,:ldxkkkdocccldkkkxkKXXKXXXKXXXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMXXXXXXXXMMMM
+,,.,::loxkOOOxddddxOKK0OOKK0Okoc,..........,,,,,,,,,.,,,,:::,,::,ccclooodddollllcol:,,.......,:,,,,,,,,,,,,,,,,,,,::::::::::ccll:::c:,,,.. ...c.............,::,,,,,,,,,,,,::clloxxxxxolddxOOkO0KXXXXXXMXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMXXXXXXXXMMMMM
+,,,,:coxk00OOxolllldxkO00KK0Okol,......,,,,::,,.,,..,,,.,,,,,,,,:clloooodddolllccccccc:,,,,,,:::,::,,,,.,,,,,,,,,,,,:::::,,,.....,::::,,,....,,..............,,,,,,,,,.,,,,::cllldxdxxxkxxxkOO00XXKXXMXXXXXXXXXXXXXXXKKKXXXXXXXXMMMMMMMMMMMMXXXXXXXXMMMMMM
+:::,,:oxOKKOkxol:::coxk00Oxkkkoc,,........,::,........,,,,,,,,::loodddooddollllocc::cllc::,,:cc::::,,::,,.....,,,,,,:::::..,......,,,,,,..,.:c................,,,,,,,..,,,,::clllllldxxkOOkkkkkO0XXXXXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMMXXXXXXXXXXXMMMMM
+:::::cldxkkkxl:,:,:ldxO0KK0kdol:,,....................,,,,..,:clooddddooddoollccccc:,,:lc::::cc:::::,:,,,,..,,....,,,,,,...,,,......,,..,..,:,...  .............,..,,..,,,,,:::cclclloodxOKKK0KKKXXXKXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMMXXMMMMMMMMXXXXXXXX
+,,,,:ldxxddoc:,::cclodkO0Oxdolcc,..................,,:,,....,:ccldxxxxdodddoollccclc:,.,cccccccc:::,,,,,....,,..........,,:::::,.....................,,............,..,,,,,,,,:::ccccclldx0KKKKKXKKXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMXXXMMMMMMMMMMMMMXXXX
+.,,,,coxxxdoc,:codxxxxkkxdolcc:::,................,.,,,,,,,.,,:coddddxdodddooolccccc::,,,:cllccc::,,::,,:,,,.........,,,::cc:::::,................,::::,,,.............,.,,,,,,:::::ccccldxOXXKKXXXXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXX
+,,,,,:ldxxdlc::clodddxxdllc::,,,.............,,......,,,,...,,:codddddooodddollcccc::,,,.,:cllllcc::::::::,,....,,,,,,:::::::::::c::::,......,::::c:::::::,.................,,,,,,:::cccclld0XKXKXXXXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXX
+,,,:cloddolcc:,,:lllcllc::,,,..,,,............................,clddoooolooooollccccc:,,,..,,:ccccc:::::::c:,,...,,::::::::::,,,,,,,:::,,::::,,......,,,,,,,,................,,,,,,:::ccccccox0KK0XMXXXXXXXXXXXXXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXX
+,,..,,collc:,,,.,,:::::::,,.....,..............,,,,,.........,:codddxxdoooooolccccc::,,,...,,::::::,,,::,,,,,,,:,::::ccccc:::,,,,,,,:,,...................,,................,,,,,,,:::cccllok0KKKXMMXXXXXXXXXXXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXKK
+,,,,,clllll:,,:c:,...,,,,,,...,,...............,,,.............,coooooooooooolcc::::::,,,,.,,,::::,,,,,,,::cccccccccccccccccccc:::,,::::,,,,,,,.,,,,....,,,,,,...............,,,,,,::ccclodk00KXXMMMMMXXXXXXXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXK
+..,.,:cccc::,.,,,,..............................,,,............,clooooooolllllllccc::,,.,....,,:cc::,,,:::::cclllllllllllllllllllccccc::::::,,::::,,,,,,,,,,,,,,....,,,,,,,,,,..,,:cclooxkOO0KKXMMMMMMMXXXXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXXX
+....,,,,,,,,.......,,,,,.....,,,................,,..............:loooooooolllllllc:::,,,,,,,....,,::::::::::cclllollllllooooodddddoollllcccccccccccccc::::,,::,,,,,,:::ccc:,,,:clooodxkO0000KXXMMMMMMMMMMMXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXXXX
+.....,,,,,,,,.....,..........................................,,,:clodooooolloolllcc:::,,..,,.....,,::::,:::cccllollodoooooodddddddxxddddddoooooooolllccccc:::::::,,ccccloooolllllclclk0kkkOKKXMMMMMMMMMMMMMXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXX
+.....,,,,,,,,.....,,,,,.....,,..............................,,,::clooollooooollllcc::,,.,.........,,::cc::cclllloodoodxxxxddddddxxxxxxxxxxxxxxxdddolllllllc::,,:,::cccclodddddxxxdxxxxkkO0KXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXKKK
+.....,,.,,,,........,,.....,,............................,::,,,,:llooolloooloolllc:::,,..,,,.....,,,,,,::cclccllooodxxxkkkkkOOOOOOkkOOOOkkkxxxxddoooooolc:,,,,,,::,,:coddxxxxkkkkkkOO000KKXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXKKKK
+.......,,,,,,.....,,.......,............................,,::,,,,:cloollloooololccc::,,,,,,,.........,,:ccclooooddddxxxkkOOOO000000000000000OOkkxxxxddolc::,,::::clodddddxxxkkkkkOOO0KKKKKXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXX
+...................,,..................................,::::::,:lllloolloodollllcc:::,,,.........,,,,cllllooooooooloodddxxxkkOO00000000KKKKKK000OOOxdooddoooddddxdoooodxkOOOOOOO00KKKKKXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXKK
+........,,,,,,....,,,,..................................,::::::cllllllloooooooolcc:,,,,,,,.......,,:::ccllooooolcccllllloodxxkkkOOOOOOOOOOOO000000KKK0OkdddddoddddxxkOO000OO00KKXKKKKXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXXXKK
+.........,,,.......,,....................................,::c:cllolllllollooooolcc:::,,.,...,,,.....,,,:cccccllllllllloodddddxxxkkOOkkkkOOOO000KKKKKKKKK00OOkkkkOOO0000K00KKKXKKKXXXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXXXXX
+..................................................,......,ccllclloooollollllllllcc:,,,,,,,..,,,......,,,,::cclllllllloooooddxxxxxxxxkkOOOOO00000KKKKKKXXXXXXXXXXKKXXXXXXXXXXXXXMXMXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXXXXXX
+.........................................................:clcclloddolllllcccllccccc,.,::,...,,........,,,:ccclllooooooddxdddxxkkkkkkkOOOOOO000000KKKKKKKXXMMXXXXXXXXXXXXXXXXKKKKKKXXXMMMMMMXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXMMXXXXXXXXXXXXX
+.........................................................:cllllllodolllllcccllcclc:,,,,....,,.........,:::ccclllllloooddddxxxkkkkOOkkkkkkOOOO000KK0KKKXXXXXXXXXXKKKKKKKK000KKKK0KXXXMMMMMMXXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXKXX
+..........................,,,............................,cccllloodolclllcc:cclllcc:,..,.,,,,,..,.,,,,,::ccllloollooooddddxxkkkkkkOOOOOOOO000000000KKKKKKKKXXXXKKKKKKKK00000KKXXXXMMMMMMXXKKXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXXXXXX
+.........................................................:cccclloooolccc::::cclllllc::::::,,.......,:ccllllooolllcclooooddxxxkOOOOOOOkOOOOOO00000000000000KKKKKKKKKKK0KK0KKXXXXXMMMMMMXXKKKKXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXX
+..........,,...,,........................................:cccclodddolc:::::,,:lollcc::::::,::,,,,,,cccccolllccccollllodddddxkkOOOOOOOOOkOOOO000000OOOOkkkO00KKKKKKKKKKKKXXXXXXMMXMMMMMXK000KXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXX
+...........,,...........................................,:ccccllooolc:::::,,,:clllllc::::::,,::,,::,,:clcc:ccccccclooddddxxxxkkkkkkkkkkkkkkkkkkkkkkkxxxxkO000KKKKKKKXXXXXXXXXMMMMMMXXXK0OO0KKXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXXX
+.............,,..........................................:ccccclloolcc::c:,,,:::cccccccc::::::,,,,,:::::clool::cccccloddxxxxxxxxxxxxxkxdddxxxxxxxxxxdxxkkkOO00KKKKKKXXXXXXXXMMMMMMXMMXKOkO00KXXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXXXKXX
+.....,...................................................,:cccccloolc:::,,.,,,,:lcccccccc::ccccc:ccc::cldoloolllllllllooddoooddoodddxxdooddddxxxxxxxxxxxkkkOO000KKKKXXXXXXXMMMMXMMXXX0kxxkO00KXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXMXXXXXXXXX
+...,,,..................................................,,:ccc:::cccc:,,,,.....,cclc::ccc::cc:::lcccloooloodddoolc:cllllllloddddxxxxxxxxxkkxxkkkkkxxxxxxkkkO000KKKKXXXXXXXXXXXXXXXXK0kxxkkO000KXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXX
+........................................................,,::::::::ccc:,.........,:lc::::c::ccc:ccclooolcloodddlccccllllloododdxkkkkkkkkxxkkkkkkkkkkkkxxkkOO00KKKKKKXXXXXXXXXXXXXXKK0OkxxkOO000KXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXXXXX
+.........................................................,,,::::,,:clc:,,,.......,:cc::::::::::::clllllloooolc::cclllllllooddxkkkkkkkkxxxxkkkkkkOOOOkkkkOO000KKKKKKKXXXXXXXXXXXXXK0OkkkkkkOOO0KXXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXXXMMMXXXX
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..58c844e
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,19 @@
+use clap::Parser;
+use picture::*;
+use std::path::PathBuf;
+
+mod picture;
+#[derive(Parser)]
+#[command(name = "pascii")]
+#[command(bin_name = "pascii")]
+struct Args {
+ #[arg()]
+ from: PathBuf,
+}
+
+fn main() -> anyhow::Result<()> {
+ let args = Args::parse();
+ let p = image::open(args.from)?;
+ println!("{}", p.text(" ...,:clodxkO0KXM".as_bytes()));
+ Ok(())
+}
diff --git a/src/picture.rs b/src/picture.rs
new file mode 100644
index 0000000..262def0
--- /dev/null
+++ b/src/picture.rs
@@ -0,0 +1,75 @@
+use image::{DynamicImage, GenericImageView, Pixel, Rgb, Rgba};
+#[cfg(rayon)]
+use rayon::prelude::*;
+use rgb2ansi256::rgb_to_ansi256;
+
+macro_rules! fg {
+ ($color:expr,$c:expr) => {
+ format!("\x1b[38;5;{}m{}", $color, $c)
+ };
+}
+
+pub trait ToText {
+ fn text(&self, palette: &[u8]) -> String;
+}
+impl ToText for DynamicImage {
+ fn text(&self, palette: &[u8]) -> String {
+ let p_len = (palette.len() - 1) as f32;
+ let mut output: Vec<String> = vec![];
+ let height = (self.height() / 2) as usize;
+ output.resize(height, String::new());
+ #[cfg(not(rayon))]
+ let iter = output.iter_mut();
+ #[cfg(rayon)]
+ let iter = output.par_iter_mut();
+ iter.enumerate().for_each(|(mut y, output)| {
+ y <<= 1;
+ let mut last_p: Option<Rgba<u8>> = None;
+ for x in 0..self.width() {
+ let p = unsafe { self.unsafe_get_pixel(x, y as u32) };
+ let y = p.to_luma()[0] as f32 / 255_f32;
+ let a = i2range(p[3]);
+ let pos = (p_len * y).round();
+ let i: usize = (pos * a).round() as usize;
+ let ch = palette[i] as char;
+ if let Some(last) = last_p {
+ if last == p {
+ output.push(ch);
+ continue;
+ }
+ }
+ let color = p.to_rgb().ansi_256();
+ last_p = Some(p);
+ output.push_str(&fg!(color, ch));
+ }
+ });
+ output.join("\n")
+ }
+}
+
+trait Ansi256 {
+ fn ansi_256(&self) -> u8;
+}
+
+impl Ansi256 for Rgb<u8> {
+ fn ansi_256(&self) -> u8 {
+ rgb_to_ansi256(self[0], self[1], self[2])
+ }
+}
+
+fn i2range(i: u8) -> f32 {
+ (i as f32 / u8::MAX as f32).clamp(0.0, 1.0)
+}
+
+#[test]
+fn ansi_color() {
+ macro_rules! test {
+ ($c:expr, $expect:expr) => {{
+ let args: [u8; 3] = $c;
+ assert_eq!(Rgb::from(args).ansi_256(), $expect)
+ }};
+ }
+ test!([0, 0, 255], 21);
+ test!([0, 255, 0], 46);
+ test!([255, 0, 0], 196);
+}