├── .github └── workflows │ ├── build.yml │ └── release.yml ├── .gitignore ├── .idea ├── .gitignore ├── dye.iml ├── libraries │ └── dye_linux.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── README.rst ├── dye ├── dye-linux.zip ├── dye.nimble ├── ex ├── LakesideVillage.jpg ├── conv-LakesideVillage.png ├── conv-unknown.png └── unknown.png ├── lib ├── args.nim ├── colors.nim ├── palettes.nim └── updates.nim ├── scripts └── zigcc └── src └── dye.nim /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | - push 5 | - pull_request 6 | 7 | jobs: 8 | build: 9 | name: ${{ matrix.os }} 10 | runs-on: ${{ matrix.os }} 11 | strategy: 12 | matrix: 13 | os: 14 | - ubuntu-latest 15 | - macOS-latest 16 | - windows-latest 17 | 18 | steps: 19 | - name: Checkout sources 20 | uses: actions/checkout@v2 21 | - uses: alaviss/setup-nim@0.1.1 22 | with: 23 | path: 'nim' 24 | version: devel 25 | - uses: actions/cache@v3.1.0-beta.1 26 | with: 27 | path: | 28 | ../../../../.nimble/pkgs/ 29 | key: ${{ runner.os }}-nim-${{ hashFiles('**/nimble.lock') }} 30 | - name: Install dependacies 31 | if: steps.cache.outputs.cache-hit != 'false' 32 | run: nimble install -d -y --deepcopy:on 33 | - name: Build 34 | run: nimble build -d:release -d:ssl --verbose 35 | - name: Cache 36 | - uses: actions/upload-artifact@v2 37 | if: ${{ matrix.os != 'windows-latest' }} 38 | with: 39 | name: dye-${{ matrix.os }} 40 | path: dye 41 | - uses: actions/upload-artifact@v2 42 | if: ${{ matrix.os == 'windows-latest' }} 43 | with: 44 | name: dye-${{ matrix.os }} 45 | path: dye.exe 46 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | release: 6 | types: [released] 7 | 8 | jobs: 9 | build: 10 | name: ${{ matrix.os }} 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: 15 | - ubuntu-latest 16 | #- windows-latest 17 | permissions: 18 | contents: write 19 | checks: write 20 | 21 | actions: read 22 | issues: read 23 | packages: write 24 | pull-requests: read 25 | repository-projects: read 26 | statuses: read 27 | 28 | steps: 29 | - name: Checkout sources 30 | uses: actions/checkout@v2 31 | - uses: iffy/install-nim@v4 32 | with: 33 | version: binary:stable 34 | - name: Build 35 | run: | 36 | nimble install -d -y 37 | nimble build -d:release --deepcopy:on 38 | - uses: thedoctor0/zip-release@main 39 | if: ${{ matrix.os == 'ubuntu-latest' }} 40 | with: 41 | type: 'zip' 42 | filename: dye-linux.zip 43 | path: dye 44 | - uses: thedoctor0/zip-release@main 45 | if: ${{ matrix.os == 'windows-latest' }} 46 | with: 47 | type: 'zip' 48 | filename: dye-windows.zip 49 | path: dye.exe 50 | 51 | - name: Release 52 | uses: alexellis/upload-assets@0.4.0 53 | env: 54 | GITHUB_TOKEN: ${{ secrets.github_token }} 55 | with: 56 | asset_paths: '["dye-*.zip"]' 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /.idea/dye.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/libraries/dye_linux.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | dye 2 | === 3 | 4 | An ultrafast image colorizer tool 5 | --------------------------------- 6 | 7 | Installation 8 | ~~~~~~~~~~~~ 9 | 10 | From Source 11 | ^^^^^^^^^^^ 12 | 13 | **Dependencies Required:** 14 | * nim 15 | * nimble 16 | 17 | .. code:: bash 18 | 19 | nimble install dye@"#head" 20 | 21 | Binary 22 | ^^^^^^ 23 | 24 | There are many binaries for different operating systems and 25 | architectures on the github releases page 26 | 27 | 28 | Packages 29 | ^^^^^^^^ 30 | .. raw:: html 31 | 32 | 33 | 34 | Packaging status 35 | 36 | 37 | Currently dye can be installed from 38 | * AUR 39 | * Nimble 40 | * Jitter 41 | You can install from `jitter `_ with the command: ``jitter install gh:Infinitybeond1/dye`` 42 | 43 | Usage 44 | ~~~~~ 45 | 46 | .. code-block:: bash 47 | 48 | # Get command info 49 | dye --help 50 | 51 | # Convert 'test.jpg' using the dark-decay color palette (available color palettes: decay, darkdecay, decayce, articblush, catppuccin, ok, nord, everforest, iceberg) 52 | dye -b -p dark-decay test.jpg 53 | 54 | # Convert the image to black and white 55 | dye -b -p "#000000,#FFFFFF" test.jpg 56 | 57 | # List color palettes 58 | dye list 59 | 60 | Contributing 61 | ~~~~~~~~~~~~ 62 | 63 | Feel free to open a pull request if you wish to make any changes, here 64 | are a few of the ways you can help 65 | * Create some color palettes (lib/palettes.nim) they are just exported sequences of quoted hex codes 66 | * Help me improve the docs 67 | * Package it for platforms 68 | -------------------------------------------------------------------------------- /dye: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arashi-software/dye/78c7e2bca3438feb5cb025d12fb59e28443051e4/dye -------------------------------------------------------------------------------- /dye-linux.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arashi-software/dye/78c7e2bca3438feb5cb025d12fb59e28443051e4/dye-linux.zip -------------------------------------------------------------------------------- /dye.nimble: -------------------------------------------------------------------------------- 1 | version = "1.2.1" 2 | author = "Luke" 3 | description = "An image colorizer" 4 | license = "GPL-3.0-or-later" 5 | srcDir = "src" 6 | bin = @["dye"] 7 | 8 | requires "nim >= 1.4.8" 9 | requires "progress" 10 | requires "pixie#head" 11 | requires "chroma#head" 12 | requires "therapist" 13 | requires "puppy" 14 | requires "zippy" 15 | #requires "downit" 16 | 17 | task lint, "Lint all *.nim files": 18 | exec "nimpretty --indent:2 */**.nim" 19 | 20 | task b, "Build for release": 21 | exec "nimble install -d:release && nim c --passL:'-s' -d:ssl -d:release src/dye && mkdir -p bin && mv -f src/dye bin/" 22 | 23 | task bi, "Build and install to your path (/usr/bin/)": 24 | exec "nimble install -d:release && nim c --passL:'-s' -d:release -d:ssl src/dye" 25 | 26 | task bz, "Build using zig as a c compiler": 27 | exec "nimble install -y -d && nim c -d:release -d:ssl --passL:'-s' --cc:clang --clang.exe:'scripts/zigcc' src/dye.nim && mkdir -p bin && mv -f src/dye bin/" 28 | 29 | task i, "Install a built version of dye": 30 | exec "sudo mv -fv bin/dye /usr/bin/" 31 | 32 | task bzi, "Build with zig and install": 33 | exec "nimble bz && nimble i" 34 | -------------------------------------------------------------------------------- /ex/LakesideVillage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arashi-software/dye/78c7e2bca3438feb5cb025d12fb59e28443051e4/ex/LakesideVillage.jpg -------------------------------------------------------------------------------- /ex/conv-LakesideVillage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arashi-software/dye/78c7e2bca3438feb5cb025d12fb59e28443051e4/ex/conv-LakesideVillage.png -------------------------------------------------------------------------------- /ex/conv-unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arashi-software/dye/78c7e2bca3438feb5cb025d12fb59e28443051e4/ex/conv-unknown.png -------------------------------------------------------------------------------- /ex/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arashi-software/dye/78c7e2bca3438feb5cb025d12fb59e28443051e4/ex/unknown.png -------------------------------------------------------------------------------- /lib/args.nim: -------------------------------------------------------------------------------- 1 | import os, strutils, strformat, therapist 2 | 3 | const versionNum* = staticRead(fmt"../dye.nimble").splitLines()[0].split("=")[ 4 | 1].strip().replace("\"", "") 5 | 6 | const release = defined(release) 7 | 8 | var bType: string 9 | 10 | if release: 11 | bType = "release" 12 | else: 13 | bType = "debug" 14 | 15 | let list = ( 16 | help: newHelpArg() 17 | ) 18 | 19 | let flip = ( 20 | help: newHelpArg(), 21 | bar: newCountArg(@["--bar", "-b"], multi = false, 22 | help = "Show a progress bar"), 23 | output: newStringArg(@["--output", "-o"], help = "The file to write to", 24 | optional = true, defaultVal = "null"), 25 | file: newPathArg(@[""], help = "The file (or folder of files) to convert") 26 | ) 27 | 28 | let luma = ( 29 | help: newHelpArg(), 30 | bar: newCountArg(@["--bar", "-b"], multi = false, 31 | help = "Show a progress bar"), 32 | output: newStringArg(@["--output", "-o"], help = "The file to write to", 33 | optional = true, defaultVal = "null"), 34 | file: newPathArg(@[""], help = "The file (or folder of files) to convert") 35 | ) 36 | 37 | let update = ( 38 | help: newHelpArg() 39 | ) 40 | 41 | let args* = ( 42 | list: newCommandArg(@["list", "ls"], list, help = "List all palettes"), 43 | luma: newCommandArg(@["luma", "l"], luma, 44 | help = "Invert the luminance of an image"), 45 | flip: newCommandArg(@["flip", "f"], flip, 46 | help = "Flip the colors of an image"), 47 | update: newCommandArg(@["update", "u"], update, help = "Update dye"), 48 | bar: newCountArg(@["--bar", "-b"], multi = false, 49 | help = "Show a progress bar"), 50 | recursive: newCountArg(@["--rec", "-r"], multi = false, 51 | help = "Recursively scan directories"), 52 | output: newStringArg(@["--output", "-o"], help = "The file to write to", 53 | optional = true, defaultVal = "null"), 54 | file: newPathArg(@[""], help = "The file (or folder of files) to convert", 55 | optional = true), 56 | palette: newStringArg(@["--palette", "-p"], help = "The palette to use"), 57 | version: newCountArg(@["--version", "-v"], multi = false, 58 | help = "Show dye version information"), 59 | help: newHelpArg() 60 | ) 61 | 62 | args.parseOrQuit(prolog = "Dye. The ultrafast image colorizer", command = "dye") 63 | 64 | if args.version.seen: 65 | echo "dye v$#\nrelease: $#" % @[versionNum, $release] 66 | quit(0) 67 | 68 | export therapist 69 | -------------------------------------------------------------------------------- /lib/colors.nim: -------------------------------------------------------------------------------- 1 | import chroma, 2 | strutils, 3 | os, 4 | math, 5 | pixie, 6 | terminal, 7 | parseutils 8 | 9 | #proc parseColor(colors: seq[string]): seq[Color] = 10 | # var res: seq[Color] = @[] 11 | # for color in colors: 12 | # res.add(parseHex(color)) 13 | # res 14 | # 15 | # proc prepareClosestColor*(colors: seq[string]): seq[ColorLAB] = 16 | # for color in colors: 17 | # result.add parseHex(color).to(ColorLAB) 18 | # 19 | # proc getClosestColor*(colors: seq[ColorLAB], old: Color): Color = 20 | # var 21 | # minDiff = 255 22 | # minDiffColor: ColorLAB 23 | # oldLab = old.to(ColorLab) 24 | # for color in colors: 25 | # let diff = oldLab.distance(color).int 26 | # if minDiff > diff: 27 | # minDiff = diff 28 | # minDiffColor = color 29 | # minDiffColor.to(Color) 30 | 31 | # Mimic the go function 32 | proc getClosestColor*(colors: seq[ColorRGB], old: Color): Color = 33 | var 34 | r: int 35 | g: int 36 | b: int 37 | r2: int 38 | g2: int 39 | b2: int 40 | oldcol: ColorRGB 41 | res: Color 42 | minDiff: float64 = 999.0 ^ 2 43 | distance: float64 44 | for color in colors: 45 | r = color.r.int() 46 | g = color.g.int() 47 | b = color.b.int() 48 | oldcol = old.to(ColorRGB) 49 | r2 = oldcol.r.int() 50 | g2 = oldcol.g.int() 51 | b2 = oldcol.b.int() 52 | distance = ((r2 - r)^2 + (g2 - g)^2 + (b2 - b)^2).float64 53 | if minDiff > distance: 54 | minDiff = distance 55 | res = color.to(Color) 56 | res 57 | 58 | proc prepareClosestColor*(colors: seq[string]): seq[ColorRGB] = 59 | var res: seq[ColorRGB] = @[] 60 | for color in colors: 61 | res.add(parseHex(color).to(ColorRGB)) 62 | res 63 | 64 | proc getFilename*(file: string): string = 65 | extractFilename(file).split(".")[0] 66 | 67 | proc invertLuma*(color: Color): Color = 68 | var hsl = color.hsl() 69 | hsl.l = 100 - hsl.l 70 | result = color(hsl) 71 | 72 | proc checkFileOrDir*(file: string): seq[string] = 73 | if dirExists(file): 74 | result = @[] 75 | for lfile in walkDirRec(file): 76 | if ".png" in $lfile or ".jpg" in $lfile or ".jpeg" in $lfile: 77 | result.add(strip(lfile)) 78 | else: 79 | if not fileExists(file): 80 | stdout.styledWriteLine(fgRed, "Error: ", fgWhite, "File not found: " & 81 | file & "\n") 82 | result = @[file] 83 | 84 | proc rmTag*(colors: seq[string]): seq[string] = 85 | for color in colors: 86 | if "#" in color: 87 | result.add(color.replace("#", "")) 88 | else: 89 | result.add(color) 90 | 91 | proc parseColors*(input: string): seq[string] = # Please return colours 92 | var 93 | i = 0 94 | buff = "" 95 | while i < input.len: 96 | i += input.skipWhile({'#', ' ', ','}, i) 97 | i += input.parseUntil(buff, ',', i) 98 | result.add buff 99 | 100 | proc save*(image: Image, path: string) = 101 | removeFile(path) 102 | image.writeFile(path) 103 | -------------------------------------------------------------------------------- /lib/palettes.nim: -------------------------------------------------------------------------------- 1 | let pal* = ( 2 | decay: @["#171B20", "#15191d", "#1a1e23", "#21262e", "#b6beca", "#e9a180", 3 | "#1a1e24", "#4d5768", "#b6beca", "#242931", "#e05f65", "#73c291", 4 | "#f1cf8a", "#70a5eb", "#c68aee", "#74bee9", "#b6beca", "#485263", 5 | "#e05f65", "#7ddac5", "#f1cf8a", "#70a5eb", "#c68aee", "#74bee9", 6 | "#b6beca"], 7 | darkdecay: @["#101419", "#0e1217", "#13171c", "#1a1e23", "#b6beca", "#15191e", 8 | "#e9a180", "#4d5768", "#b6beca", "#242931", "#e05f65", "#73c291", 9 | "#f1cf8a", "#70a5eb", "#c68aee", "#74bee9", "#b6beca", "#485263", 10 | "#e05f65", "#7ddac5", "#f1cf8a", "#70a5eb", "#c68aee", "#74bee9", 11 | "#b6beca"], 12 | decayce: @["#0d0f18", "#0b0d16", "#0f111a", "#11131c", "#a5b6cf", "#151720", 13 | "#ecd3a0", "#1c1e27", "#a5b6cf", "#151720", "#dd6777", "#90ceaa", 14 | "#f1d8a5", "#86aaec", "#c296eb", "#93cee9", "#a5b6cf", "#1c1e27", 15 | "#dd6777", "#90ceaa", "#ecd3a0", "#86aaec", "#c296eb", "#93cee9", 16 | "#cbced3"], 17 | articblush: @["#040c16", "#cce9ea", "#c2cae2", "#d9d7d6", "#323949", 18 | "#E6676B", "#A2E4B8", "#e2d06a", "#92bbed", "#ecc6e8", "#80ffff", 19 | "#cfebec", "#3d3e51", "#FF7377", "#AAF0C1", "#eadd94", "#bdd6f4", 20 | "#f9ecf7", "#b3ffff", "#edf7f8"], 21 | iceberg: @["#161821", "#1e2132", "#c6c8d1", "#d2d4de", "#6b7089", 22 | "#e27878", "#e98989", "#b4be82", "#c0ca8e", 23 | "#e2a478", "#e9b189", 24 | "#84a0c6", "#95c4ce", "#89b8c2", "#91acd1", 25 | "#a093c7", "#ada0d3"], 26 | catppuccin: @["#F5E0DC", "#F2CDCD", "#F5C2E7", "#CBA6F7", "#F38BA8", 27 | "#EBA0AC", "#FAB387", "#F9E2AF", "#A6E3A1", "#94E2D5", "#89DCEB", 28 | "#90C1FB", 29 | "#74C7EC", "#B4BEFE", "#C6D0F5", "#AEB7D9", "#969DBC", "#7E84A0", 30 | "#666A83", "#4E5167", "#36374A", "#1E1E2E", "#12121C", "#07070A"], 31 | ok: @["#0b0d10", "#0b0d10", "#d2daf4", "#d2daf4", "#636c7e", "#c44949", 32 | "#3fcc6c", "#dfa93f", "#3580c1", "#ac45cc", "#36b5a4", "#b5cdbd", 33 | "#636c7e", "#e15858", "#53db7f", "#daa640", "#4796d9", "#b057cb", 34 | "#51d5c3", "#51d5c3"], 35 | nord: @["#2e3440", "#3b4252", "#434c5e", "#4c566a", "#d8dee9", "#e5e9f0", 36 | "#eceff4", "#8fbcbb", "#88c0d0", "#81a1c1", "#5e81ac", "#bf616a", 37 | "#d08770", 38 | "#ebcb8b", "#a3be8c", "#b48ead"], 39 | everforest: @[ 40 | "#d3c6aa", "#e67e80", "#e69875", "#dbbc7f", "#a7c080", "#83c092", "#7fbbb3", 41 | "#d699b6", "#7a8478", "#859289", "#9da9a0", "#f8f0dc", "#efead4", "#e9e5cf", 42 | "#e1ddc9", "#dcd8c4", "#b9c0ab", "#e6e9c4", "#f9e0d4", "#edeece", "#e7ede5", "#f6e9c9" 43 | ], 44 | ashes: @[ 45 | "#1C2023", "#393F45", "#565E65", "#747C84", "#ADB3BA", "#C7CCD1", "#DFE2E5", 46 | "#F3F4F5", "#C7AE95", "#C7C795", "#AEC795", "#95C7AE", "#95AEC7", "#AE95C7", 47 | "#C795AE", "#C79595" 48 | ], 49 | tokyonight: @[ 50 | "#f7768e", "#ff9e64", "#e0af68", "#9ece6a", "#73daca", "#b4f9f8", "#2ac3de", 51 | "#7dcfff", "#7aa2f7", 52 | "#bb9af7", "#c0caf5", "#a9b1d6", "#9aa5ce", "#cfc9c2", "#565f89", "#414868", 53 | "#24283b", "#1a1b26" 54 | ] 55 | ) 56 | 57 | -------------------------------------------------------------------------------- /lib/updates.nim: -------------------------------------------------------------------------------- 1 | import os, puppy, strutils, distros, 2 | strformat, zippy/ziparchives 3 | 4 | proc u*(v: string): void = 5 | let cv = fetch("https://raw.githubusercontent.com/Infinitybeond1/dye/main/dye.nimble").splitLines( 6 | )[0].split("=")[1].strip().replace("\"", "") 7 | if v.replace(".", "").strip().parseInt() < cv.replace(".", "").strip().parseInt(): 8 | stdout.write("Updates are availible, would you like to update (Y/n): ") 9 | let a = readLine(stdin).toLower() 10 | if a == "n": 11 | echo "Exiting..." 12 | quit(0) 13 | let app = getAppFilename() 14 | echo "Detecting os..." 15 | var os: string 16 | if detectOs(Windows): 17 | echo "This feature isnt supported on windows" 18 | elif detectOs(Linux): 19 | os = "linux" 20 | elif detectOs(MacOSX): 21 | os = "darwin" 22 | else: 23 | quit 1 24 | echo "Downloading file..." 25 | writeFile(getTempDir() / fmt"dye-{os}.zip", fetch(fmt"https://github.com/Infinitybeond1/dye/releases/download/v{cv.strip()}/dye-{os}.zip")) 26 | while true: 27 | if fileExists(getTempDir() / fmt"dye-{os}.zip"): 28 | break 29 | let file = getTempDir() / fmt"dye-{os}.zip" 30 | echo "Extracting..." 31 | extractAll(file, getTempDir() / "dye") 32 | removeFile(file) 33 | echo "Moving file..." 34 | removeFile(app) 35 | copyFileWithPermissions(getTempDir() / "dye" / "dye", app) 36 | removeDir(getTempDir() / "dye") 37 | echo "Completed!" 38 | elif v.replace(".", "").strip().parseInt() == cv.replace(".", "").strip().parseInt(): 39 | echo "You're all up to date" 40 | else: 41 | echo "Your version: $#\nCurrent version: $#" % @[v, cv] 42 | 43 | -------------------------------------------------------------------------------- /scripts/zigcc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | zig cc $@ 3 | -------------------------------------------------------------------------------- /src/dye.nim: -------------------------------------------------------------------------------- 1 | # Most of the comments in the code are echo statements for debug purposes. 2 | import os, 3 | chroma, 4 | pixie, 5 | strutils, 6 | progress, 7 | terminal, 8 | strformat 9 | 10 | include ../lib/args 11 | 12 | import ../lib/[colors, palettes, updates] 13 | 14 | var 15 | flipName: string 16 | convName: string 17 | lumaName: string 18 | 19 | var outfile: string 20 | var fileDir: string 21 | 22 | if args.flip.seen: 23 | outfile = flip.output.value 24 | fileDir = flip.file.value 25 | elif args.luma.seen: 26 | outfile = luma.output.value 27 | fileDir = luma.file.value 28 | else: 29 | outfile = args.output.value 30 | fileDir = args.file.value 31 | 32 | proc fileName(file: string, outfile: string): void = 33 | if outfile != "null": 34 | flipName = outfile & ".png" 35 | convName = outfile & ".png" 36 | lumaName = outfile & ".png" 37 | else: 38 | flipName = "flip-" & getFilename(file) & ".png" 39 | convName = "conv-" & getFilename(file) & ".png" 40 | lumaName = "luma-" & getFilename(file) & ".png" 41 | 42 | proc addFiles(fileDir: string): seq[string] = 43 | if dirExists(fileDir): 44 | if args.recursive.seen: 45 | for file in walkDirRec(fileDir): 46 | if file.splitFile().ext in [".png", ".jpg", ".jpeg"]: 47 | result.add(file) 48 | else: 49 | for file in walkDir(fileDir): 50 | if file.path.splitFile().ext in [".png", ".jpg", ".jpeg"]: 51 | result.add(file.path) 52 | else: 53 | result.add(fileDir) 54 | 55 | proc flipCol(imgPath: string, bar: bool): void = 56 | stdout.styledWriteLine(fgYellow, "Converting: ", fgWhite, splitFile( 57 | imgPath).name & splitFile(imgPath).ext & " ...") 58 | if bar: 59 | var imageFile = readImage(imgPath) 60 | var newImg = copy(imageFile) 61 | var bar = newProgressBar(total = imageFile.width * imageFile.height) 62 | bar.start() 63 | for y in 1..newImg.height: 64 | for x in 1..newImg.width: 65 | var rgbx = newImg.getColor(x, y).rgbx() 66 | rgbx.r = 255 - rgbx.r 67 | rgbx.g = 255 - rgbx.g 68 | rgbx.b = 255 - rgbx.b 69 | newImg.setColor(x, y, rgbx.color) 70 | bar.increment() 71 | bar.finish() 72 | stdout.styledWriteLine(fgGreen, "Completed: ", fgWhite, splitFile( 73 | imgPath).name & splitFile(imgPath).ext & "\n") 74 | fileName(imgPath, flip.output.value) 75 | newImg.save(flipName) 76 | else: 77 | var imageFile = readImage(imgPath) 78 | var newImg = copy(imageFile) 79 | for y in 1..newImg.height: 80 | for x in 1..newImg.width: 81 | var rgbx = newImg.getColor(x, y).rgbx() 82 | rgbx.r = 255 - rgbx.r 83 | rgbx.g = 255 - rgbx.g 84 | rgbx.b = 255 - rgbx.b 85 | newImg.setColor(x, y, rgbx.color) 86 | stdout.styledWriteLine(fgGreen, "Completed: ", fgWhite, splitFile( 87 | imgPath).name & splitFile(imgPath).ext & "\n") 88 | fileName(imgPath, flip.output.value) 89 | newImg.save(flipName) 90 | 91 | proc lumaCol(imgPath: string, bar: bool): void = 92 | stdout.styledWriteLine(fgYellow, "Converting: ", fgWhite, splitFile( 93 | imgPath).name & splitFile(imgPath).ext & " ...") 94 | if bar: 95 | var imageFile = readImage(imgPath) 96 | var newImg = copy(imageFile) 97 | var bar = newProgressBar(total = imageFile.width * imageFile.height) 98 | bar.start() 99 | for y in 1..newImg.height: 100 | for x in 1..newImg.width: 101 | #echo 1 - hsl(newImg.getColor(x, y)).l / 100 102 | newImg.setColor(x, y, newImg.getColor(x, y).invertLuma()) 103 | #echo -(newImg.getColor(x, y).hsl().l / 100) 104 | bar.increment() 105 | bar.finish() 106 | stdout.styledWriteLine(fgGreen, "Completed: ", fgWhite, splitFile( 107 | imgPath).name & splitFile(imgPath).ext & "\n") 108 | fileName(imgPath, luma.output.value) 109 | newImg.save(lumaName) 110 | else: 111 | var imageFile = readImage(imgPath) 112 | var newImg = copy(imageFile) 113 | for y in 1..newImg.height: 114 | for x in 1..newImg.width: 115 | #echo 1 - hsl(newImg.getColor(x, y)).l / 100 116 | newImg.setColor(x, y, newImg.getColor(x, y).invertLuma()) 117 | #echo -(newImg.getColor(x, y).hsl().l / 100) 118 | stdout.styledWriteLine(fgGreen, "Completed: ", fgWhite, splitFile( 119 | imgPath).name & splitFile(imgPath).ext & "\n") 120 | fileName(imgPath, luma.output.value) 121 | newImg.save(lumaName) 122 | 123 | proc col(imgPath: string, bar: bool, colors: seq[string]): void = 124 | stdout.styledWriteLine(fgYellow, "Converting: ", fgWhite, splitFile( 125 | imgPath).name & splitFile(imgPath).ext & " ...") 126 | fileName(imgPath, args.output.value) 127 | if bar: 128 | var imageFile = readImage(imgPath) 129 | let h = imageFile.height 130 | let w = imageFile.width 131 | let colorsRGB = colors.prepareClosestColor() 132 | var newImg = copy(imageFile) 133 | var bar = newProgressBar(total = h) 134 | bar.start() 135 | for y in 1..h: 136 | for x in 1..w: 137 | newImg.setColor(x = x, y = y, color = getClosestColor(colorsRGB, 138 | newImg.getColor(x, y))) 139 | bar.increment() 140 | newImg.save(convName) 141 | bar.finish() 142 | stdout.styledWriteLine(fgGreen, "Completed: ", fgWhite, splitFile( 143 | imgPath).name & splitFile(imgPath).ext & "\n") 144 | else: 145 | var imageFile = readImage(imgPath) 146 | let h = imageFile.height 147 | let w = imageFile.width 148 | let colorsRGB = colors.prepareClosestColor() 149 | var newImg = copy(imageFile) 150 | for y in 1..h: 151 | for x in 1..w: 152 | newImg.setColor(x = x, y = y, color = getClosestColor( 153 | colorsRGB, newImg.getColor(x, y))) 154 | newImg.save(convName) 155 | stdout.styledWriteLine(fgGreen, "Completed: ", fgWhite, splitFile( 156 | imgPath).name & splitFile(imgPath).ext & "\n") 157 | 158 | if args.flip.seen: 159 | for img in addFiles(flip.file.value): 160 | try: 161 | flipCol(img, flip.bar.seen) 162 | except: 163 | stdout.styledWriteLine(fgRed, "Error: ", fgWhite, getCurrentExceptionMsg(), "\n") 164 | continue 165 | elif args.update.seen: 166 | u(versionNum) 167 | elif args.luma.seen: 168 | for img in addFiles(luma.file.value): 169 | try: 170 | lumaCol(img, luma.bar.seen) 171 | except: 172 | stdout.styledWriteLine(fgRed, "Error: ", fgWhite, getCurrentExceptionMsg(), "\n") 173 | continue 174 | elif args.list.seen: 175 | for k, v in pal.fieldPairs: 176 | discard v 177 | echo k 178 | else: 179 | var cols: seq[string] 180 | if "," in args.palette.value: 181 | cols = args.palette.value.parseColors() 182 | elif fileExists(args.palette.value): 183 | cols = readFile(args.palette.value).parseColors() 184 | else: 185 | for k, v in pal.fieldPairs: 186 | if args.palette.value == k: 187 | cols = v 188 | break 189 | cols = cols.rmTag() 190 | for img in addFiles(args.file.value): 191 | try: 192 | col(img, args.bar.seen, cols) 193 | except: 194 | stdout.styledWriteLine(fgRed, "Error: ", fgWhite, getCurrentExceptionMsg(), "\n") 195 | continue 196 | --------------------------------------------------------------------------------