├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── flake.lock ├── flake.nix ├── images ├── dipc_dark.png ├── dipc_examples.png └── dipc_light.png └── src ├── cli.rs ├── config.rs ├── delta.rs ├── main.rs ├── palettes.rs └── palettes ├── catppuccin.json ├── dracula.json ├── edge.json ├── everforest.json ├── gruvbox-material.json ├── gruvbox.json ├── nord.json ├── onedark.json ├── rose-pine.json ├── solarized.json └── tokyo-night.json /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | # Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "adler2" 7 | version = "2.0.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 10 | 11 | [[package]] 12 | name = "aligned-vec" 13 | version = "0.5.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" 16 | 17 | [[package]] 18 | name = "anstream" 19 | version = "0.6.18" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 22 | dependencies = [ 23 | "anstyle", 24 | "anstyle-parse", 25 | "anstyle-query", 26 | "anstyle-wincon", 27 | "colorchoice", 28 | "is_terminal_polyfill", 29 | "utf8parse", 30 | ] 31 | 32 | [[package]] 33 | name = "anstyle" 34 | version = "1.0.10" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 37 | 38 | [[package]] 39 | name = "anstyle-parse" 40 | version = "0.2.6" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 43 | dependencies = [ 44 | "utf8parse", 45 | ] 46 | 47 | [[package]] 48 | name = "anstyle-query" 49 | version = "1.1.2" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 52 | dependencies = [ 53 | "windows-sys", 54 | ] 55 | 56 | [[package]] 57 | name = "anstyle-wincon" 58 | version = "3.0.7" 59 | source = "registry+https://github.com/rust-lang/crates.io-index" 60 | checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" 61 | dependencies = [ 62 | "anstyle", 63 | "once_cell", 64 | "windows-sys", 65 | ] 66 | 67 | [[package]] 68 | name = "anyhow" 69 | version = "1.0.98" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" 72 | 73 | [[package]] 74 | name = "arbitrary" 75 | version = "1.4.1" 76 | source = "registry+https://github.com/rust-lang/crates.io-index" 77 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" 78 | 79 | [[package]] 80 | name = "arg_enum_proc_macro" 81 | version = "0.3.4" 82 | source = "registry+https://github.com/rust-lang/crates.io-index" 83 | checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" 84 | dependencies = [ 85 | "proc-macro2", 86 | "quote", 87 | "syn", 88 | ] 89 | 90 | [[package]] 91 | name = "arrayvec" 92 | version = "0.7.6" 93 | source = "registry+https://github.com/rust-lang/crates.io-index" 94 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 95 | 96 | [[package]] 97 | name = "autocfg" 98 | version = "1.4.0" 99 | source = "registry+https://github.com/rust-lang/crates.io-index" 100 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 101 | 102 | [[package]] 103 | name = "av1-grain" 104 | version = "0.2.3" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" 107 | dependencies = [ 108 | "anyhow", 109 | "arrayvec", 110 | "log", 111 | "nom", 112 | "num-rational", 113 | "v_frame", 114 | ] 115 | 116 | [[package]] 117 | name = "avif-serialize" 118 | version = "0.8.3" 119 | source = "registry+https://github.com/rust-lang/crates.io-index" 120 | checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e" 121 | dependencies = [ 122 | "arrayvec", 123 | ] 124 | 125 | [[package]] 126 | name = "bit_field" 127 | version = "0.10.2" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" 130 | 131 | [[package]] 132 | name = "bitflags" 133 | version = "1.3.2" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 136 | 137 | [[package]] 138 | name = "bitflags" 139 | version = "2.9.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 142 | 143 | [[package]] 144 | name = "bitstream-io" 145 | version = "2.6.0" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" 148 | 149 | [[package]] 150 | name = "built" 151 | version = "0.7.7" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b" 154 | 155 | [[package]] 156 | name = "bumpalo" 157 | version = "3.17.0" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 160 | 161 | [[package]] 162 | name = "bytemuck" 163 | version = "1.22.0" 164 | source = "registry+https://github.com/rust-lang/crates.io-index" 165 | checksum = "b6b1fc10dbac614ebc03540c9dbd60e83887fda27794998c6528f1782047d540" 166 | 167 | [[package]] 168 | name = "byteorder-lite" 169 | version = "0.1.0" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" 172 | 173 | [[package]] 174 | name = "cc" 175 | version = "1.2.19" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" 178 | dependencies = [ 179 | "jobserver", 180 | "libc", 181 | "shlex", 182 | ] 183 | 184 | [[package]] 185 | name = "cfg-expr" 186 | version = "0.15.8" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" 189 | dependencies = [ 190 | "smallvec", 191 | "target-lexicon", 192 | ] 193 | 194 | [[package]] 195 | name = "cfg-if" 196 | version = "1.0.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 199 | 200 | [[package]] 201 | name = "clap" 202 | version = "4.5.37" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" 205 | dependencies = [ 206 | "clap_builder", 207 | "clap_derive", 208 | ] 209 | 210 | [[package]] 211 | name = "clap_builder" 212 | version = "4.5.37" 213 | source = "registry+https://github.com/rust-lang/crates.io-index" 214 | checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" 215 | dependencies = [ 216 | "anstream", 217 | "anstyle", 218 | "clap_lex", 219 | "strsim", 220 | ] 221 | 222 | [[package]] 223 | name = "clap_derive" 224 | version = "4.5.32" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" 227 | dependencies = [ 228 | "heck", 229 | "proc-macro2", 230 | "quote", 231 | "syn", 232 | ] 233 | 234 | [[package]] 235 | name = "clap_lex" 236 | version = "0.7.4" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" 239 | 240 | [[package]] 241 | name = "color_quant" 242 | version = "1.1.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 245 | 246 | [[package]] 247 | name = "colorchoice" 248 | version = "1.0.3" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 251 | 252 | [[package]] 253 | name = "console" 254 | version = "0.15.11" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8" 257 | dependencies = [ 258 | "encode_unicode", 259 | "libc", 260 | "once_cell", 261 | "unicode-width", 262 | "windows-sys", 263 | ] 264 | 265 | [[package]] 266 | name = "crc32fast" 267 | version = "1.4.2" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 270 | dependencies = [ 271 | "cfg-if", 272 | ] 273 | 274 | [[package]] 275 | name = "crossbeam-deque" 276 | version = "0.8.6" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" 279 | dependencies = [ 280 | "crossbeam-epoch", 281 | "crossbeam-utils", 282 | ] 283 | 284 | [[package]] 285 | name = "crossbeam-epoch" 286 | version = "0.9.18" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 289 | dependencies = [ 290 | "crossbeam-utils", 291 | ] 292 | 293 | [[package]] 294 | name = "crossbeam-utils" 295 | version = "0.8.21" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" 298 | 299 | [[package]] 300 | name = "crunchy" 301 | version = "0.2.3" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" 304 | 305 | [[package]] 306 | name = "deltae" 307 | version = "0.3.2" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" 310 | 311 | [[package]] 312 | name = "dipc" 313 | version = "1.0.0" 314 | dependencies = [ 315 | "clap", 316 | "deltae", 317 | "image", 318 | "indicatif", 319 | "lab", 320 | "owo-colors", 321 | "rayon", 322 | "serde_json", 323 | "supports-color 3.0.2", 324 | ] 325 | 326 | [[package]] 327 | name = "either" 328 | version = "1.15.0" 329 | source = "registry+https://github.com/rust-lang/crates.io-index" 330 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 331 | 332 | [[package]] 333 | name = "encode_unicode" 334 | version = "1.0.0" 335 | source = "registry+https://github.com/rust-lang/crates.io-index" 336 | checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" 337 | 338 | [[package]] 339 | name = "equivalent" 340 | version = "1.0.2" 341 | source = "registry+https://github.com/rust-lang/crates.io-index" 342 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 343 | 344 | [[package]] 345 | name = "exr" 346 | version = "1.73.0" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" 349 | dependencies = [ 350 | "bit_field", 351 | "half", 352 | "lebe", 353 | "miniz_oxide", 354 | "rayon-core", 355 | "smallvec", 356 | "zune-inflate", 357 | ] 358 | 359 | [[package]] 360 | name = "fdeflate" 361 | version = "0.3.7" 362 | source = "registry+https://github.com/rust-lang/crates.io-index" 363 | checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" 364 | dependencies = [ 365 | "simd-adler32", 366 | ] 367 | 368 | [[package]] 369 | name = "flate2" 370 | version = "1.1.1" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" 373 | dependencies = [ 374 | "crc32fast", 375 | "miniz_oxide", 376 | ] 377 | 378 | [[package]] 379 | name = "getrandom" 380 | version = "0.2.16" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" 383 | dependencies = [ 384 | "cfg-if", 385 | "libc", 386 | "wasi 0.11.0+wasi-snapshot-preview1", 387 | ] 388 | 389 | [[package]] 390 | name = "getrandom" 391 | version = "0.3.2" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 394 | dependencies = [ 395 | "cfg-if", 396 | "libc", 397 | "r-efi", 398 | "wasi 0.14.2+wasi-0.2.4", 399 | ] 400 | 401 | [[package]] 402 | name = "gif" 403 | version = "0.13.1" 404 | source = "registry+https://github.com/rust-lang/crates.io-index" 405 | checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" 406 | dependencies = [ 407 | "color_quant", 408 | "weezl", 409 | ] 410 | 411 | [[package]] 412 | name = "half" 413 | version = "2.6.0" 414 | source = "registry+https://github.com/rust-lang/crates.io-index" 415 | checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" 416 | dependencies = [ 417 | "cfg-if", 418 | "crunchy", 419 | ] 420 | 421 | [[package]] 422 | name = "hashbrown" 423 | version = "0.15.2" 424 | source = "registry+https://github.com/rust-lang/crates.io-index" 425 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 426 | 427 | [[package]] 428 | name = "heck" 429 | version = "0.5.0" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 432 | 433 | [[package]] 434 | name = "hermit-abi" 435 | version = "0.5.0" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e" 438 | 439 | [[package]] 440 | name = "image" 441 | version = "0.25.6" 442 | source = "registry+https://github.com/rust-lang/crates.io-index" 443 | checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" 444 | dependencies = [ 445 | "bytemuck", 446 | "byteorder-lite", 447 | "color_quant", 448 | "exr", 449 | "gif", 450 | "image-webp", 451 | "num-traits", 452 | "png", 453 | "qoi", 454 | "ravif", 455 | "rayon", 456 | "rgb", 457 | "tiff", 458 | "zune-core", 459 | "zune-jpeg", 460 | ] 461 | 462 | [[package]] 463 | name = "image-webp" 464 | version = "0.2.1" 465 | source = "registry+https://github.com/rust-lang/crates.io-index" 466 | checksum = "b77d01e822461baa8409e156015a1d91735549f0f2c17691bd2d996bef238f7f" 467 | dependencies = [ 468 | "byteorder-lite", 469 | "quick-error", 470 | ] 471 | 472 | [[package]] 473 | name = "imgref" 474 | version = "1.11.0" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" 477 | 478 | [[package]] 479 | name = "indexmap" 480 | version = "2.9.0" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" 483 | dependencies = [ 484 | "equivalent", 485 | "hashbrown", 486 | ] 487 | 488 | [[package]] 489 | name = "indicatif" 490 | version = "0.17.11" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" 493 | dependencies = [ 494 | "console", 495 | "number_prefix", 496 | "portable-atomic", 497 | "rayon", 498 | "unicode-width", 499 | "web-time", 500 | ] 501 | 502 | [[package]] 503 | name = "interpolate_name" 504 | version = "0.2.4" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" 507 | dependencies = [ 508 | "proc-macro2", 509 | "quote", 510 | "syn", 511 | ] 512 | 513 | [[package]] 514 | name = "is-terminal" 515 | version = "0.4.16" 516 | source = "registry+https://github.com/rust-lang/crates.io-index" 517 | checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" 518 | dependencies = [ 519 | "hermit-abi", 520 | "libc", 521 | "windows-sys", 522 | ] 523 | 524 | [[package]] 525 | name = "is_ci" 526 | version = "1.2.0" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" 529 | 530 | [[package]] 531 | name = "is_terminal_polyfill" 532 | version = "1.70.1" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 535 | 536 | [[package]] 537 | name = "itertools" 538 | version = "0.12.1" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 541 | dependencies = [ 542 | "either", 543 | ] 544 | 545 | [[package]] 546 | name = "itoa" 547 | version = "1.0.15" 548 | source = "registry+https://github.com/rust-lang/crates.io-index" 549 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 550 | 551 | [[package]] 552 | name = "jobserver" 553 | version = "0.1.33" 554 | source = "registry+https://github.com/rust-lang/crates.io-index" 555 | checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" 556 | dependencies = [ 557 | "getrandom 0.3.2", 558 | "libc", 559 | ] 560 | 561 | [[package]] 562 | name = "jpeg-decoder" 563 | version = "0.3.1" 564 | source = "registry+https://github.com/rust-lang/crates.io-index" 565 | checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" 566 | 567 | [[package]] 568 | name = "js-sys" 569 | version = "0.3.77" 570 | source = "registry+https://github.com/rust-lang/crates.io-index" 571 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 572 | dependencies = [ 573 | "once_cell", 574 | "wasm-bindgen", 575 | ] 576 | 577 | [[package]] 578 | name = "lab" 579 | version = "0.11.0" 580 | source = "registry+https://github.com/rust-lang/crates.io-index" 581 | checksum = "bf36173d4167ed999940f804952e6b08197cae5ad5d572eb4db150ce8ad5d58f" 582 | 583 | [[package]] 584 | name = "lebe" 585 | version = "0.5.2" 586 | source = "registry+https://github.com/rust-lang/crates.io-index" 587 | checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" 588 | 589 | [[package]] 590 | name = "libc" 591 | version = "0.2.172" 592 | source = "registry+https://github.com/rust-lang/crates.io-index" 593 | checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" 594 | 595 | [[package]] 596 | name = "libfuzzer-sys" 597 | version = "0.4.9" 598 | source = "registry+https://github.com/rust-lang/crates.io-index" 599 | checksum = "cf78f52d400cf2d84a3a973a78a592b4adc535739e0a5597a0da6f0c357adc75" 600 | dependencies = [ 601 | "arbitrary", 602 | "cc", 603 | ] 604 | 605 | [[package]] 606 | name = "log" 607 | version = "0.4.27" 608 | source = "registry+https://github.com/rust-lang/crates.io-index" 609 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 610 | 611 | [[package]] 612 | name = "loop9" 613 | version = "0.1.5" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" 616 | dependencies = [ 617 | "imgref", 618 | ] 619 | 620 | [[package]] 621 | name = "maybe-rayon" 622 | version = "0.1.1" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" 625 | dependencies = [ 626 | "cfg-if", 627 | "rayon", 628 | ] 629 | 630 | [[package]] 631 | name = "memchr" 632 | version = "2.7.4" 633 | source = "registry+https://github.com/rust-lang/crates.io-index" 634 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 635 | 636 | [[package]] 637 | name = "minimal-lexical" 638 | version = "0.2.1" 639 | source = "registry+https://github.com/rust-lang/crates.io-index" 640 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 641 | 642 | [[package]] 643 | name = "miniz_oxide" 644 | version = "0.8.8" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" 647 | dependencies = [ 648 | "adler2", 649 | "simd-adler32", 650 | ] 651 | 652 | [[package]] 653 | name = "new_debug_unreachable" 654 | version = "1.0.6" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 657 | 658 | [[package]] 659 | name = "nom" 660 | version = "7.1.3" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 663 | dependencies = [ 664 | "memchr", 665 | "minimal-lexical", 666 | ] 667 | 668 | [[package]] 669 | name = "noop_proc_macro" 670 | version = "0.3.0" 671 | source = "registry+https://github.com/rust-lang/crates.io-index" 672 | checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" 673 | 674 | [[package]] 675 | name = "num-bigint" 676 | version = "0.4.6" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 679 | dependencies = [ 680 | "num-integer", 681 | "num-traits", 682 | ] 683 | 684 | [[package]] 685 | name = "num-derive" 686 | version = "0.4.2" 687 | source = "registry+https://github.com/rust-lang/crates.io-index" 688 | checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" 689 | dependencies = [ 690 | "proc-macro2", 691 | "quote", 692 | "syn", 693 | ] 694 | 695 | [[package]] 696 | name = "num-integer" 697 | version = "0.1.46" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 700 | dependencies = [ 701 | "num-traits", 702 | ] 703 | 704 | [[package]] 705 | name = "num-rational" 706 | version = "0.4.2" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 709 | dependencies = [ 710 | "num-bigint", 711 | "num-integer", 712 | "num-traits", 713 | ] 714 | 715 | [[package]] 716 | name = "num-traits" 717 | version = "0.2.19" 718 | source = "registry+https://github.com/rust-lang/crates.io-index" 719 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 720 | dependencies = [ 721 | "autocfg", 722 | ] 723 | 724 | [[package]] 725 | name = "number_prefix" 726 | version = "0.4.0" 727 | source = "registry+https://github.com/rust-lang/crates.io-index" 728 | checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" 729 | 730 | [[package]] 731 | name = "once_cell" 732 | version = "1.21.3" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 735 | 736 | [[package]] 737 | name = "owo-colors" 738 | version = "4.2.0" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564" 741 | dependencies = [ 742 | "supports-color 2.1.0", 743 | "supports-color 3.0.2", 744 | ] 745 | 746 | [[package]] 747 | name = "paste" 748 | version = "1.0.15" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 751 | 752 | [[package]] 753 | name = "pkg-config" 754 | version = "0.3.32" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" 757 | 758 | [[package]] 759 | name = "png" 760 | version = "0.17.16" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" 763 | dependencies = [ 764 | "bitflags 1.3.2", 765 | "crc32fast", 766 | "fdeflate", 767 | "flate2", 768 | "miniz_oxide", 769 | ] 770 | 771 | [[package]] 772 | name = "portable-atomic" 773 | version = "1.11.0" 774 | source = "registry+https://github.com/rust-lang/crates.io-index" 775 | checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e" 776 | 777 | [[package]] 778 | name = "ppv-lite86" 779 | version = "0.2.21" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 782 | dependencies = [ 783 | "zerocopy", 784 | ] 785 | 786 | [[package]] 787 | name = "proc-macro2" 788 | version = "1.0.95" 789 | source = "registry+https://github.com/rust-lang/crates.io-index" 790 | checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" 791 | dependencies = [ 792 | "unicode-ident", 793 | ] 794 | 795 | [[package]] 796 | name = "profiling" 797 | version = "1.0.16" 798 | source = "registry+https://github.com/rust-lang/crates.io-index" 799 | checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" 800 | dependencies = [ 801 | "profiling-procmacros", 802 | ] 803 | 804 | [[package]] 805 | name = "profiling-procmacros" 806 | version = "1.0.16" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" 809 | dependencies = [ 810 | "quote", 811 | "syn", 812 | ] 813 | 814 | [[package]] 815 | name = "qoi" 816 | version = "0.4.1" 817 | source = "registry+https://github.com/rust-lang/crates.io-index" 818 | checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" 819 | dependencies = [ 820 | "bytemuck", 821 | ] 822 | 823 | [[package]] 824 | name = "quick-error" 825 | version = "2.0.1" 826 | source = "registry+https://github.com/rust-lang/crates.io-index" 827 | checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" 828 | 829 | [[package]] 830 | name = "quote" 831 | version = "1.0.40" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 834 | dependencies = [ 835 | "proc-macro2", 836 | ] 837 | 838 | [[package]] 839 | name = "r-efi" 840 | version = "5.2.0" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 843 | 844 | [[package]] 845 | name = "rand" 846 | version = "0.8.5" 847 | source = "registry+https://github.com/rust-lang/crates.io-index" 848 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 849 | dependencies = [ 850 | "libc", 851 | "rand_chacha", 852 | "rand_core", 853 | ] 854 | 855 | [[package]] 856 | name = "rand_chacha" 857 | version = "0.3.1" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 860 | dependencies = [ 861 | "ppv-lite86", 862 | "rand_core", 863 | ] 864 | 865 | [[package]] 866 | name = "rand_core" 867 | version = "0.6.4" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 870 | dependencies = [ 871 | "getrandom 0.2.16", 872 | ] 873 | 874 | [[package]] 875 | name = "rav1e" 876 | version = "0.7.1" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" 879 | dependencies = [ 880 | "arbitrary", 881 | "arg_enum_proc_macro", 882 | "arrayvec", 883 | "av1-grain", 884 | "bitstream-io", 885 | "built", 886 | "cfg-if", 887 | "interpolate_name", 888 | "itertools", 889 | "libc", 890 | "libfuzzer-sys", 891 | "log", 892 | "maybe-rayon", 893 | "new_debug_unreachable", 894 | "noop_proc_macro", 895 | "num-derive", 896 | "num-traits", 897 | "once_cell", 898 | "paste", 899 | "profiling", 900 | "rand", 901 | "rand_chacha", 902 | "simd_helpers", 903 | "system-deps", 904 | "thiserror", 905 | "v_frame", 906 | "wasm-bindgen", 907 | ] 908 | 909 | [[package]] 910 | name = "ravif" 911 | version = "0.11.12" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "d6a5f31fcf7500f9401fea858ea4ab5525c99f2322cfcee732c0e6c74208c0c6" 914 | dependencies = [ 915 | "avif-serialize", 916 | "imgref", 917 | "loop9", 918 | "quick-error", 919 | "rav1e", 920 | "rayon", 921 | "rgb", 922 | ] 923 | 924 | [[package]] 925 | name = "rayon" 926 | version = "1.10.0" 927 | source = "registry+https://github.com/rust-lang/crates.io-index" 928 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 929 | dependencies = [ 930 | "either", 931 | "rayon-core", 932 | ] 933 | 934 | [[package]] 935 | name = "rayon-core" 936 | version = "1.12.1" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 939 | dependencies = [ 940 | "crossbeam-deque", 941 | "crossbeam-utils", 942 | ] 943 | 944 | [[package]] 945 | name = "rgb" 946 | version = "0.8.50" 947 | source = "registry+https://github.com/rust-lang/crates.io-index" 948 | checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" 949 | 950 | [[package]] 951 | name = "rustversion" 952 | version = "1.0.20" 953 | source = "registry+https://github.com/rust-lang/crates.io-index" 954 | checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" 955 | 956 | [[package]] 957 | name = "ryu" 958 | version = "1.0.20" 959 | source = "registry+https://github.com/rust-lang/crates.io-index" 960 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" 961 | 962 | [[package]] 963 | name = "serde" 964 | version = "1.0.219" 965 | source = "registry+https://github.com/rust-lang/crates.io-index" 966 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 967 | dependencies = [ 968 | "serde_derive", 969 | ] 970 | 971 | [[package]] 972 | name = "serde_derive" 973 | version = "1.0.219" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 976 | dependencies = [ 977 | "proc-macro2", 978 | "quote", 979 | "syn", 980 | ] 981 | 982 | [[package]] 983 | name = "serde_json" 984 | version = "1.0.140" 985 | source = "registry+https://github.com/rust-lang/crates.io-index" 986 | checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" 987 | dependencies = [ 988 | "indexmap", 989 | "itoa", 990 | "memchr", 991 | "ryu", 992 | "serde", 993 | ] 994 | 995 | [[package]] 996 | name = "serde_spanned" 997 | version = "0.6.8" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 1000 | dependencies = [ 1001 | "serde", 1002 | ] 1003 | 1004 | [[package]] 1005 | name = "shlex" 1006 | version = "1.3.0" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 1009 | 1010 | [[package]] 1011 | name = "simd-adler32" 1012 | version = "0.3.7" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 1015 | 1016 | [[package]] 1017 | name = "simd_helpers" 1018 | version = "0.1.0" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" 1021 | dependencies = [ 1022 | "quote", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "smallvec" 1027 | version = "1.15.0" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" 1030 | 1031 | [[package]] 1032 | name = "strsim" 1033 | version = "0.11.1" 1034 | source = "registry+https://github.com/rust-lang/crates.io-index" 1035 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 1036 | 1037 | [[package]] 1038 | name = "supports-color" 1039 | version = "2.1.0" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" 1042 | dependencies = [ 1043 | "is-terminal", 1044 | "is_ci", 1045 | ] 1046 | 1047 | [[package]] 1048 | name = "supports-color" 1049 | version = "3.0.2" 1050 | source = "registry+https://github.com/rust-lang/crates.io-index" 1051 | checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" 1052 | dependencies = [ 1053 | "is_ci", 1054 | ] 1055 | 1056 | [[package]] 1057 | name = "syn" 1058 | version = "2.0.100" 1059 | source = "registry+https://github.com/rust-lang/crates.io-index" 1060 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 1061 | dependencies = [ 1062 | "proc-macro2", 1063 | "quote", 1064 | "unicode-ident", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "system-deps" 1069 | version = "6.2.2" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" 1072 | dependencies = [ 1073 | "cfg-expr", 1074 | "heck", 1075 | "pkg-config", 1076 | "toml", 1077 | "version-compare", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "target-lexicon" 1082 | version = "0.12.16" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" 1085 | 1086 | [[package]] 1087 | name = "thiserror" 1088 | version = "1.0.69" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 1091 | dependencies = [ 1092 | "thiserror-impl", 1093 | ] 1094 | 1095 | [[package]] 1096 | name = "thiserror-impl" 1097 | version = "1.0.69" 1098 | source = "registry+https://github.com/rust-lang/crates.io-index" 1099 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 1100 | dependencies = [ 1101 | "proc-macro2", 1102 | "quote", 1103 | "syn", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "tiff" 1108 | version = "0.9.1" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" 1111 | dependencies = [ 1112 | "flate2", 1113 | "jpeg-decoder", 1114 | "weezl", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "toml" 1119 | version = "0.8.20" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" 1122 | dependencies = [ 1123 | "serde", 1124 | "serde_spanned", 1125 | "toml_datetime", 1126 | "toml_edit", 1127 | ] 1128 | 1129 | [[package]] 1130 | name = "toml_datetime" 1131 | version = "0.6.8" 1132 | source = "registry+https://github.com/rust-lang/crates.io-index" 1133 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 1134 | dependencies = [ 1135 | "serde", 1136 | ] 1137 | 1138 | [[package]] 1139 | name = "toml_edit" 1140 | version = "0.22.24" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" 1143 | dependencies = [ 1144 | "indexmap", 1145 | "serde", 1146 | "serde_spanned", 1147 | "toml_datetime", 1148 | "winnow", 1149 | ] 1150 | 1151 | [[package]] 1152 | name = "unicode-ident" 1153 | version = "1.0.18" 1154 | source = "registry+https://github.com/rust-lang/crates.io-index" 1155 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 1156 | 1157 | [[package]] 1158 | name = "unicode-width" 1159 | version = "0.2.0" 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" 1161 | checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" 1162 | 1163 | [[package]] 1164 | name = "utf8parse" 1165 | version = "0.2.2" 1166 | source = "registry+https://github.com/rust-lang/crates.io-index" 1167 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 1168 | 1169 | [[package]] 1170 | name = "v_frame" 1171 | version = "0.3.8" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" 1174 | dependencies = [ 1175 | "aligned-vec", 1176 | "num-traits", 1177 | "wasm-bindgen", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "version-compare" 1182 | version = "0.2.0" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" 1185 | 1186 | [[package]] 1187 | name = "wasi" 1188 | version = "0.11.0+wasi-snapshot-preview1" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1191 | 1192 | [[package]] 1193 | name = "wasi" 1194 | version = "0.14.2+wasi-0.2.4" 1195 | source = "registry+https://github.com/rust-lang/crates.io-index" 1196 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 1197 | dependencies = [ 1198 | "wit-bindgen-rt", 1199 | ] 1200 | 1201 | [[package]] 1202 | name = "wasm-bindgen" 1203 | version = "0.2.100" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 1206 | dependencies = [ 1207 | "cfg-if", 1208 | "once_cell", 1209 | "rustversion", 1210 | "wasm-bindgen-macro", 1211 | ] 1212 | 1213 | [[package]] 1214 | name = "wasm-bindgen-backend" 1215 | version = "0.2.100" 1216 | source = "registry+https://github.com/rust-lang/crates.io-index" 1217 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 1218 | dependencies = [ 1219 | "bumpalo", 1220 | "log", 1221 | "proc-macro2", 1222 | "quote", 1223 | "syn", 1224 | "wasm-bindgen-shared", 1225 | ] 1226 | 1227 | [[package]] 1228 | name = "wasm-bindgen-macro" 1229 | version = "0.2.100" 1230 | source = "registry+https://github.com/rust-lang/crates.io-index" 1231 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 1232 | dependencies = [ 1233 | "quote", 1234 | "wasm-bindgen-macro-support", 1235 | ] 1236 | 1237 | [[package]] 1238 | name = "wasm-bindgen-macro-support" 1239 | version = "0.2.100" 1240 | source = "registry+https://github.com/rust-lang/crates.io-index" 1241 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 1242 | dependencies = [ 1243 | "proc-macro2", 1244 | "quote", 1245 | "syn", 1246 | "wasm-bindgen-backend", 1247 | "wasm-bindgen-shared", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "wasm-bindgen-shared" 1252 | version = "0.2.100" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 1255 | dependencies = [ 1256 | "unicode-ident", 1257 | ] 1258 | 1259 | [[package]] 1260 | name = "web-time" 1261 | version = "1.1.0" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1264 | dependencies = [ 1265 | "js-sys", 1266 | "wasm-bindgen", 1267 | ] 1268 | 1269 | [[package]] 1270 | name = "weezl" 1271 | version = "0.1.8" 1272 | source = "registry+https://github.com/rust-lang/crates.io-index" 1273 | checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" 1274 | 1275 | [[package]] 1276 | name = "windows-sys" 1277 | version = "0.59.0" 1278 | source = "registry+https://github.com/rust-lang/crates.io-index" 1279 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 1280 | dependencies = [ 1281 | "windows-targets", 1282 | ] 1283 | 1284 | [[package]] 1285 | name = "windows-targets" 1286 | version = "0.52.6" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1289 | dependencies = [ 1290 | "windows_aarch64_gnullvm", 1291 | "windows_aarch64_msvc", 1292 | "windows_i686_gnu", 1293 | "windows_i686_gnullvm", 1294 | "windows_i686_msvc", 1295 | "windows_x86_64_gnu", 1296 | "windows_x86_64_gnullvm", 1297 | "windows_x86_64_msvc", 1298 | ] 1299 | 1300 | [[package]] 1301 | name = "windows_aarch64_gnullvm" 1302 | version = "0.52.6" 1303 | source = "registry+https://github.com/rust-lang/crates.io-index" 1304 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1305 | 1306 | [[package]] 1307 | name = "windows_aarch64_msvc" 1308 | version = "0.52.6" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1311 | 1312 | [[package]] 1313 | name = "windows_i686_gnu" 1314 | version = "0.52.6" 1315 | source = "registry+https://github.com/rust-lang/crates.io-index" 1316 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1317 | 1318 | [[package]] 1319 | name = "windows_i686_gnullvm" 1320 | version = "0.52.6" 1321 | source = "registry+https://github.com/rust-lang/crates.io-index" 1322 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1323 | 1324 | [[package]] 1325 | name = "windows_i686_msvc" 1326 | version = "0.52.6" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1329 | 1330 | [[package]] 1331 | name = "windows_x86_64_gnu" 1332 | version = "0.52.6" 1333 | source = "registry+https://github.com/rust-lang/crates.io-index" 1334 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1335 | 1336 | [[package]] 1337 | name = "windows_x86_64_gnullvm" 1338 | version = "0.52.6" 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" 1340 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1341 | 1342 | [[package]] 1343 | name = "windows_x86_64_msvc" 1344 | version = "0.52.6" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1347 | 1348 | [[package]] 1349 | name = "winnow" 1350 | version = "0.7.6" 1351 | source = "registry+https://github.com/rust-lang/crates.io-index" 1352 | checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" 1353 | dependencies = [ 1354 | "memchr", 1355 | ] 1356 | 1357 | [[package]] 1358 | name = "wit-bindgen-rt" 1359 | version = "0.39.0" 1360 | source = "registry+https://github.com/rust-lang/crates.io-index" 1361 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 1362 | dependencies = [ 1363 | "bitflags 2.9.0", 1364 | ] 1365 | 1366 | [[package]] 1367 | name = "zerocopy" 1368 | version = "0.8.24" 1369 | source = "registry+https://github.com/rust-lang/crates.io-index" 1370 | checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" 1371 | dependencies = [ 1372 | "zerocopy-derive", 1373 | ] 1374 | 1375 | [[package]] 1376 | name = "zerocopy-derive" 1377 | version = "0.8.24" 1378 | source = "registry+https://github.com/rust-lang/crates.io-index" 1379 | checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" 1380 | dependencies = [ 1381 | "proc-macro2", 1382 | "quote", 1383 | "syn", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "zune-core" 1388 | version = "0.4.12" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" 1391 | 1392 | [[package]] 1393 | name = "zune-inflate" 1394 | version = "0.2.54" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" 1397 | dependencies = [ 1398 | "simd-adler32", 1399 | ] 1400 | 1401 | [[package]] 1402 | name = "zune-jpeg" 1403 | version = "0.4.14" 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" 1405 | checksum = "99a5bab8d7dedf81405c4bb1f2b83ea057643d9cb28778cea9eecddeedd2e028" 1406 | dependencies = [ 1407 | "zune-core", 1408 | ] 1409 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dipc" 3 | version = "1.0.0" 4 | edition = "2021" 5 | description = "Convert your favorite images and wallpapers with your favorite color palettes/themes" 6 | homepage = "https://github.com/doprz/dipc" 7 | repository = "https://github.com/doprz/dipc" 8 | readme = "README.md" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["cli", "graphics", "utility", "image", "tool"] 11 | categories = [ 12 | "command-line-interface", 13 | "command-line-utilities", 14 | "graphics", 15 | "multimedia::images", 16 | "rendering", 17 | ] 18 | 19 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 20 | 21 | [dependencies] 22 | clap = { version = "4.5", features = ["derive"] } 23 | serde_json = { version = "1.0", features = ["preserve_order"] } 24 | image = { version = "0.25" } 25 | deltae = "0.3" 26 | lab = "0.11" 27 | owo-colors = { version = "4.2", features = ["supports-colors"] } 28 | supports-color = "3.0" 29 | rayon = "1.10" 30 | indicatif = { version = "0.17", features = ["rayon"] } 31 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 doprz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dipc 2 | 3 | [![crates.io](https://img.shields.io/crates/v/dipc)](https://crates.io/crates/dipc) 4 | [![Homebrew](https://img.shields.io/homebrew/v/dipc)](https://formulae.brew.sh/formula/dipc) 5 | 6 | 7 | 8 | dipc light icon 9 | 10 | 11 | doprz' image palette converter 12 | 13 | Convert your favorite images and wallpapers with your favorite color palettes/themes 14 | 15 | ## Color Palettes/Themes 16 | 17 | - catppuccin 18 | - dracula 19 | - edge 20 | - everforest 21 | - gruvbox 22 | - gruvbox-material 23 | - nord 24 | - onedark 25 | - rose-pine 26 | - solarized 27 | - tokyo-night 28 | 29 | ## Examples 30 | 31 | ![dipc examples](images/dipc_examples.png) 32 | 33 | ### Image Credits 34 | 35 | Paul Bill - [https://unsplash.com/@hoffman11](https://unsplash.com/@hoffman11) 36 | 37 | Adrien Vajas - [https://unsplash.com/@adrien_vj](https://unsplash.com/@adrien_vj) 38 | 39 | Filipp Romanovski - [https://unsplash.com/@filipp_roman_photography](https://unsplash.com/@filipp_roman_photography) 40 | 41 | ## Installation 42 | 43 | ### Homebrew 44 | 45 | ```sh 46 | brew install dipc 47 | ``` 48 | 49 | ### Cargo 50 | 51 | ```sh 52 | cargo install dipc 53 | ``` 54 | 55 | ### From Source 56 | 57 | To build and install from source, first checkout the tag or branch you want to install, then run 58 | 59 | ```sh 60 | cargo install --path . 61 | ``` 62 | 63 | This will build and install `dipc` in your `~/.cargo/bin`. Make sure that `~/.cargo/bin` is in your `$PATH` variable. 64 | 65 | ## Usage 66 | 67 | ``` 68 | Convert your favorite images and wallpapers with your favorite color palettes/themes 69 | 70 | Usage: dipc [OPTIONS] [FILE]... 71 | 72 | Arguments: 73 | 74 | The color palette to use: 75 | - name of a builtin theme 76 | - path to a theme in JSON 77 | - a JSON string with the theme (starting with `JSON: {}`) 78 | Run with --help instead of -h for a list of all builtin themes 79 | 80 | Builtin themes: 81 | - catppuccin 82 | - dracula 83 | - edge 84 | - everforest 85 | - gruvbox 86 | - gruvbox-material 87 | - nord 88 | - onedark 89 | - rose-pine 90 | - solarized 91 | - tokyo-night 92 | 93 | [FILE]... 94 | The image(s) to process 95 | 96 | Options: 97 | -s, --styles 98 | The color palette variation(s) to use 99 | Run with --help instead of -h for a list of all possible values 100 | 101 | Possible values: 102 | - `all` to generate an image for each of the variations 103 | - `none` if you are using a flat theme without variations 104 | - or a comma-delimited list of the names of variations it should use 105 | 106 | [default: all] 107 | 108 | -o, --output 109 | Output image(s) name/path as a comma-delimited list 110 | 111 | -d, --dir-output 112 | Output directory name/path 113 | 114 | -m, --method 115 | CIELAB DeltaE method to use 116 | 117 | [default: de2000] 118 | 119 | Possible values: 120 | - de2000: The default DeltaE method 121 | - de1994g: CIE94 DeltaE implementation, weighted with a tolerance for graphics 122 | - de1994t: CIE94 DeltaE implementation, weighted with a tolerance for textiles 123 | - de1976: The original DeltaE implementation, a basic euclidian distance formula 124 | 125 | -v, --verbose... 126 | Verbose mode (-v, -vv, -vvv) 127 | 128 | -h, --help 129 | Print help (see a summary with '-h') 130 | 131 | -V, --version 132 | Print version 133 | ``` 134 | 135 | ### Convert all images in directory 136 | 137 | ```sh 138 | # Save to current directory 139 | dipc /* 140 | 141 | # Save to output directory 142 | dipc --dir-output /* 143 | ``` 144 | 145 | ### Convert multiple images 146 | 147 | ```sh 148 | dipc img0.png img1.png 149 | 150 | # Rename files 151 | dipc --output new-img0.png,new-img1.png img0.png img1.png 152 | ``` 153 | 154 | ### Color palette variation(s)/style(s) 155 | 156 | ```sh 157 | dipc --styles Style0 img.png 158 | dipc --styles Style0,Style1 img.png 159 | ``` 160 | 161 | ### CIELAB DeltaE method 162 | 163 | ```sh 164 | dipc --method img.png 165 | ``` 166 | 167 | ## License 168 | 169 | `dipc` is dual-licensed under the terms of both the MIT License and the Apache License 2.0 170 | 171 | SPDX-License-Identifier: MIT OR Apache-2.0 172 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "flake-utils": { 4 | "inputs": { 5 | "systems": "systems" 6 | }, 7 | "locked": { 8 | "lastModified": 1689068808, 9 | "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", 10 | "owner": "numtide", 11 | "repo": "flake-utils", 12 | "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", 13 | "type": "github" 14 | }, 15 | "original": { 16 | "owner": "numtide", 17 | "repo": "flake-utils", 18 | "type": "github" 19 | } 20 | }, 21 | "naersk": { 22 | "inputs": { 23 | "nixpkgs": "nixpkgs" 24 | }, 25 | "locked": { 26 | "lastModified": 1690373729, 27 | "narHash": "sha256-e136hTT7LqQ2QjOTZQMW+jnsevWwBpMj78u6FRUsH9I=", 28 | "owner": "nix-community", 29 | "repo": "naersk", 30 | "rev": "d9a33d69a9c421d64c8d925428864e93be895dcc", 31 | "type": "github" 32 | }, 33 | "original": { 34 | "owner": "nix-community", 35 | "repo": "naersk", 36 | "type": "github" 37 | } 38 | }, 39 | "nixpkgs": { 40 | "locked": { 41 | "lastModified": 1691368598, 42 | "narHash": "sha256-ia7li22keBBbj02tEdqjVeLtc7ZlSBuhUk+7XTUFr14=", 43 | "path": "/nix/store/631cgbs310h1rcix7zs171xzx7p2y97g-source", 44 | "rev": "5a8e9243812ba528000995b294292d3b5e120947", 45 | "type": "path" 46 | }, 47 | "original": { 48 | "id": "nixpkgs", 49 | "type": "indirect" 50 | } 51 | }, 52 | "nixpkgs_2": { 53 | "locked": { 54 | "lastModified": 1691371061, 55 | "narHash": "sha256-BxPbPVlBIoneaXIBiHd0LVzA+L4nmvFCNBU6TmQAiMM=", 56 | "owner": "NixOS", 57 | "repo": "nixpkgs", 58 | "rev": "5068bc8fe943bde3c446326da8d0ca9c93d5a682", 59 | "type": "github" 60 | }, 61 | "original": { 62 | "owner": "NixOS", 63 | "ref": "nixpkgs-unstable", 64 | "repo": "nixpkgs", 65 | "type": "github" 66 | } 67 | }, 68 | "root": { 69 | "inputs": { 70 | "flake-utils": "flake-utils", 71 | "naersk": "naersk", 72 | "nixpkgs": "nixpkgs_2" 73 | } 74 | }, 75 | "systems": { 76 | "locked": { 77 | "lastModified": 1681028828, 78 | "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", 79 | "owner": "nix-systems", 80 | "repo": "default", 81 | "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", 82 | "type": "github" 83 | }, 84 | "original": { 85 | "owner": "nix-systems", 86 | "repo": "default", 87 | "type": "github" 88 | } 89 | } 90 | }, 91 | "root": "root", 92 | "version": 7 93 | } 94 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | flake-utils.url = "github:numtide/flake-utils"; 4 | naersk.url = "github:nix-community/naersk"; 5 | nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; 6 | }; 7 | 8 | outputs = { self, flake-utils, naersk, nixpkgs, ... }: 9 | flake-utils.lib.eachDefaultSystem (system: 10 | let 11 | pkgs = (import nixpkgs) { 12 | inherit system; 13 | }; 14 | 15 | naersk' = pkgs.callPackage naersk {}; 16 | 17 | in rec { 18 | # For `nix build` & `nix run`: 19 | packages.default = naersk'.buildPackage { 20 | src = ./.; 21 | }; 22 | 23 | # For `nix develop` (optional, can be skipped): 24 | devShell = pkgs.mkShell { 25 | nativeBuildInputs = with pkgs; [ rustc cargo ]; 26 | }; 27 | } 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /images/dipc_dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doprz/dipc/a046ef2f25cb4a1747c6425e2f4f4cad3658688d/images/dipc_dark.png -------------------------------------------------------------------------------- /images/dipc_examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doprz/dipc/a046ef2f25cb4a1747c6425e2f4f4cad3658688d/images/dipc_examples.png -------------------------------------------------------------------------------- /images/dipc_light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/doprz/dipc/a046ef2f25cb4a1747c6425e2f4f4cad3658688d/images/dipc_light.png -------------------------------------------------------------------------------- /src/cli.rs: -------------------------------------------------------------------------------- 1 | use std::{fs::File, io::BufReader, path::PathBuf, str::FromStr}; 2 | 3 | use clap::Parser; 4 | use serde_json::Value; 5 | 6 | use crate::delta::CLIDEMethod; 7 | 8 | #[derive(Parser, Debug)] 9 | #[command(author, version, about, long_about = None)] 10 | pub struct Cli { 11 | // Options 12 | /// The color palette variation(s) to use 13 | /// Run with --help instead of -h for a list of all possible values 14 | /// 15 | /// Possible values: 16 | /// - `all` to generate an image for each of the variations 17 | /// - `none` if you are using a flat theme without variations 18 | /// - or a comma-delimited list of the names of variations it should use 19 | #[arg( 20 | short, 21 | long, 22 | value_name = "VARIATIONS", 23 | default_value = "all", 24 | verbatim_doc_comment 25 | )] 26 | pub styles: ColorPaletteStyles, 27 | 28 | /// Output image(s) name/path as a comma-delimited list 29 | #[arg(short, long, value_name = "PATH", value_delimiter = ',')] 30 | pub output: Option>, 31 | 32 | /// Output directory name/path 33 | #[arg(short, long, value_name = "PATH")] 34 | pub dir_output: Option, 35 | 36 | /// CIELAB DeltaE method to use 37 | #[arg(short, long, value_enum, default_value = "de2000")] 38 | pub method: CLIDEMethod, 39 | 40 | /// Verbose mode (-v, -vv, -vvv) 41 | #[arg(short, long, action = clap::ArgAction::Count)] 42 | pub verbose: u8, 43 | 44 | // Arguments 45 | /// The color palette to use: 46 | /// - name of a builtin theme 47 | /// - path to a theme in JSON 48 | /// - a JSON string with the theme (starting with `JSON: {}`) 49 | /// Run with --help instead of -h for a list of all builtin themes 50 | /// 51 | /// Builtin themes: 52 | /// - catppuccin 53 | /// - dracula 54 | /// - edge 55 | /// - everforest 56 | /// - gruvbox 57 | /// - gruvbox-material 58 | /// - nord 59 | /// - onedark 60 | /// - rose-pine 61 | /// - solarized 62 | /// - tokyo-night 63 | #[arg(value_name = "PALETTE", verbatim_doc_comment)] 64 | pub color_palette: ColorPalette, 65 | 66 | /// The image(s) to process 67 | #[arg(value_name = "FILE", value_delimiter = ',')] 68 | pub process: Vec, 69 | } 70 | 71 | #[derive(Clone, Debug)] 72 | pub enum ColorPaletteStyles { 73 | All, 74 | Some { styles: Vec }, 75 | None, 76 | } 77 | 78 | impl FromStr for ColorPaletteStyles { 79 | type Err = String; 80 | 81 | fn from_str(s: &str) -> Result { 82 | let style = match s { 83 | "all" | "ALL" => Self::All, 84 | "none" | "NONE" | "no" | "NO" => Self::None, 85 | some => Self::Some { 86 | styles: { 87 | let mut vars = Vec::new(); 88 | for var in some.split(',') { 89 | if var.is_empty() { 90 | return Err("One of the variations seems to be an empty string. Do you have a double comma in your variations list (-v)?".to_string()); 91 | }; 92 | vars.push(var.to_string()) 93 | } 94 | if vars.is_empty() { 95 | return Err("No styles selected".to_string()); 96 | }; 97 | vars 98 | }, 99 | }, 100 | }; 101 | Ok(style) 102 | } 103 | } 104 | 105 | #[derive(Clone, Debug)] 106 | pub enum ColorPalette { 107 | RawJSON { map: serde_json::Map }, 108 | Catppuccin, 109 | Dracula, 110 | Edge, 111 | Everforest, 112 | Gruvbox, 113 | GruvboxMaterial, 114 | Nord, 115 | OneDark, 116 | RosePine, 117 | Solarized, 118 | TokyoNight, 119 | } 120 | 121 | impl std::fmt::Display for ColorPalette { 122 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 123 | match self { 124 | ColorPalette::RawJSON { map } => { 125 | write!(f, "JSON: {}", serde_json::to_string(map).unwrap()) 126 | } 127 | ColorPalette::Catppuccin => write!(f, "catppuccin"), 128 | ColorPalette::Dracula => write!(f, "dracula"), 129 | ColorPalette::Edge => write!(f, "edge"), 130 | ColorPalette::Everforest => write!(f, "everforest"), 131 | ColorPalette::Gruvbox => write!(f, "gruvbox"), 132 | ColorPalette::GruvboxMaterial => write!(f, "gruvbox-material"), 133 | ColorPalette::Nord => write!(f, "nord"), 134 | ColorPalette::OneDark => write!(f, "onedark"), 135 | ColorPalette::RosePine => write!(f, "rose-pine"), 136 | ColorPalette::Solarized => write!(f, "solarized"), 137 | ColorPalette::TokyoNight => write!(f, "tokyo-night"), 138 | } 139 | } 140 | } 141 | 142 | impl FromStr for ColorPalette { 143 | type Err = String; 144 | 145 | fn from_str(s: &str) -> Result { 146 | if s.starts_with("JSON: ") { 147 | let jsonstr = &s[5..]; 148 | let json: Value = serde_json::from_str(jsonstr).map_err(|err| err.to_string())?; 149 | let Value::Object(map) = json else { 150 | return Err("Encountered error while parsing inline JSON string: the string appears to not be a JSON object".to_string()); 151 | }; 152 | return Ok(ColorPalette::RawJSON { map }); 153 | }; 154 | 155 | let palette = match s { 156 | "catppuccin" => ColorPalette::Catppuccin, 157 | "dracula" => ColorPalette::Dracula, 158 | "edge" => ColorPalette::Edge, 159 | "everforest" => ColorPalette::Everforest, 160 | "gruvbox" => ColorPalette::Gruvbox, 161 | "gruvbox-material" | "gruvbox_material" | "gruvboxmaterial" => { 162 | ColorPalette::GruvboxMaterial 163 | } 164 | "nord" => ColorPalette::Nord, 165 | "onedark" | "one_dark" | "one-dark" => ColorPalette::OneDark, 166 | "rose-pine" | "rose_pine" | "rosepine" => ColorPalette::RosePine, 167 | "solarized" => ColorPalette::Solarized, 168 | "tokyo-night" | "tokyo_night" | "tokyonight" => ColorPalette::TokyoNight, 169 | 170 | // The color palette seems to be the path to an external file 171 | external => { 172 | let external: PathBuf = external.into(); 173 | if !external.is_file() { 174 | return Err(format!("Theme source file `{s}` appears to not be a file.")); 175 | }; 176 | let file = File::open(external).map_err(|err| err.to_string())?; 177 | let file = BufReader::new(file); 178 | let json = serde_json::from_reader(file) 179 | .map_err(|err| format!("Error while parsing JSON content of {s}: {err}"))?; 180 | let Value::Object(map) = json else { 181 | return Err("Encountered error while parsing JSON theme file: the contents of the file are valid JSON but do not appear to be a JSON object".to_string()); 182 | }; 183 | ColorPalette::RawJSON { map } 184 | } 185 | }; 186 | Ok(palette) 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | use std::path::PathBuf; 3 | 4 | use image::Rgb; 5 | use serde_json::Value; 6 | 7 | use crate::cli::{ColorPalette, ColorPaletteStyles}; 8 | 9 | pub fn parse_palette( 10 | json: serde_json::Map, 11 | styles: &ColorPaletteStyles, 12 | ) -> Result, String> { 13 | match styles { 14 | ColorPaletteStyles::None => { 15 | // Flat theme 16 | Ok(vec![Palette::try_from(json)?]) 17 | } 18 | ColorPaletteStyles::All => { 19 | // Parse all styles 20 | let mut out = Vec::with_capacity(json.len()); 21 | for (style, val) in json { 22 | let Value::Object(map) = val else { 23 | return Err(format!("Failed to parse palette style `{style}`: It's value is not a JSON object")) 24 | }; 25 | let mut palette = Palette::try_from(map) 26 | .map_err(|err| format!("Failed to parse palette style `{style}`: {err}"))?; 27 | palette.name = Some(style); 28 | out.push(palette); 29 | } 30 | Ok(out) 31 | } 32 | ColorPaletteStyles::Some { styles } => { 33 | let mut json = json; 34 | let mut out = Vec::with_capacity(styles.len()); 35 | for style in styles { 36 | let Some(Value::Object(map)) = json.remove(style) else { 37 | return Err(format!("Failed to parse palette style `{style}`: It does not exist in the theme JSON source")) 38 | }; 39 | let mut palette = Palette::try_from(map) 40 | .map_err(|err| format!("Failed to parse palette style `{style}`: {err}"))?; 41 | palette.name = Some(style.to_string()); 42 | out.push(palette); 43 | } 44 | Ok(out) 45 | } 46 | } 47 | } 48 | 49 | #[derive(Debug, Clone)] 50 | pub struct Palette { 51 | pub name: Option, 52 | pub colors: Vec<(String, Rgb)>, 53 | } 54 | 55 | impl TryFrom> for Palette { 56 | type Error = String; 57 | 58 | fn try_from(json: serde_json::Map) -> Result { 59 | let mut colors = Vec::with_capacity(json.len()); 60 | for (name, value) in json { 61 | let mut colorarr: [u8; 3] = [0_u8; 3]; 62 | match value { 63 | Value::String(hex) => { 64 | // For representing a color as a hex string `#FF8800` in JSON 65 | if !hex.starts_with('#') { 66 | return Err(format!( 67 | "Encountered a color string not in the `#HEX` format: `{hex}`" 68 | )); 69 | }; 70 | let color = &hex[1..]; 71 | if !matches!(color.len(), 3 | 6) { 72 | return Err(format!( 73 | "Encountered a HEX color string of an invalid length: `{hex}`" 74 | )); 75 | } 76 | let channel_length = color.len() / 3; 77 | let multiplier = match channel_length { 78 | 1 => 16, 79 | 2 => 1, 80 | _ => unreachable!(), 81 | }; 82 | for (channel, c) in colorarr.iter_mut().enumerate() { 83 | let start = channel * channel_length; 84 | let Some(channelstr) = color.get(start..start + channel_length) else { 85 | return Err(format!( 86 | "Failed to parse HEX color string `{hex}`. Does it contain a multi-byte sequence? Only hexadecimal digits are allowed." 87 | )); 88 | }; 89 | let Ok(val) = u8::from_str_radix(channelstr, 16).map(|x| x * multiplier) else { 90 | return Err(format!( 91 | "Failed to parse HEX color string `{hex}`. Only hexadecimal digits are allowed." 92 | )); 93 | }; 94 | *c = val; 95 | } 96 | } 97 | Value::Array(arr) => { 98 | // For representing a color as `[128, 255, 0]` in JSON 99 | if arr.len() != 3 { 100 | return Err(format!( 101 | "Encountered a color array with {} elements instead of 3: {arr:?}", 102 | arr.len() 103 | )); 104 | } 105 | for (i, channel) in arr.iter().enumerate() { 106 | let Value::Number(num) = channel else { 107 | return Err(format!("Encountered a non-number in a color array: {arr:?}")) 108 | }; 109 | let Some(Ok(brightness)): Option> = num.as_u64().map(|num| num.try_into()) else { 110 | return Err(format!("Encountered a number not representable by an 8-bit-integer in a color array: {arr:?}, element {i}")) 111 | }; 112 | colorarr[i] = brightness 113 | } 114 | } 115 | Value::Object(mut map) => { 116 | // For representing a color as a JSON object: `{"r": 255, "g": 128, "b": 0}` 117 | for (channel, name) in ["r", "g", "b"].into_iter().enumerate() { 118 | let Some(obj)=map.remove(name) else { 119 | return Err(format!(r#"Key `{name}` not found in JSON object {map:?}. The format is `{{"r": 255, "g": 128, "b": 0\}}"#)) 120 | }; 121 | let Value::Number(num) = obj else { 122 | return Err(format!(r#"Key `{name}` has a non-number value in JSON object {map:?}. The format is `{{"r": 255, "g": 128, "b": 0}}"#)) 123 | }; 124 | let Some(Ok(brightness)): Option> = num.as_u64().map(|num| num.try_into()) else { 125 | return Err(format!("Encountered a number not representable by an 8-bit-integer in a color object: at key {name}: {num}")) 126 | }; 127 | colorarr[channel] = brightness; 128 | } 129 | } 130 | _ => {} 131 | }; 132 | colors.push((name, Rgb(colorarr))) 133 | } 134 | Ok(Palette { colors, name: None }) 135 | } 136 | } 137 | 138 | pub fn output_file_name( 139 | dir_path: &Option, 140 | input_path: &Path, 141 | color_palette: &ColorPalette, 142 | color_palette_variations: &[Palette], 143 | method: deltae::DEMethod, 144 | ) -> PathBuf { 145 | let mut output = PathBuf::new(); 146 | let mut output_file_name = String::new(); 147 | 148 | if let Some(dir) = dir_path { 149 | match dir.to_str() { 150 | Some(dir) => output.push(dir), 151 | None => { 152 | eprintln!("Failed to convert directory path to string"); 153 | std::process::exit(1); 154 | } 155 | }; 156 | } 157 | 158 | let file_stem = match input_path.file_stem() { 159 | Some(stem) => match stem.to_str() { 160 | Some(stem) => stem, 161 | None => { 162 | eprintln!("Failed to convert file stem to string"); 163 | eprintln!("Defaulting to \"image\""); 164 | "image" 165 | } 166 | }, 167 | None => { 168 | eprintln!("Failed to get file stem"); 169 | eprintln!("Defaulting to \"image\""); 170 | "image" 171 | } 172 | }; 173 | output_file_name.push_str(file_stem); 174 | 175 | let color_palette: String = match &color_palette { 176 | ColorPalette::RawJSON { .. } => String::from("custom"), 177 | _ => format!("{}", color_palette), 178 | }; 179 | output_file_name.push_str(format!("_{}", color_palette).as_str()); 180 | 181 | color_palette_variations.iter().for_each(|variation| { 182 | if let Some(name) = &variation.name { 183 | output_file_name.push_str(format!("-{}", name.replace(' ', "_")).as_str()); 184 | } 185 | }); 186 | 187 | if method != deltae::DEMethod::DE2000 { 188 | output_file_name.push_str(format!("_{}", method).as_str()); 189 | } 190 | 191 | output.push(output_file_name); 192 | output.set_extension("png"); 193 | output 194 | } 195 | -------------------------------------------------------------------------------- /src/delta.rs: -------------------------------------------------------------------------------- 1 | use deltae::LabValue; 2 | 3 | #[derive(Debug, Clone, Copy)] 4 | pub struct Lab { 5 | l: f32, 6 | a: f32, 7 | b: f32, 8 | } 9 | 10 | impl From<[u8; 3]> for Lab { 11 | fn from(value: [u8; 3]) -> Self { 12 | let lab::Lab { l, a, b } = lab::Lab::from_rgb(&value); 13 | Lab { l, a, b } 14 | } 15 | } 16 | 17 | impl From<[u8; 4]> for Lab { 18 | fn from(value: [u8; 4]) -> Self { 19 | let lab::Lab { l, a, b } = lab::Lab::from_rgba(&value); 20 | Lab { l, a, b } 21 | } 22 | } 23 | 24 | impl From for LabValue { 25 | fn from(lab: Lab) -> Self { 26 | LabValue { 27 | l: lab.l, 28 | a: lab.a, 29 | b: lab.b, 30 | } 31 | } 32 | } 33 | 34 | impl Lab { 35 | pub fn to_nearest_palette(self, palette: &[Lab], method: deltae::DEMethod) -> Self { 36 | let mut min_distance = std::f32::MAX; 37 | let mut new_color = self; 38 | 39 | for &color in palette { 40 | // let delta = *deltae::DeltaE::new(self, color, deltae::DEMethod::DE2000).value(); 41 | let delta = *deltae::DeltaE::new(self, color, method).value(); 42 | 43 | if delta < min_distance { 44 | min_distance = delta; 45 | new_color = color; 46 | } 47 | } 48 | 49 | new_color 50 | } 51 | 52 | pub fn to_rgb(self) -> [u8; 3] { 53 | let lab = lab::Lab { 54 | l: self.l, 55 | a: self.a, 56 | b: self.b, 57 | }; 58 | lab.to_rgb() 59 | } 60 | } 61 | 62 | // Implement DeltaEq for Lab 63 | impl deltae::DeltaEq for Lab {} 64 | 65 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)] 66 | pub enum CLIDEMethod { 67 | /// The default DeltaE method 68 | DE2000, 69 | // /// An implementation of DeltaE with separate tolerances for Lightness and Chroma 70 | // DECMC( 71 | // /// Lightness tolerance 72 | // f32, 73 | // /// Chroma tolerance 74 | // f32, 75 | // ), 76 | /// CIE94 DeltaE implementation, weighted with a tolerance for graphics 77 | DE1994G, 78 | /// CIE94 DeltaE implementation, weighted with a tolerance for textiles 79 | DE1994T, 80 | /// The original DeltaE implementation, a basic euclidian distance formula 81 | DE1976, 82 | } 83 | 84 | impl Default for CLIDEMethod { 85 | fn default() -> Self { 86 | Self::DE2000 87 | } 88 | } 89 | 90 | impl std::fmt::Display for CLIDEMethod { 91 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 92 | match self { 93 | CLIDEMethod::DE2000 => write!(f, "de2000"), 94 | // CLIDEMethod::DECMC(l, c) => write!(f, "decmc({}, {})", l, c), 95 | CLIDEMethod::DE1994G => write!(f, "de1994g"), 96 | CLIDEMethod::DE1994T => write!(f, "de1994t"), 97 | CLIDEMethod::DE1976 => write!(f, "de1976"), 98 | } 99 | } 100 | } 101 | 102 | impl From for deltae::DEMethod { 103 | fn from(method: CLIDEMethod) -> Self { 104 | match method { 105 | CLIDEMethod::DE2000 => Self::DE2000, 106 | // CLIDEMethod::DECMC(l, c) => Self::DECMC(l, c), 107 | CLIDEMethod::DE1994G => Self::DE1994G, 108 | CLIDEMethod::DE1994T => Self::DE1994T, 109 | CLIDEMethod::DE1976 => Self::DE1976, 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::io::{self, stdout, BufWriter, Write}; 2 | 3 | use clap::Parser; 4 | use delta::Lab; 5 | use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; 6 | use owo_colors::{OwoColorize, Style}; 7 | use rayon::{ 8 | prelude::{IntoParallelRefIterator, ParallelIterator}, 9 | slice::ParallelSliceMut, 10 | }; 11 | 12 | use crate::{ 13 | cli::Cli, 14 | config::{output_file_name, parse_palette}, 15 | }; 16 | 17 | mod cli; 18 | mod config; 19 | mod delta; 20 | mod palettes; 21 | 22 | fn main() -> io::Result<()> { 23 | let total_start = std::time::Instant::now(); 24 | let cli = Cli::parse(); 25 | 26 | let stdout = stdout().lock(); 27 | let mut writer = BufWriter::new(stdout); 28 | 29 | if cli.process.is_empty() { 30 | eprintln!( 31 | "{}", 32 | "You need to provide at least a single image to process" 33 | .if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 34 | ); 35 | std::process::exit(127) 36 | }; 37 | if let Some(output_vec) = &cli.output { 38 | if output_vec.is_empty() { 39 | eprintln!( 40 | "{}", 41 | "You need to provide at least a single output image name or path" 42 | .if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 43 | ); 44 | } 45 | } 46 | match &cli.output { 47 | Some(output_vec) if output_vec.len() != cli.process.len() => { 48 | eprintln!( 49 | "{}", 50 | "You need to provide the same amount of output image names/paths as input images" 51 | .if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 52 | ); 53 | std::process::exit(127) 54 | } 55 | _ => {} 56 | } 57 | 58 | println!( 59 | "Color palette: {}\nStyles: {:?}\nDeltaE method: {}", 60 | cli.color_palette, cli.styles, cli.method 61 | ); 62 | match &cli.dir_output { 63 | Some(path) if !path.is_dir() => { 64 | eprintln!( 65 | "Output directory \"{}\" does not exist.\nAttempting to create it.", 66 | path.display() 67 | ); 68 | if let Err(err) = std::fs::create_dir_all(path) { 69 | eprintln!( 70 | "Creating provided output directory failed with error: {}", 71 | err.if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 72 | ); 73 | std::process::exit(127) 74 | }; 75 | } 76 | _ => {} 77 | } 78 | if let Some(path) = &cli.dir_output { 79 | println!("Writing results to {:#?} directory.", path); 80 | } 81 | println!("Processing {:#?}", &cli.process); 82 | if let Some(output_vec) = &cli.output { 83 | println!("Output names: {:#?}", output_vec); 84 | } 85 | 86 | let mut palettes = match parse_palette(cli.color_palette.clone().get_json(), &cli.styles) { 87 | Ok(p) => p, 88 | Err(err) => { 89 | eprintln!( 90 | "{}", 91 | err.if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 92 | ); 93 | std::process::exit(127) 94 | } 95 | }; 96 | // Print palettes 97 | let color = match supports_color::on_cached(supports_color::Stream::Stdout) { 98 | Some(level) => level.has_16m, 99 | None => false, 100 | }; 101 | let max_name = palettes 102 | .iter() 103 | .map(|p| p.name.as_ref().map(|n| n.len()).unwrap_or_default()) 104 | .max() 105 | .unwrap_or_default(); 106 | for palette in &palettes { 107 | if let Some(name) = &palette.name { 108 | writeln!( 109 | writer, 110 | "{: = palettes 141 | .par_iter() 142 | .flat_map_iter(|palette| { 143 | palette 144 | .colors 145 | .iter() 146 | .map(|(_name, color)| Lab::from(color.0)) 147 | }) 148 | .collect(); 149 | 150 | for (idx, path) in cli.process.iter().enumerate() { 151 | let start = std::time::Instant::now(); 152 | // Open image 153 | let mut image = match image::open(path) { 154 | Ok(i) => i.into_rgba8(), 155 | Err(err) => { 156 | eprintln!( 157 | "Encountered error while opening image at path {}: {}", 158 | path.display() 159 | .if_supports_color(owo_colors::Stream::Stderr, |text| text.blue()), 160 | err.if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 161 | ); 162 | std::process::exit(127) 163 | } 164 | }; 165 | 166 | println!( 167 | "[{}/{}] Converting image... (this may take a while)", 168 | idx + 1, 169 | cli.process.len() 170 | ); 171 | 172 | const PIXEL_SIZE: usize = 4; 173 | const CHUNK: usize = 4096; 174 | 175 | // Apply palettes to image 176 | let progress_bar = ProgressBar::new( 177 | (image.len() / CHUNK) 178 | .try_into() 179 | .expect("Failed to convert usize to u64"), 180 | ); 181 | progress_bar.set_style( 182 | ProgressStyle::with_template( 183 | "[{elapsed_precise}] [{wide_bar}] {pos}/{len} ({eta_precise})", 184 | ) 185 | .expect("Failed to set progress bar style"), 186 | ); 187 | let progress_bar_clone = progress_bar.clone(); 188 | image 189 | .par_chunks_mut(CHUNK) 190 | .progress_with(progress_bar) 191 | .for_each(|chunk| { 192 | chunk.chunks_exact_mut(PIXEL_SIZE).for_each(|bytes| { 193 | let pixel: &mut [u8; 3] = &mut bytes[..3].try_into().unwrap(); 194 | let lab = Lab::from(*pixel); 195 | let new_rgb = lab 196 | .to_nearest_palette(&palettes_lab, deltae::DEMethod::from(cli.method)) 197 | .to_rgb(); 198 | *pixel = new_rgb; 199 | }); 200 | }); 201 | progress_bar_clone.finish(); 202 | 203 | let output_file_name = match &cli.output { 204 | Some(output_vec) => { 205 | let mut name = output_vec[idx].clone(); 206 | name.set_extension("png"); 207 | match &cli.dir_output { 208 | Some(path) => { 209 | let mut output = path.clone(); 210 | output.push(name); 211 | output 212 | } 213 | None => { 214 | let mut output = std::path::PathBuf::new(); 215 | output.push(name); 216 | output 217 | } 218 | } 219 | } 220 | None => { 221 | let mut output = std::path::PathBuf::new(); 222 | output.push(output_file_name( 223 | &cli.dir_output, 224 | path, 225 | &cli.color_palette, 226 | &palettes, 227 | deltae::DEMethod::from(cli.method), 228 | )); 229 | output 230 | } 231 | }; 232 | 233 | match image.save_with_format(&output_file_name, image::ImageFormat::Png) { 234 | Ok(_) => println!("Saved image: {:?}", output_file_name.display()), 235 | Err(err) => { 236 | eprintln!( 237 | "Encountered error while trying to save image \"{}\": {}", 238 | output_file_name.display(), 239 | err.if_supports_color(owo_colors::Stream::Stderr, |text| text.red()) 240 | ); 241 | std::process::exit(127) 242 | } 243 | }; 244 | 245 | if cli.verbose >= 1 { 246 | let duration = start.elapsed().as_secs_f32(); 247 | println!("Conversion took {} seconds.", duration); 248 | } 249 | } 250 | 251 | if cli.verbose >= 1 { 252 | let duration = total_start.elapsed().as_secs_f32(); 253 | println!("Total duration: {} seconds.", duration); 254 | } 255 | 256 | Ok(()) 257 | } 258 | -------------------------------------------------------------------------------- /src/palettes.rs: -------------------------------------------------------------------------------- 1 | use serde_json::Value; 2 | 3 | use crate::cli::ColorPalette; 4 | 5 | impl ColorPalette { 6 | pub fn get_json(self) -> serde_json::Map { 7 | let colors = match self { 8 | ColorPalette::RawJSON { map } => return map, 9 | ColorPalette::Catppuccin => { 10 | serde_json::from_str(include_str!("./palettes/catppuccin.json")).unwrap() 11 | } 12 | ColorPalette::Dracula => { 13 | serde_json::from_str(include_str!("./palettes/dracula.json")).unwrap() 14 | } 15 | ColorPalette::Edge => { 16 | serde_json::from_str(include_str!("./palettes/edge.json")).unwrap() 17 | } 18 | ColorPalette::Everforest => { 19 | serde_json::from_str(include_str!("./palettes/everforest.json")).unwrap() 20 | } 21 | ColorPalette::Gruvbox => { 22 | serde_json::from_str(include_str!("./palettes/gruvbox.json")).unwrap() 23 | } 24 | ColorPalette::GruvboxMaterial => { 25 | serde_json::from_str(include_str!("./palettes/gruvbox-material.json")).unwrap() 26 | } 27 | ColorPalette::Nord => { 28 | serde_json::from_str(include_str!("./palettes/nord.json")).unwrap() 29 | } 30 | ColorPalette::OneDark => { 31 | serde_json::from_str(include_str!("./palettes/onedark.json")).unwrap() 32 | } 33 | ColorPalette::RosePine => { 34 | serde_json::from_str(include_str!("./palettes/rose-pine.json")).unwrap() 35 | } 36 | ColorPalette::Solarized => { 37 | serde_json::from_str(include_str!("./palettes/solarized.json")).unwrap() 38 | } 39 | ColorPalette::TokyoNight => { 40 | serde_json::from_str(include_str!("./palettes/tokyo-night.json")).unwrap() 41 | } 42 | }; 43 | let Value::Object(obj) = colors else { 44 | panic!("An included theme appears to not be a JSON object?") 45 | }; 46 | obj 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/palettes/catppuccin.json: -------------------------------------------------------------------------------- 1 | { 2 | "latte": { 3 | "rosewater": "#DC8A78", 4 | "flamingo": "#DD7878", 5 | "pink": "#EA76CB", 6 | "mauve": "#8839EF", 7 | "red": "#D20F39", 8 | "maroon": "#E64553", 9 | "peach": "#FE640B", 10 | "yellow": "#DF8E1D", 11 | "green": "#40A02B", 12 | "teal": "#179299", 13 | "sky": "#04A5E5", 14 | "sapphire": "#209FB5", 15 | "blue": "#1E66F5", 16 | "lavender": "#7287FD", 17 | "text": "#4C4F69", 18 | "subtext1": "#5C5F77", 19 | "subtext0": "#6C6F85", 20 | "overlay2": "#7C7F93", 21 | "overlay1": "#8C8FA1", 22 | "overlay0": "#9CA0B0", 23 | "surface2": "#ACB0BE", 24 | "surface1": "#BCC0CC", 25 | "surface0": "#CCD0DA", 26 | "crust": "#DCE0E8", 27 | "mantle": "#E6E9EF", 28 | "base": "#EFF1F5" 29 | }, 30 | "frappe": { 31 | "rosewater": "#F2D5CF", 32 | "flamingo": "#EEBEBE", 33 | "pink": "#F4B8E4", 34 | "mauve": "#CA9EE6", 35 | "red": "#E78284", 36 | "maroon": "#EA999C", 37 | "peach": "#EF9F76", 38 | "yellow": "#E5C890", 39 | "green": "#A6D189", 40 | "teal": "#81C8BE", 41 | "sky": "#99D1DB", 42 | "sapphire": "#85C1DC", 43 | "blue": "#8CAAEE", 44 | "lavender": "#BABBF1", 45 | "text": "#C6D0F5", 46 | "subtext1": "#B5BFE2", 47 | "subtext0": "#A5ADCE", 48 | "overlay2": "#949CBB", 49 | "overlay1": "#838BA7", 50 | "overlay0": "#737994", 51 | "surface2": "#626880", 52 | "surface1": "#51576D", 53 | "surface0": "#414559", 54 | "base": "#303446", 55 | "mantle": "#292C3C", 56 | "crust": "#232634" 57 | }, 58 | "macchiato": { 59 | "rosewater": "#F4DBD6", 60 | "flamingo": "#F0C6C6", 61 | "pink": "#F5BDE6", 62 | "mauve": "#C6A0F6", 63 | "red": "#ED8796", 64 | "maroon": "#EE99A0", 65 | "peach": "#F5A97F", 66 | "yellow": "#EED49F", 67 | "green": "#A6DA95", 68 | "teal": "#8BD5CA", 69 | "sky": "#91D7E3", 70 | "sapphire": "#7DC4E4", 71 | "blue": "#8AADF4", 72 | "lavender": "#B7BDF8", 73 | "text": "#CAD3F5", 74 | "subtext1": "#B8C0E0", 75 | "subtext0": "#A5ADCB", 76 | "overlay2": "#939AB7", 77 | "overlay1": "#8087A2", 78 | "overlay0": "#6E738D", 79 | "surface2": "#5B6078", 80 | "surface1": "#494D64", 81 | "surface0": "#363A4F", 82 | "base": "#24273A", 83 | "mantle": "#1E2030", 84 | "crust": "#181926" 85 | }, 86 | "mocha": { 87 | "Rosewater": "#F5E0DC", 88 | "Flamingo": "#F2CDCD", 89 | "Pink": "#F5C2E7", 90 | "Mauve": "#CBA6F7", 91 | "Red": "#F38BA8", 92 | "Maroon": "#EBA0AC", 93 | "Peach": "#FAB387", 94 | "Yellow": "#F9E2AF", 95 | "Green": "#A6E3A1", 96 | "Teal": "#94E2D5", 97 | "Sky": "#89DCEB", 98 | "Sapphire": "#74C7EC", 99 | "Blue": "#89B4FA", 100 | "Lavender": "#B4BEFE", 101 | "Text": "#CDD6F4", 102 | "Subtext1": "#BAC2DE", 103 | "Subtext0": "#A6ADC8", 104 | "Overlay2": "#9399B2", 105 | "Overlay1": "#7F849C", 106 | "Overlay0": "#6C7086", 107 | "Surface2": "#585B70", 108 | "Surface1": "#45475A", 109 | "Surface0": "#313244", 110 | "Base": "#1E1E2E", 111 | "Mantle": "#181825", 112 | "Crust": "#11111B" 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/palettes/dracula.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dracula": { 3 | "Background": "#282A36", 4 | "Selection": "#44475A", 5 | "Foreground": "#F8F8F2", 6 | "Comment": "#6272A4", 7 | "Cyan": "#8BE9FD", 8 | "Green": "#50FA7B", 9 | "Orange": "#FFB86C", 10 | "Pink": "#FF79C6", 11 | "Purple": "#BD93F9", 12 | "Red": "#FF5555", 13 | "Yellow": "#F1FA8C" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/palettes/edge.json: -------------------------------------------------------------------------------- 1 | { 2 | "Edge Dark": { 3 | "black": "#202023", 4 | "bg_dim": "#24262A", 5 | "bg0": "#2C2E34", 6 | "bg1": "#33353F", 7 | "bg2": "#363944", 8 | "bg3": "#3B3E48", 9 | "bg4": "#414550", 10 | "gray_dim": "#535C6A", 11 | "bg_red": "#EC7279", 12 | "diff_red": "#55393D", 13 | "bg_green": "#A0C980", 14 | "diff_green": "#394634", 15 | "bg_blue": "#6CB6EB", 16 | "diff_blue": "#354157", 17 | "bg_purple": "#D38AEA", 18 | "gray": "#758094", 19 | "red": "#EC7279", 20 | "yellow": "#DEB974", 21 | "green": "#A0C980", 22 | "cyan": "#5DBBC1", 23 | "blue": "#6CB6EB", 24 | "diff_yellow": "#4E432F", 25 | "purple": "#D38AEA", 26 | "fg": "#C5CDD9" 27 | }, 28 | "Edge Dark (Aura)": { 29 | "black": "#202023", 30 | "bg_dim": "#24262D", 31 | "bg0": "#2B2D37", 32 | "bg1": "#333644", 33 | "bg2": "#363A49", 34 | "bg3": "#3A3E4E", 35 | "bg4": "#404455", 36 | "gray_dim": "#535C6A", 37 | "bg_red": "#EC7279", 38 | "diff_red": "#55393D", 39 | "bg_green": "#A0C980", 40 | "diff_green": "#394634", 41 | "bg_blue": "#6CB6EB", 42 | "diff_blue": "#354157", 43 | "bg_purple": "#D38AEA", 44 | "gray": "#758094", 45 | "red": "#EC7279", 46 | "yellow": "#DEB974", 47 | "green": "#A0C980", 48 | "cyan": "#5DBBC1", 49 | "blue": "#6CB6EB", 50 | "diff_yellow": "#4E432F", 51 | "purple": "#d38aea", 52 | "fg": "#C5CDD9" 53 | }, 54 | "Edge Dark (Neon)": { 55 | "black": "#202023", 56 | "bg_dim": "#252630", 57 | "bg0": "#2B2D3A", 58 | "bg1": "#333648", 59 | "bg2": "#363A4E", 60 | "bg3": "#393E53", 61 | "bg4": "#3F445B", 62 | "gray_dim": "#535C6A", 63 | "bg_red": "#EC7279", 64 | "diff_red": "#55393D", 65 | "bg_green": "#A0C980", 66 | "diff_green": "#394634", 67 | "bg_blue": "#6CB6EB", 68 | "diff_blue": "#354157", 69 | "bg_purple": "#D38AEA", 70 | "gray": "#758094", 71 | "red": "#EC7279", 72 | "yellow": "#DEB974", 73 | "green": "#A0C980", 74 | "cyan": "#5DBBC1", 75 | "blue": "#6CB6EB", 76 | "diff_yellow": "#4E432F", 77 | "purple": "#D38AEA", 78 | "fg": "#C5CDD9" 79 | }, 80 | "Edge Dark (Aura Dim)": { 81 | "black": "#202023", 82 | "bg_dim": "#24262D", 83 | "bg0": "#2B2D37", 84 | "bg1": "#333644", 85 | "bg2": "#363A49", 86 | "bg3": "#3A3E4E", 87 | "bg4": "#404455", 88 | "gray_dim": "#4F5866", 89 | "bg_red": "#EC7279", 90 | "diff_red": "#55393D", 91 | "bg_green": "#A0C980", 92 | "diff_green": "#394634", 93 | "bg_blue": "#6CB6EB", 94 | "diff_blue": "#354157", 95 | "bg_purple": "#D38AEA", 96 | "gray": "#677287", 97 | "red": "#EC7279", 98 | "yellow": "#DEB974", 99 | "green": "#A0C980", 100 | "cyan": "#5DBBC1", 101 | "blue": "#6CB6EB", 102 | "diff_yellow": "#4E432F", 103 | "purple": "#D38AEA", 104 | "fg": "#97A4B5" 105 | }, 106 | "Edge Light": { 107 | "black": "#DDE2E7", 108 | "bg_dim": "#E8EBF0", 109 | "bg0": "#FAFAFA", 110 | "bg1": "#EEF1F4", 111 | "bg2": "#E8EBF0", 112 | "bg3": "#E8EBF0", 113 | "bg4": "#DDE2E7", 114 | "gray_dim": "#BAC3CB", 115 | "bg_red": "#E17373", 116 | "diff_red": "#F6E4E4", 117 | "bg_green": "#76AF6F", 118 | "diff_green": "#E5EEE4", 119 | "bg_blue": "#6996E0", 120 | "diff_blue": "#E3EAF6", 121 | "bg_purple": "#BF75D6", 122 | "gray": "#8790A0", 123 | "red": "#D05858", 124 | "yellow": "#BE7E05", 125 | "green": "#608E32", 126 | "cyan": "#3A8B84", 127 | "blue": "#5079BE", 128 | "diff_yellow": "#F0ECE2", 129 | "purple": "#B05CCC", 130 | "fg": "#4B505B" 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /src/palettes/everforest.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dark": { 3 | "bg_dim": "#232A2E", 4 | "bg0": "#2D353B", 5 | "bg1": "#343F44", 6 | "bg2": "#3D484D", 7 | "bg3": "#475258", 8 | "bg4": "#4F585E", 9 | "bg5": "#56635F", 10 | "bg_red": "#543A48", 11 | "bg_visual": "#514045", 12 | "bg_yellow": "#4D4C43", 13 | "bg_green": "#425047", 14 | "bg_blue": "#3A515D", 15 | "red": "#E67E80", 16 | "orange": "#E69875", 17 | "yellow": "#DBBC7F", 18 | "green": "#A7C080", 19 | "blue": "#7FBBB3", 20 | "aqua": "#83C092", 21 | "purple": "#D699B6", 22 | "fg": "#D3C6AA", 23 | "statusline1": "#A7C080", 24 | "statusline2": "#D3C6AA", 25 | "statusline3": "#E67E80", 26 | "gray0": "#7A8478", 27 | "gray1": "#859289", 28 | "gray2": "#9DA9A0" 29 | }, 30 | "Light": { 31 | "bg_dim": "#EFEBD4", 32 | "bg0": "#FDF6E3", 33 | "bg1": "#F4F0D9", 34 | "bg2": "#EFEBD4", 35 | "bg3": "#E6E2CC", 36 | "bg4": "#E0DCC7", 37 | "bg5": "#BDC3AF", 38 | "bg_red": "#FBE3DA", 39 | "bg_visual": "#EAEDC8", 40 | "bg_yellow": "#FAEDCD", 41 | "bg_green": "#F0F1D2", 42 | "bg_blue": "#E9F0E9", 43 | "red": "#F85552", 44 | "orange": "#F57D26", 45 | "yellow": "#DFA000", 46 | "green": "#8DA101", 47 | "blue": "#3A94C5", 48 | "aqua": "#35A77C", 49 | "purple": "#DF69BA", 50 | "fg": "#5C6A72", 51 | "statusline1": "#93B259", 52 | "statusline2": "#708089", 53 | "statusline3": "#E66868", 54 | "gray0": "#A6B0A0", 55 | "gray1": "#939F91", 56 | "gray2": "#829181" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/palettes/gruvbox-material.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dark": { 3 | "bg_dim": "#1B1B1B", 4 | "bg0": "#282828", 5 | "bg1": "#32302F", 6 | "bg2": "#32302F", 7 | "bg3": "#45403D", 8 | "bg4": "#45403D", 9 | "bg5": "#5A524C", 10 | "bg_statusline1": "#32302F", 11 | "bg_statusline2": "#3A3735", 12 | "bg_statusline3": "#504945", 13 | "bg_diff_green": "#34381B", 14 | "bg_visual_green": "#3B4439", 15 | "bg_diff_red": "#402120", 16 | "bg_visual_red": "#4C3432", 17 | "bg_diff_blue": "#0E363E", 18 | "bg_visual_blue": "#374141", 19 | "bg_visual_yellow": "#4F422E", 20 | "bg_current_word": "#3C3836", 21 | "fg0": "#D4BE98", 22 | "fg1": "#DDC7A1", 23 | "red": "#EA6962", 24 | "orange": "#E78A4E", 25 | "yellow": "#D8A657", 26 | "green": "#A9B665", 27 | "aqua": "#89B482", 28 | "blue": "#7DAEA3", 29 | "purple": "#D3869B", 30 | "bg_red": "#EA6962", 31 | "bg_green": "#A9B665", 32 | "bg_yellow": "#D8A657", 33 | "grey0": "#7C6F64", 34 | "grey1": "#928374", 35 | "grey2": "#A89984" 36 | }, 37 | "Light": { 38 | "bg_dim": "#F2E5BC", 39 | "bg0": "#FBF1C7", 40 | "bg1": "#F4E8BE", 41 | "bg2": "#F2E5BC", 42 | "bg3": "#EEE0B7", 43 | "bg4": "#E5D5AD", 44 | "bg5": "#DDCCAB", 45 | "bg_statusline1": "#F2E5BC", 46 | "bg_statusline2": "#F2E5BC", 47 | "bg_statusline3": "#E5D5AD", 48 | "bg_diff_green": "#E6EABC", 49 | "bg_visual_green": "#DEE2B6", 50 | "bg_diff_red": "#F9E0BB", 51 | "bg_visual_red": "#F1D9B5", 52 | "bg_diff_blue": "#E2E6C7", 53 | "bg_visual_blue": "#DADEC0", 54 | "bg_visual_yellow": "#FAE7B3", 55 | "bg_current_word": "#F2E5BC", 56 | "fg0": "#654735", 57 | "fg1": "#4F3829", 58 | "red": "#C14A4A", 59 | "orange": "#C35E0A", 60 | "yellow": "#B47109", 61 | "green": "#6C782E", 62 | "aqua": "#4C7A5D", 63 | "blue": "#45707A", 64 | "purple": "#945E80", 65 | "bg_red": "#AE5858", 66 | "bg_green": "#6F8352", 67 | "bg_yellow": "#A96B2C", 68 | "grey0": "#A89984", 69 | "grey1": "#928374", 70 | "grey2": "#7C6F64" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/palettes/gruvbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dark mode": { 3 | "bg_0": "#282828", 4 | "red_0": "#CC241D", 5 | "green_0": "#98971A", 6 | "yellow_0": "#D79921", 7 | "blue_0": "#458588", 8 | "purple_0": "#B16286", 9 | "aqua_0": "#689D6A", 10 | "gray_0": "#A89984", 11 | "grey_1": "#928374", 12 | "red_1": "#FB4934", 13 | "green_1": "#B8BB26", 14 | "yellow_1": "#FABD2F", 15 | "blue_1": "#83A598", 16 | "purple_1": "#D3869B", 17 | "aqua_1": "#8EC07C", 18 | "fg_1": "#EBDBB2", 19 | "bg0_h_2": "#1D2021", 20 | "bg0_2": "#282828", 21 | "bg1_2": "#3C3836", 22 | "bg2_2": "#504945", 23 | "bg3_2": "#665C54", 24 | "bg4_2": "#7C6F64", 25 | "grey_2": "#928374", 26 | "orange_2": "#D65D0E", 27 | "bg0_s_3": "#32302F", 28 | "fg4_3": "#A89984", 29 | "fg3_3": "#BDAE93", 30 | "fg2_3": "#D5C4A1", 31 | "fg1_3": "#EBDBB2", 32 | "fg0_3": "#FBF1C7", 33 | "orange_3": "#FE8019" 34 | }, 35 | "Light mode": { 36 | "bg_0": "#FBF1C7", 37 | "red_0": "#CC241D", 38 | "green_0": "#98971A", 39 | "yellow_0": "#D79921", 40 | "blue_0": "#458588", 41 | "purple_0": "#B16286", 42 | "aqua_0": "#689D6A", 43 | "gray_0": "#7C6F64", 44 | "grey_1": "#928374", 45 | "red_1": "#9D0006", 46 | "green_1": "#79740E", 47 | "yellow_1": "#B57614", 48 | "blue_1": "#076678", 49 | "purple_1": "#8F3F71", 50 | "aqua_1": "#427B58", 51 | "fg_1": "#3C3836", 52 | "bg0_h_2": "#F9F5D7", 53 | "bg0_2": "#FBF1C7", 54 | "bg1_2": "#EBDBB2", 55 | "bg2_2": "#D5C4A1", 56 | "bg3_2": "#BDAE93", 57 | "bg4_2": "#A89984", 58 | "grey_2": "#928374", 59 | "orange_2": "#D65D0E", 60 | "bg0_s_3": "#F2E5BC", 61 | "fg4_3": "#7C6F64", 62 | "fg3_3": "#665C54", 63 | "fg2_3": "#504945", 64 | "fg1_3": "#3C3836", 65 | "fg0_3": "#282828", 66 | "orange_3": "#AF3A03" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/palettes/nord.json: -------------------------------------------------------------------------------- 1 | { 2 | "Polar Night": { 3 | "nord0": "#2E3440", 4 | "nord1": "#3B4252", 5 | "nord2": "#434C5E", 6 | "nord3": "#4C566A" 7 | }, 8 | "Snow Storm": { 9 | "nord4": "#D8DEE9", 10 | "nord5": "#E5E9F0", 11 | "nord6": "#ECEFF4" 12 | }, 13 | "Frost": { 14 | "nord7": "#8FBCBB", 15 | "nord8": "#88C0D0", 16 | "nord9": "#81A1C1", 17 | "nord10": "#5E81AC" 18 | }, 19 | "Aurora": { 20 | "nord11": "#BF616A", 21 | "nord12": "#D08770", 22 | "nord13": "#EBCB8B", 23 | "nord14": "#A3BE8C", 24 | "nord15": "#B48EAD" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/palettes/onedark.json: -------------------------------------------------------------------------------- 1 | { 2 | "dark": { 3 | "black": "#181A1F", 4 | "bg0": "#282C34", 5 | "bg1": "#31353F", 6 | "bg2": "#393F4A", 7 | "bg3": "#3B3F4C", 8 | "bg_d": "#21252B", 9 | "bg_blue": "#73B8F1", 10 | "bg_yellow": "#EBD09C", 11 | "fg": "#ABB2BF", 12 | "purple": "#C678DD", 13 | "green": "#98C379", 14 | "orange": "#D19A66", 15 | "blue": "#61AFEF", 16 | "yellow": "#E5C07B", 17 | "cyan": "#56B6C2", 18 | "red": "#E86671", 19 | "grey": "#5C6370", 20 | "light_grey": "#848B98", 21 | "dark_cyan": "#2B6F77", 22 | "dark_red": "#993939", 23 | "dark_yellow": "#93691D", 24 | "dark_purple": "#8A3FA0", 25 | "diff_add": "#31392B", 26 | "diff_delete": "#382B2C", 27 | "diff_change": "#1C3448", 28 | "diff_text": "#2C5372" 29 | }, 30 | "darker": { 31 | "black": "#0E1013", 32 | "bg0": "#1F2329", 33 | "bg1": "#282C34", 34 | "bg2": "#30363F", 35 | "bg3": "#323641", 36 | "bg_d": "#181B20", 37 | "bg_blue": "#61AFEF", 38 | "bg_yellow": "#E8C88C", 39 | "fg": "#A0A8B7", 40 | "purple": "#BF68D9", 41 | "green": "#8EBD6B", 42 | "orange": "#CC9057", 43 | "blue": "#4FA6ED", 44 | "yellow": "#E2B86B", 45 | "cyan": "#48B0BD", 46 | "red": "#E55561", 47 | "grey": "#535965", 48 | "light_grey": "#7A818E", 49 | "dark_cyan": "#266269", 50 | "dark_red": "#8B3434", 51 | "dark_yellow": "#835D1A", 52 | "dark_purple": "#7E3992", 53 | "diff_add": "#272E23", 54 | "diff_delete": "#2D2223", 55 | "diff_change": "#172A3A", 56 | "diff_text": "#274964" 57 | }, 58 | "cool": { 59 | "black": "#151820", 60 | "bg0": "#242B38", 61 | "bg1": "#2D3343", 62 | "bg2": "#343E4F", 63 | "bg3": "#363C51", 64 | "bg_d": "#1E242E", 65 | "bg_blue": "#6DB9F7", 66 | "bg_yellow": "#F0D197", 67 | "fg": "#A5B0C5", 68 | "purple": "#CA72E4", 69 | "green": "#97CA72", 70 | "orange": "#D99A5E", 71 | "blue": "#5AB0F6", 72 | "yellow": "#EBC275", 73 | "cyan": "#4DBDCB", 74 | "red": "#EF5F6B", 75 | "grey": "#546178", 76 | "light_grey": "#7D899F", 77 | "dark_cyan": "#25747D", 78 | "dark_red": "#A13131", 79 | "dark_yellow": "#9A6B16", 80 | "dark_purple": "#8F36A9", 81 | "diff_add": "#303D27", 82 | "diff_delete": "#3C2729", 83 | "diff_change": "#18344C", 84 | "diff_text": "#265478" 85 | }, 86 | "deep": { 87 | "black": "#0C0E15", 88 | "bg0": "#1A212E", 89 | "bg1": "#21283B", 90 | "bg2": "#283347", 91 | "bg3": "#2A324A", 92 | "bg_d": "#141B24", 93 | "bg_blue": "#54B0FD", 94 | "bg_yellow": "#F2CC81", 95 | "fg": "#93A4C3", 96 | "purple": "#C75AE8", 97 | "green": "#8BCD5B", 98 | "orange": "#DD9046", 99 | "blue": "#41A7FC", 100 | "yellow": "#EFBD5D", 101 | "cyan": "#34BFD0", 102 | "red": "#F65866", 103 | "grey": "#455574", 104 | "light_grey": "#6C7D9C", 105 | "dark_cyan": "#1B6A73", 106 | "dark_red": "#992525", 107 | "dark_yellow": "#8F610D", 108 | "dark_purple": "#862AA1", 109 | "diff_add": "#27341C", 110 | "diff_delete": "#331C1E", 111 | "diff_change": "#102B40", 112 | "diff_text": "#1C4A6E" 113 | }, 114 | "warm": { 115 | "black": "#191A1C", 116 | "bg0": "#2C2D30", 117 | "bg1": "#35373B", 118 | "bg2": "#3E4045", 119 | "bg3": "#404247", 120 | "bg_d": "#242628", 121 | "bg_blue": "#79B7EB", 122 | "bg_yellow": "#E6CFA1", 123 | "fg": "#B1B4B9", 124 | "purple": "#C27FD7", 125 | "green": "#99BC80", 126 | "orange": "#C99A6E", 127 | "blue": "#68AEE8", 128 | "yellow": "#DFBE81", 129 | "cyan": "#5FAFB9", 130 | "red": "#E16D77", 131 | "grey": "#646568", 132 | "light_grey": "#8B8D91", 133 | "dark_cyan": "#316A71", 134 | "dark_red": "#914141", 135 | "dark_yellow": "#8C6724", 136 | "dark_purple": "#854897", 137 | "diff_add": "#32352F", 138 | "diff_delete": "#342F2F", 139 | "diff_change": "#203444", 140 | "diff_text": "#32526C" 141 | }, 142 | "warmer": { 143 | "black": "#101012", 144 | "bg0": "#232326", 145 | "bg1": "#2C2D31", 146 | "bg2": "#35363B", 147 | "bg3": "#37383D", 148 | "bg_d": "#1B1C1E", 149 | "bg_blue": "#68AEE8", 150 | "bg_yellow": "#E2C792", 151 | "fg": "#A7AAB0", 152 | "purple": "#BB70D2", 153 | "green": "#8FB573", 154 | "orange": "#C49060", 155 | "blue": "#57A5E5", 156 | "yellow": "#DBB671", 157 | "cyan": "#51A8B3", 158 | "red": "#DE5D68", 159 | "grey": "#5A5B5E", 160 | "light_grey": "#818387", 161 | "dark_cyan": "#2B5D63", 162 | "dark_red": "#833B3B", 163 | "dark_yellow": "#7C5C20", 164 | "dark_purple": "#79428A", 165 | "diff_add": "#282B26", 166 | "diff_delete": "#2A2626", 167 | "diff_change": "#1A2A37", 168 | "diff_text": "#2C485F" 169 | }, 170 | "light": { 171 | "black": "#101012", 172 | "bg0": "#FAFAFA", 173 | "bg1": "#F0F0F0", 174 | "bg2": "#E6E6E6", 175 | "bg3": "#DCDCDC", 176 | "bg_d": "#C9C9C9", 177 | "bg_blue": "#68AEE8", 178 | "bg_yellow": "#E2C792", 179 | "fg": "#383A42", 180 | "purple": "#A626A4", 181 | "green": "#50A14F", 182 | "orange": "#C18401", 183 | "blue": "#4078F2", 184 | "yellow": "#986801", 185 | "cyan": "#0184BC", 186 | "red": "#E45649", 187 | "grey": "#A0A1A7", 188 | "light_grey": "#818387", 189 | "dark_cyan": "#2B5D63", 190 | "dark_red": "#833B3B", 191 | "dark_yellow": "#7C5C20", 192 | "dark_purple": "#79428A", 193 | "diff_add": "#E2FBE4", 194 | "diff_delete": "#FCE2E5", 195 | "diff_change": "#E2ECFB", 196 | "diff_text": "#CAD3E0" 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /src/palettes/rose-pine.json: -------------------------------------------------------------------------------- 1 | { 2 | "Rose Pine": { 3 | "Base": "#191724", 4 | "Surface": "#1F1D2E", 5 | "Overlay": "#26233A", 6 | "Muted": "#6E6A86", 7 | "Subtle": "#908CAA", 8 | "Text": "#E0DEF4", 9 | "Love": "#EB6F92", 10 | "Gold": "#F6C177", 11 | "Rose": "#EBBCBA", 12 | "Pine": "#31748F", 13 | "Foam": "#9CCFD8", 14 | "Iris": "#C4A7E7", 15 | "Highlight Low": "#21202E", 16 | "Highlight Med": "#403D52", 17 | "Highlight High": "#524F67" 18 | }, 19 | "Rose Pine Moon": { 20 | "Base": "#232136", 21 | "Surface": "#2A273F", 22 | "Overlay": "#393552", 23 | "Muted": "#6E6A86", 24 | "Subtle": "#908CAA", 25 | "Text": "#E0DEF4", 26 | "Love": "#EB6F92", 27 | "Gold": "#F6C177", 28 | "Rose": "#EA9A97", 29 | "Pine": "#3E8FB0", 30 | "Foam": "#9CCFD8", 31 | "Iris": "#C4A7E7", 32 | "Highlight Low": "#2A283E", 33 | "Highlight Med": "#44415A", 34 | "Highlight High": "#56526E" 35 | }, 36 | "Rose Pine Dawn": { 37 | "Base": "#FAF4ED", 38 | "Surface": "#FFFAF3", 39 | "Overlay": "#F2E9E1", 40 | "Muted": "#9893A5", 41 | "Subtle": "#797593", 42 | "Text": "#575279", 43 | "Love": "#B4637A", 44 | "Gold": "#EA9D34", 45 | "Rose": "#D7827E", 46 | "Pine": "#286983", 47 | "Foam": "#56949F", 48 | "Iris": "#907AA9", 49 | "Highlight Low": "#F4EDE8", 50 | "Highlight Med": "#DFDAD9", 51 | "Highlight High": "#CECACD" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/palettes/solarized.json: -------------------------------------------------------------------------------- 1 | { 2 | "Solarized": { 3 | "base03": "#002B36", 4 | "base02": "#073642", 5 | "base01": "#586E75", 6 | "base00": "#657B83", 7 | "base0": "#839496", 8 | "base1": "#93A1A1", 9 | "base2": "#EEE8D5", 10 | "base3": "#FDF6E3", 11 | "yellow": "#B58900", 12 | "orange": "#CB4B16", 13 | "red": "#DC322F", 14 | "magenta": "#D33682", 15 | "violet": "#6C71C4", 16 | "blue": "#268BD2", 17 | "cyan": "#2AA198", 18 | "green": "#859900" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/palettes/tokyo-night.json: -------------------------------------------------------------------------------- 1 | { 2 | "Storm": { 3 | "background": "#24283B", 4 | "black": "#1D202F", 5 | "blue": "#7AA2F7", 6 | "brightBlack": "#414868", 7 | "brightBlue": "#7AA2F7", 8 | "brightCyan": "#7DCFFF", 9 | "brightGreen": "#9ECE6A", 10 | "brightPurple": "#9D7CD8", 11 | "brightRed": "#F7768E", 12 | "brightWhite": "#C0CAF5", 13 | "brightYellow": "#E0AF68", 14 | "cursorColor": "#C0CAF5", 15 | "cyan": "#7DCFFF", 16 | "foreground": "#C0CAF5", 17 | "green": "#9ECE6A", 18 | "purple": "#BB9AF7", 19 | "red": "#F7768E", 20 | "selectionBackground": "#2E3C64", 21 | "white": "#A9B1D6", 22 | "yellow": "#E0AF68" 23 | }, 24 | "Night": { 25 | "background": "#1A1B26", 26 | "black": "#15161E", 27 | "blue": "#7AA2F7", 28 | "brightBlack": "#414868", 29 | "brightBlue": "#7AA2F7", 30 | "brightCyan": "#7DCFFF", 31 | "brightGreen": "#9ECE6A", 32 | "brightPurple": "#9D7CD8", 33 | "brightRed": "#F7768E", 34 | "brightWhite": "#C0CAF5", 35 | "brightYellow": "#E0AF68", 36 | "cursorColor": "#C0CAF5", 37 | "cyan": "#7DCFFF", 38 | "foreground": "#C0CAF5", 39 | "green": "#9ECE6A", 40 | "purple": "#BB9AF7", 41 | "red": "#F7768E", 42 | "selectionBackground": "#283457", 43 | "white": "#A9B1D6", 44 | "yellow": "#E0AF68" 45 | }, 46 | "Moon": { 47 | "background": "#222436", 48 | "black": "#1B1D2B", 49 | "blue": "#82AAFF", 50 | "brightBlack": "#444A73", 51 | "brightBlue": "#82AAFF", 52 | "brightCyan": "#86E1FC", 53 | "brightGreen": "#C3E88D", 54 | "brightPurple": "#FCA7EA", 55 | "brightRed": "#FF757F", 56 | "brightWhite": "#C8D3F5", 57 | "brightYellow": "#FFC777", 58 | "cursorColor": "#C8D3F5", 59 | "cyan": "#86E1FC", 60 | "foreground": "#C8D3F5", 61 | "green": "#C3E88D", 62 | "purple": "#C099FF", 63 | "red": "#FF757F", 64 | "selectionBackground": "#2D3F76", 65 | "white": "#828BB8", 66 | "yellow": "#FFC777" 67 | }, 68 | "Day": { 69 | "background": "#E1E2E7", 70 | "black": "#E9E9ED", 71 | "blue": "#2E7DE9", 72 | "brightBlack": "#A1A6C5", 73 | "brightBlue": "#2E7DE9", 74 | "brightCyan": "#007197", 75 | "brightGreen": "#587539", 76 | "brightPurple": "#7847BD", 77 | "brightRed": "#F52A65", 78 | "brightWhite": "#3760BF", 79 | "brightYellow": "#8C6C3E", 80 | "cursorColor": "#3760BF", 81 | "cyan": "#007197", 82 | "foreground": "#3760BF", 83 | "green": "#587539", 84 | "purple": "#9854F1", 85 | "red": "#F52A65", 86 | "selectionBackground": "#B6BFE2", 87 | "white": "#6172B0", 88 | "yellow": "#8C6C3E" 89 | } 90 | } 91 | --------------------------------------------------------------------------------