Last active
August 15, 2023 01:53
-
-
Save ernstki/495ff1a60509e0b771f0d65740de1a19 to your computer and use it in GitHub Desktop.
Convert many images to any ImageMagick-supported format in parallel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# intended for use with https://github.com/erichs/composure | |
# requires ImageMagick's 'convert' and GNU Parallel | |
# source: https://gist.github.com/ernstki/495ff1a60509e0b771f0d65740de1a19/edit | |
convertto () | |
{ | |
author 'Kevin Ernst' | |
about 'Convert arguments to another image format based on extension' | |
example "$ convertto jpg *.heic" | |
example "$ convertto -geometry 200x200 png *.heic" | |
param "-* - any valid ImageMagick 'convert' command line option" | |
param '$* - image(s) to convert' | |
group 'graphics' | |
group 'util' | |
local endopts dryrun ext opts=() files=() | |
local -A formats | |
local cache=~/.cache/imagemagick_formats.lst | |
local now=$(date +%s) | |
local setx=$(builtin set +o | grep '\bxtrace\b') | |
# set TRACE=1 in the environment for execution tracing (for debugging) | |
# you can also just run this inside a subshell with 'func() ()' | |
# instead of 'func() {}', and not worry about setting 'set +x' when | |
# you're done, but I wanted to see if this was possible to do (it is) | |
(( TRACE )) && set -x | |
trap "$setx" RETURN | |
# cache ImageMagick's list of formats at most once per day; also not | |
# stricly necessary -- it doesn't take *that* long to run, but I wanted | |
# to figure out how to do it | |
if [[ ! -s $cache ]] || (( (now - $(date -r $cache +%s)) > 86400 )); then | |
mkdir -p ~/.cache | |
identify -list format \ | |
| awk '/^ *[A-Z0-9*]+ /{gsub(/\*/,"",$1);if($1){print $1}}' \ | |
> $cache | |
fi | |
# read in list of formats | |
while read fmt; do formats[$fmt]=1; done < $cache | |
while (( $# )); do | |
if (( endopts )); then | |
files+=("$1"); shift; continue | |
fi | |
case $1 in | |
-h|--help) | |
reference $FUNCNAME | |
return | |
;; | |
-n|--dry-run) | |
dryrun=1 | |
;; | |
--) | |
endopts=1 | |
;; | |
-*) | |
opts+=("$1") | |
;; | |
*) | |
if [[ -r $1 ]]; then | |
files+=("$1") | |
elif [[ ${opts[@]: -1} =~ ^- && ! $ext ]]; then | |
# probably an argument to a previous ImageMagick option | |
opts+=("$1") | |
# the output of `identify -list format` is upper-case, so | |
# upper-case the argument and see if it's a key in $formats | |
elif [[ ${formats[${1^^}]} && ! $ext ]]; then | |
ext=$1 | |
else | |
echo "ERROR: Unexpected option or unsupported image format '$1'." >&2 | |
return 1 | |
fi | |
;; | |
esac | |
shift | |
done | |
if [[ ${#files[@]} -eq 0 ]]; then | |
echo "ERROR: No files specified for conversion." >&2 | |
return 1 | |
fi | |
parallel ${dryrun:+--dry-run }convert ${opts:+"${opts[@]}"} {} {.}.$ext ::: "${files[@]}" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment