#!/usr/bin/env bash # requires magick from ImageMagick >= 6.5 (7+ is okay too) # Suppors output to non-pcx formats too: # --ext .bmp # Can be sourced by zsh or bash, but only use filetopcx__convert_file or filetopcx__main filetopcx__tmpdir= filetopcx__ext='.pcx' filetopcx__files=() filetopcx__args=( -compress RLE -alpha off -dither FloydSteinberg -density 300 -colors 256 -verbose ) filetopcx__one_arg_flags=( -adaptive-blur -adaptive-resize -adaptive-sharpen -alpha -attenuate -authenticate -auto-threshold -background -bench -bias -bilateral-blur -black-threshold -blend -blue-primary -blue-shift -blur -border -bordercolor -borderwidth -brightness-contrast -cache -canny -caption -cdl -channel +channel -channel-fx -charcoal -chop -clahe -clip-path -clone -color-matrix -color-threshold -colorize -colormap -colors -colorspace -comment -complex -compose -compress -connected-components -contrast-stretch -convolve -crop -cycle -debug -decipher -define -delay -delete -density -depth -deskew -direction -displace -display -dispose -dissimilarity-threshold -dissolve -distribute-cache -dither -draw -duplicate -edge -emboss -encipher -encoding -endian -evaluate-sequence -extent -extract -family -features -fill -filter -font -foreground -format -frame -fuzz -fx -gamma -gaussian-blur -geometry -gravity -grayscale -green-primary -highlight-color -hough-lines -iconGeometry -illuminant -implode -insert -intensity -intent -interlace -interline-spacing -interpolate -interpolative-resize -interword-spacing -kerning -kmeans -kuwahara -kuwahara -label -lat -layers -level +level -level-colors +level-colors -linear-stretch -liquid-rescale -list -log -loop -lowlight-color -map -mattecolor -mean-shift -median -metric -mode -modulate -morph -motion-blur -noise +noise -opaque -ordered-dither -page -paint -path -pause -perceptible -pointsize -polaroid -poly -posterize -precision -preview -print -process -profile +profile -quality -quantize -raise -random-threshold -range-threshold -read -read-mask -red-primary -region -remap -repage -resample -reshape -resize -roll -rotate -rotational-blur -sample -sampling-factor -scale -scene -script -segment +set -selective-blur -sepia-tone -shade -shadow -sharpen -shave -shear -sigmoidal-contrast +sigmoidal-contrast -similarity-threshold -size -sketch -smush -snaps -solarize -splice -spread -stegano -stereo -storage-type -stretch -stroke -strokewidth -style -swap -swirl -text-font -texture -threshold -thumbnail -tile -tile-offset -tint -title -transparent -transparent-color -treedepth -type -undercolor -units -unsharp -update -view -vignette -virtual-pixel -visual -watermark -wave -wavelet-denoise -weight -white-point -white-threshold -window -word-break -write +write -write-mask ) filetopcx__two_arg_flags=( -copy -distort -evaluate -floodfill -function -limit -orient -set -sparse-color -statistic ) filetopcx__count_args_for_flag() { local a for a in "${filetopcx__one_arg_flags[@]}"; do if [[ "$1" == "$a" ]]; then echo 2 return fi done for a in "${filetopcx__two_arg_flags[@]}"; do if [[ "$1" == "$a" ]]; then echo 3 return fi done echo 1 } filetopcx__die() { echo >&2 "$@" exit 1 } filetopcx__parse_options() { (("$#" > 0)) || filetopcx__die "Usage: $0 [magick options] file..." while (($# > 0)); do case "$1" in -) filetopcx__files+=("$1") ;; --) shift break ;; --ext) (($# >= 2)) || filetopcx__die "Missing argument(s) for option: $1" filetopcx__ext=".${2#.}" shift ;; -* | +*) n=$(filetopcx__count_args_for_flag "$1") (($# >= n)) || filetopcx__die "Missing argument(s) for option: $1" filetopcx__args+=("${@:1:n}") shift $((n - 1)) ;; *) filetopcx__files+=("$1") ;; esac shift done filetopcx__files+=("$@") } filetopcx__ensure_tmpdir() { if [[ -z "$filetopcx__tmpdir" ]]; then # shellcheck disable=SC2154 trap 'e=$?; trap - EXIT; [[ -n "$filetopcx__tmpdir" ]] && rm -rf "$filetopcx__tmpdir"; exit $e' EXIT filetopcx__tmpdir=$(mktemp -d) fi } filetopcx__convert_file() { ( set -euEo pipefail [[ -z "${FILETOPCX__DEBUG-}" ]] || set -x filetopcx__ensure_tmpdir file="$1" orig_base=$(basename "$file") new_base="${orig_base%.*}${filetopcx__ext}" tmp="$filetopcx__tmpdir/$new_base" out="$(dirname "$(realpath "$(file)")")/$new_base" "${MAGICK:-magick}" \ "$file" \ "${filetopcx__args[@]}" \ "$tmp" mv "$tmp" "$out" ) } filetopcx__main() { ( set -euEo pipefail [[ -z "${FILETOPCX__DEBUG-}" ]] || set -x filetopcx__parse_options "$@" for file in "${filetopcx__files[@]}"; do filetopcx__convert_file "$file" done ) } filetopcx__is_sourced() { if [ -n "${ZSH_VERSION-}" ]; then [[ "$ZSH_EVAL_CONTEXT" = *:file:* ]] elif [ -n "${BASH_VERSION-}" ]; then (return 0 2>/dev/null) else filetopcx__die 'only bash and zsh are supported' fi } #### main filetopcx__is_sourced || filetopcx__main "$@"