Permalink
Find file
e5b8a1e Aug 7, 2015
executable file 182 lines (149 sloc) 6.37 KB
#!/bin/sh
# Copyright 2013 - 2015 Bruce Ingalls
# MIT license, similar to GraphicsMagick & ImageMagick:
# http://opensource.org/licenses/MIT http://www.graphicsmagick.org/Copyright.html
GM=`which gm` > /dev/null 2>&1 #GM blank for ImageMagick
if [ $# -gt 0 ]; then
echo "Usage: `basename $0` [no args | -h This help]"
echo 'Lossless & lossy compresses all *.gif, *.jpg, *.png in a directory.'
echo 'Compares as many CLI F/OSS tools as possible, with singular goal of smallest lossless compression'
echo 'Then, GraphicsMagick creates a "compressed" folder, with lossy copies of images'
echo 'See also the source code, for tunable parameters. Any suggested installs follow - '
if [ -z $GM ]; then # convert is the ImageMagick tool
which convert >/dev/null || (echo 'Please install GraphicsMagick or ImageMagick!'; exit)
fi
#Lossless gif
which gifsicle >/dev/null || echo 'gifsicle recommended' # fast, but limited results?
#Lossless jpg
which jpegoptim >/dev/null || echo 'jpegoptim recommended'
which jpegrescan >/dev/null || echo 'jpegrescan recommended'
#Lossless png
which optipng >/dev/null || 'optipng recommended'
which pngcrush >/dev/null || echo 'pngcrush recommended'
which pngnq >/dev/null || echo 'pngnq recommended'
#Lossy png
#Disabled: not clear, that pngquant compresses better than *magick.
#which pngquant || echo 'Install pngquant for greater compression'
exit
fi
# USER TUNED VALUES
COMPRESS_DIR='./compressed' # Lossy compressed copies go in $COMPRESS_DIR.
RATIO='40' # Percent compression. I recommend a range of 40%(small) - 75%(quality)
TRANSPARENT_RATIO='05' # png only; compression ratio of transparent background
# END USER TUNED VALUES
# graphicsmagick (faster alternative, but fewer unused features? than imagemagick)
# imagemagick
# gif2png # Copies *.gif into unanimated *.png files
# gifsicle
# jpegoptim
# jpegrescan
# optipng
# pngcrush
# pngnq # seems better than pngquant
# Not impressed with compression of :
# pngquant; uncomment yourself
# giflossy too lazy to install
# GraphicsMagick seems to outperform ImageMagick
# ToDo: handle -sampling-factor and filter-type
# ToDo: Handle 2-step gif optimization, where 2nd pass compresses better
# http://www.graphicsmagick.org/GraphicsMagick.html#details-quality
# See also lossless http://www.smushit.com/ysmush.it/
# GraphicsMagick & ImageMagick only handle .jpg & .png, and limited .gif
CWD=`pwd`
#Create dest dir for compressed copies of images
if [ ! -d $COMPRESS_DIR ];then
mkdir $COMPRESS_DIR
else
#read -t15 is bash for timeout of 15 seconds
read -p "$COMPRESS_DIR/ already exists. 'y' to overwrite existing files: " proceed
if [ "y" != $proceed ];then
echo "Exiting, to preserve existing contents in ./$COMPRESS_DIR/"
exit 1;
fi
fi
# Assumes images follow standard naming convention of *.gif, *.jpg, *.png
# Does anyone use *.jpeg ?
# Remember to wrap "$i", "$file", "$smallest" for filenames with spaces
if [ `find . -maxdepth 1 -name "*.jpg" | head -1` ]; then # *.jpg exists
for i in *.jpg;do
if [ `which jpegoptim` ]; then jpegoptim "$i" ;fi # also supports lossy flag
file=`basename "$i"`
if [ `which jpegrescan` ]; then
jpegrescan -s "$i" $COMPRESS_DIR/"$file"
smallest=`ls -S "$file" $COMPRESS_DIR/"$file"|tail -1`
if [ "$smallest" = $COMPRESS_DIR/"$file" ];then
mv -f "$smallest" "$file"
else
rm -f $COMPRESS_DIR/"$file"
fi
fi
cp "$i" $COMPRESS_DIR/tmp_"$file"
$GM convert $COMPRESS_DIR/tmp_"$file" -quality $RATIO $COMPRESS_DIR/tmp_lossy.jpg
smallest=`ls -S $COMPRESS_DIR/tmp_*|tail -1`
if [ "$smallest" = "$COMPRESS_DIR/tmp_lossy.jpg" ];then
mv -f "$smallest" $COMPRESS_DIR/"$file"
fi
rm $COMPRESS_DIR/tmp_*
done
fi # *.jpg exists
# GraphicsMagick can't compress gif files. Create unanimated png, if smaller
if [ `find . -maxdepth 1 -name "*.gif" | head -1` ]; then # *.gif exists
for i in *.gif;do
if [ `which gifsicle` ]; then gifsicle -b -O3 "$i" ;fi # fast, but limited results
file=`basename "$i" .gif`
cp "$i" $COMPRESS_DIR/tmp_"$file".gif
$GM convert "$i" $COMPRESS_DIR/tmp_lossless.png
# png calls syntax of transparent 0 main_image ratio; ex quality 30% 51%
if [ -f "$COMPRESS_DIR/tmp_lossless.png" ];then
#echo "Converting "$i" to png!"
$GM convert $COMPRESS_DIR/tmp_lossless.png -quality \
"$TRANSPARENT_RATIO0$RATIO" $COMPRESS_DIR/tmp_lossy.png
smallest=`ls -S $COMPRESS_DIR/tmp_*|tail -1` # compare file size
if [ `echo "$smallest" | egrep '.png$'` ];then
mv -f "$smallest" $COMPRESS_DIR/"$file".png
cd $COMPRESS_DIR
rm -f "$file".gif
ln -s "$file".png "$file".gif
cd $CWD
fi
else
echo "Could not convert $i to png!"
fi
rm $COMPRESS_DIR/tmp_*
done
fi # *.gif exists
if [ `find . -maxdepth 1 -name "*.png" | head -1` ]; then # *.png exists
mkdir $COMPRESS_DIR/tmp
for i in *.png;do
# Optipng only replaces original, if smaller.
if [ `which optipng` ]; then optipng -quiet -o2 "$i" ;fi
#More pngcrush options to hack & benchmark. Pngcrush cannot replace self.
if [ `which pngcrush` ]; then pngcrush -q "$i" $COMPRESS_DIR/tmp/crush.png ;fi
#if [ `which pngcrush` ]; then pngcrush -q -l9 -m0 "$i" $COMPRESS_DIR/tmp/crush.png ;fi
file=`basename "$i"`
if [ `which pngnq` ]; then
pngnq -e '.png' -d $COMPRESS_DIR "$i"
smallest=`ls -S "$file" $COMPRESS_DIR/"$file"|tail -1`
if [ "$smallest" = $COMPRESS_DIR/"$file" ];then
mv -f "$smallest" "$file"
else
rm -f $COMPRESS_DIR/"$file"
fi
fi
#png calls syntax of transparent 0 main_image ratio; ex quality 30% 51%
$GM convert "$i" -quality "$TRANSPARENT_RATIO0$RATIO" $COMPRESS_DIR/tmp/magick.png
smallest=`ls -1S $COMPRESS_DIR/tmp/*|tail -1`
if [ `uname` = 'Darwin' ]; then
if [ `du -k "$smallest"|cut -f1` -lt `du -k "$i"|cut -f1` ];then # Mac OSX does not support bytes :(
mv -f "$smallest" $COMPRESS_DIR/"$file"
fi
else
if [ `du -b "$smallest"|cut -f1` -lt `du -b "$i"|cut -f1` ];then # Assume Linux, which can compare bytes
mv -f "$smallest" $COMPRESS_DIR/"$file"
fi
fi
#Insert a read here, to pause, and compare *magick to pngcrush, for benchmarking.
rm $COMPRESS_DIR/tmp/*
done
rmdir $COMPRESS_DIR/tmp
fi # *.png exists