Last active
August 31, 2024 11:58
-
-
Save ernstki/74aba058622a9cea43bebc4028aba5cd to your computer and use it in GitHub Desktop.
Use ImageMagick to trim extra pixels from an image and replace with a uniform border (default 10 pixels); good for screenshots
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
#!/usr/bin/env bash | |
## | |
## Trim extra pixels from around an image, e.g., a screenshot, and replace | |
## with a border of uniform width, of a color sampled from the four image | |
## corners, using ImageMagick 6.x (or above?) | |
## | |
## Author: Kevin Ernst <ernstki -at- mail.uc.edu> | |
## Date: 29 August 2024 | |
## License: WTFPL or ISC at your option | |
## Homepage: https://gist.github.com/ernstki/74aba058622a9cea43bebc4028aba5cd | |
## Usage: See the output of `reborder --help` or HELP below | |
## | |
## References: | |
## 1. https://imagemagick.org/Usage/crop/#border | |
## 2. https://stackoverflow.com/a/48685590/785213 | |
## | |
if (( DEBUG )); then | |
set -eExo pipefail | |
trap 'echo "Trapped at line #$LINENO${FUNCNAME:+ in $FUNCNAME}."' ERR | |
fi | |
set -u | |
ME=${BASH_SOURCE[0]##*/} | |
HELP=" | |
$ME - trim extra pixels from an image, then add a border of the same color | |
usage: | |
$ $ME [-h|--help] | |
$ $ME [-f|--force] [-n|--dry-run] [BORDERSIZE] IMAGE [IMAGE…] | |
where: | |
IMAGE is any image ImageMagick can handle | |
BORDERSIZE is a valid ImageMagick '-bordersize' (default: 10x10) | |
-f, --force forces overwriting of existing rebordered image(s) | |
-n, --dry-run simulates what would happen; does not modify any images | |
-q, --quiet suppresses \"Wrote 'newimage.ext'.\" messages | |
homepage: | |
https://gist.github.com/ernstki/74aba058622a9cea43bebc4028aba5cd | |
" | |
plurality() { | |
# read hex triplet color values and print the one that appears most often | |
# or return an error if there's no plurality | |
awk ' | |
{ colorcounts[$1]++ } | |
END { | |
for (c in colorcounts) { | |
if (colorcounts[c] > max) { | |
it = c | |
max = colorcounts[c] | |
} | |
} | |
if (max <= NR/2) exit 1 | |
else print it | |
}' | |
} | |
images=() | |
borderwidth=10 | |
force= | |
# could make an option for this later | |
fuzz='1%' | |
suffix='+rebordered' | |
dryrun=${DRYRUN:-} | |
quiet= | |
endofopts= | |
while (( $# )); do | |
if (( endofopts )); then images+=("$1"); shift; continue; fi | |
case $1 in | |
--) | |
endofopts=1 | |
;; | |
-h|--help) | |
echo "$HELP" | |
exit | |
;; | |
1|1x1|[0-9]*[0-9]|[0-9]*[0-9]x[0-9]*[0-9]) | |
borderwidth=$1 | |
;; | |
-f|--force|--force-overwrite) | |
force=1 | |
;; | |
-n|--dryrun|--dry-run) | |
dryrun=1 | |
;; | |
-q|--quiet|--silent) | |
quiet=1 | |
;; | |
*) | |
images+=("$1") | |
;; | |
esac | |
shift | |
done | |
if [[ -z ${images[*]} ]]; then | |
echo "No images specified to operate on. Try '--help'." >&2; | |
exit 1 | |
fi | |
tl='%[hex:u.p{0,0}]' | |
tr='%[hex:u.p{w-1,0}]' | |
bl='%[hex:u.p{0,h-1}]' | |
br='%[hex:u.p{w-1,h-1}]' | |
processed=0 | |
for i in "${images[@]}"; do | |
if [[ ! -r $i ]]; then | |
echo "Unreadable or non-existent file '$i'. Skipping." >&2; | |
continue | |
fi | |
newi="${i%%.*}$suffix.${i##*.}" | |
cornerpixels=$(convert "$i" -format "$tl\n$tr\n$bl\n$br\n" info:) | |
if (( $? )); then | |
echo "Problem running ImageMagick 'convert'; try DEBUG=1" >&2 | |
exit 1 | |
fi | |
if color=$(echo "$cornerpixels" | plurality); then | |
if [[ -s $newi ]] && (( !force && ! dryrun)); then | |
read -rp "Image '$newi' already exists. Overwrite it? [y/N] " | |
if [[ -z $REPLY || $REPLY =~ ^[nN] ]]; then | |
if (( !quiet )); then | |
echo "Not overwriting existing '$newi'." >&2 | |
fi | |
continue | |
fi | |
fi | |
${dryrun:+echo [DRY RUN] }convert "$i" -trim -fuzz "$fuzz" +repage \ | |
"$newi" | |
${dryrun:+echo [DRY RUN] }mogrify -bordercolor "#$color" -border \ | |
"$borderwidth" "$newi" | |
if (( !dryrun && !quiet )); then echo "Wrote '$newi'." >&2; fi | |
processed=$(( processed + 1 )) | |
else | |
echo "Corner pixels of '$i' are too different, can't add a border." \ | |
"Skipping." >&2 | |
fi | |
done | |
if (( !processed )); then | |
echo "No images were processed." >&2; | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Installation
Make sure
~/bin
is in your search path. These days, it usually is. Then:Example
Running
reborder
with default settings turns this:into this:
License
WTFPL or ISC, at your option.