Skip to content

Instantly share code, notes, and snippets.

@skull-squadron
Last active October 19, 2025 12:49
Show Gist options
  • Save skull-squadron/b9bd8acebdf6e43974985ee078a38c20 to your computer and use it in GitHub Desktop.
Save skull-squadron/b9bd8acebdf6e43974985ee078a38c20 to your computer and use it in GitHub Desktop.
any image to PCX converter script helper
#!/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 "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment