mirror of
https://github.com/m-housh/dotfiles.git
synced 2026-02-14 22:22:40 +00:00
148 lines
4.8 KiB
Bash
Executable File
148 lines
4.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# B9 June 2017
|
|
|
|
# mktrans
|
|
# This is similar to ImageMagick's bg_removal script, but much higher
|
|
# quality. (It's also faster and simpler to use.)
|
|
#
|
|
# For a sample, run these commands:
|
|
# convert logo: logo.png
|
|
# mktrans logo.png
|
|
# display logo-transparent.png
|
|
|
|
|
|
# Fuzz is how far off the background color can be (in percent).
|
|
# This is important for getting good antialiasing.
|
|
defaultfuzz=20
|
|
|
|
usage() {
|
|
cat <<EOF
|
|
|
|
mktrans: Convert images into shaped transparent pngs by floodfilling
|
|
the background with transparency (antialiased alpha channel).
|
|
Unless a different starting pixel is specified, the top left
|
|
pixel is used as the "background" color to remove and
|
|
floodfill starts from all four image edges,
|
|
|
|
Typical usage:
|
|
|
|
mktrans foo.jpg (creates foo-transparent.png)
|
|
|
|
Usage: mktrans [-f <fuzz>] [-s|-S] [-p <x>,<y>] [-v] <files ... >
|
|
|
|
-f <fuzz>: How loosely to match the background color (default $defaultfuzz%)
|
|
|
|
Advanced options:
|
|
-s: Use speedy antialiasing (much faster, slightly less acurate)
|
|
-S: Supress antialiasing completely. (Useful for repeated runs)
|
|
p <x>,<y>: Floodfill from pixel at x,y instead of 0,0
|
|
-v: Verbose
|
|
EOF
|
|
|
|
# * Side note: This creates an antialiased (blurred) alpha channel
|
|
# that is also eroded by half a pixel to avoid halos. ImageMagick's
|
|
# morphological operations don't (yet?) work at the subpixel level,
|
|
# so I'm blowing up the alpha channel to 200% before eroding. Since
|
|
# this can be slow on large images, consider using the '-s' option
|
|
# which uses a faster, lower quality antialiasing.
|
|
|
|
# * Running this script on an image that already has transparency will
|
|
# erode the image due to the antialiasing. Using -S is a workaround,
|
|
# but is not very satisfactory. Perhaps this script should remove any
|
|
# existing transparency before manipulating the image and then add it
|
|
# back in at the end. But then again, how often are people going to
|
|
# want to do that? The only use I can think of is when using -p.
|
|
|
|
# * Because of the previous bug, if you do use -p to fill lots of
|
|
# lagoons, you'll probably want to use -A at the same time.
|
|
|
|
# * Finding the coordinates for -p is a pain. It'd be nice if there was
|
|
# a -P option which let the user click on a point (or multiple points)
|
|
# in the image to start the floodfill.
|
|
|
|
exit 0
|
|
}
|
|
|
|
fuzz=$defaultfuzz
|
|
pixelcomma="0,0"
|
|
pixelplus="+0+0"
|
|
|
|
while getopts f:sAShp:v name; do
|
|
case $name in
|
|
f) fuzz=$OPTARG
|
|
;;
|
|
s) sflag=True
|
|
;;
|
|
S|A) noantialias=True
|
|
;;
|
|
v) vflag=True
|
|
;;
|
|
h) usage
|
|
;;
|
|
p) pixelcomma=$OPTARG
|
|
pixelplus=+${OPTARG%,*}+${OPTARG#*,}
|
|
pflag=True
|
|
;;
|
|
*) usage
|
|
;;
|
|
esac
|
|
done
|
|
|
|
shift $((OPTIND-1))
|
|
[[ "$#" != 0 ]] || usage
|
|
|
|
|
|
for filename; do
|
|
# Get color of 0,0 (top left) pixel
|
|
color=$(convert "$filename" -format "%[pixel:p{$pixelcomma}]" info:-)
|
|
if [[ "$color" == *rgba*",0)" ]]; then
|
|
color="${color%,0)},1)" # Floodfill only works with opaque colors.
|
|
fi
|
|
if [[ "$color" == "none" ]]; then
|
|
echo "Error: $filename: pixel at $pixelcomma is completely transparent. Cannot floodfill." >&2
|
|
continue
|
|
fi
|
|
|
|
options=""
|
|
if [ -z "$pflag" ]; then
|
|
# Add a 1 pixel border so we'll fill from the bottom and sides as well.
|
|
options+=" -bordercolor $color -border 1 "
|
|
fi
|
|
# In a new stack, make a copy of the image
|
|
options+=" ( +clone "
|
|
# [copy] floodfill with transparency ("none") starting at top-left
|
|
options+=" -fuzz $fuzz% -fill none -floodfill $pixelplus $color"
|
|
# [copy] extract just the transparency (alpha channel)
|
|
options+=" -alpha extract"
|
|
|
|
if [ -z "$noantialias" ]; then
|
|
if [ -z "$sflag" ]; then
|
|
# [copy] blow up the alpha channel so we can do sub-pixel morphology
|
|
options+=" -geometry 200%"
|
|
# [copy] blur the alpha channel to make it antialiased
|
|
options+=" -blur 0x0.5"
|
|
# [copy] shrink the region that is opaque by half a pixel.
|
|
options+=" -morphology erode square:1"
|
|
# [copy] scale the alpha channel back to normal size.
|
|
options+=" -geometry 50%"
|
|
else # sflag: speedy antialias
|
|
# [copy] blur the alpha channel to make it antialiased
|
|
options+=" -blur 0x1"
|
|
# [copy] only antialias inside the figure (<50% opacity becomes 0%)
|
|
options+=" -level 50%,100%"
|
|
fi
|
|
fi
|
|
# [copy] end the stack.
|
|
options+=" ) "
|
|
# Compose the original image and the copy's alpha channel.
|
|
options+=" -compose CopyOpacity -composite"
|
|
if [ -z "$pflag" ]; then
|
|
# Remove the 1 pixel border we added
|
|
options+=" -shave 1"
|
|
fi
|
|
|
|
[ "$vflag" ] && echo convert "$filename" $options "${filename%.*}-transparent.png"
|
|
|
|
convert "$filename" $options "${filename%.*}-transparent.png"
|
|
done
|