Skip to content

Instantly share code, notes, and snippets.

@LiamKarlMitchell
Forked from lgiraudel/optimize.sh
Last active February 7, 2017 04:35
Show Gist options
  • Save LiamKarlMitchell/10b96093391792efc2cb6bb7f5c5fbf4 to your computer and use it in GitHub Desktop.
Save LiamKarlMitchell/10b96093391792efc2cb6bb7f5c5fbf4 to your computer and use it in GitHub Desktop.
Optimize Images sh script. Original: http://hugogiraudel.com/2013/07/29/optimizing-with-bash/
#!/bin/bash
# Note, apt-get on Ubuntu seems to be providing an out of date optipng.
# Try doing this to install version 0.7.6
# Run optipng -v to see the version you have installed.
# wget http://downloads.sourceforge.net/project/optipng/OptiPNG/optipng-0.7.6/optipng-0.7.6.tar.gz
# tar xvf optipng-0.7.6.tar.gz
# cd optipng-0.7.6
# ./configure
# make
# sudo cp /src/optipng/optipng /usr/local/bin/optipng
# optipng -v
PROGNAME=${0##*/}
INPUT=''
QUIET='0'
NOSTATS='0'
RETAINPATH='0'
max_input_size=0
max_output_size=0
usage()
{
cat <<EO
Usage: $PROGNAME [options]
Script to optimize JPG and PNG images in a directory.
Options:
EO
cat <<EO | column -s\& -t
-h, --help & shows this help
-q, --quiet & disables output
-i, --input [dir] & specify input directory (current directory by default)
-o, --output [dir] & specify output directory ("output" by default)
-ns, --no-stats & no stats at the end
-r, --retain-path & retains the directory structure when writing into output
EO
}
command_exists () {
type "$1" &> /dev/null ;
}
# $1: input image
# $2: output image
optimize_image()
{
input_file_size=$(stat -c%s "$1")
max_input_size=$(expr $max_input_size + $input_file_size)
if [ "${1##*.}" = "png" ]; then
optipng -o2 -clobber -strip all -quiet $1 -out $2
# pngcrush -q -rem alla -reduce -m 7 $2 $2 >/dev/null
#pngcrush -rem alla -nofilecheck -reduce -m 7 $2 $2>/dev/null
#pngcrush -rem alla -nofilecheck -reduce -m 7 -ow $2 > /dev/null
#pngcrush -reduce -brute -ow $2 > /dev/null
fi
if [ "${1##*.}" = "jpg" -o "${1##*.}" = "jpeg" ]; then
jpegtran -copy none -optimize -progressive $1 > $2
fi
output_file_size=$(stat -c%s "$2")
max_output_size=$(expr $max_output_size + $output_file_size)
}
get_max_file_length()
{
local maxlength=0
IMAGES=$(find $INPUT -regextype posix-extended -regex '.*\.(jpg|jpeg|png)' | grep -v $OUTPUT)
for CURRENT_IMAGE in $IMAGES; do
filename=$(basename "$CURRENT_IMAGE")
if [[ ${#filename} -gt $maxlength ]]; then
maxlength=${#filename}
fi
done
echo "$maxlength"
}
main()
{
# If $INPUT is empty, then we use current directory
if [[ "$INPUT" == "" ]]; then
INPUT=$(pwd)
fi
# If $OUTPUT is empty, then we use the directory "output" in the current directory
if [[ "$OUTPUT" == "" ]]; then
OUTPUT=$(pwd)/output
fi
# We create the output directory
mkdir -p $OUTPUT
# To avoid some troubles with filename with spaces, we store the current IFS (Internal File Separator)...
SAVEIFS=$IFS
# ...and we set a new one
IFS=$(echo -en "\n\b")
max_filelength=`get_max_file_length`
pad=$(printf '%0.1s' "."{1..600})
sDone=' [ DONE ]'
linelength=$(expr $max_filelength + ${#sDone} + 5)
# Search of all jpg/jpeg/png in $INPUT
# We remove images from $OUTPUT if $OUTPUT is a subdirectory of $INPUT
IMAGES=$(find $INPUT -regextype posix-extended -regex '.*\.(jpg|jpeg|png)' | grep -v $OUTPUT)
if [ "$QUIET" == "0" ]; then
echo --- Optimizing $INPUT ---
echo
fi
for CURRENT_IMAGE in $IMAGES; do
filename=$(basename $CURRENT_IMAGE)
if [ "$QUIET" == "0" ]; then
printf '%s ' "$filename"
printf '%*.*s' 0 $((linelength - ${#filename} - ${#sDone} )) "$pad"
fi
INPUTABS=$(readlink -f $INPUT)
# If we want to retain the directory path.
if [ "$RETAINPATH" == "1" ]; then
# Create a replica of the absolute path in the output directory.
abspath=$(readlink -f $CURRENT_IMAGE)
absdirname=$(dirname $abspath)
trimmeddir=${absdirname#$INPUTABS}
mkdir -p $OUTPUT$trimmeddir
# Optimize the image.
optimize_image $CURRENT_IMAGE $OUTPUT/$trimmeddir/$filename
else
# Optimize the image.
optimize_image $CURRENT_IMAGE $OUTPUT/$filename
fi
if [ "$QUIET" == "0" ]; then
printf '%s\n' "$sDone"
fi
done
# we restore the saved IFS
IFS=$SAVEIFS
if [ "$NOSTATS" == "0" -a "$QUIET" == "0" ]; then
echo
echo "Input: " $(human_readable_filesize $max_input_size)
echo "Output: " $(human_readable_filesize $max_output_size)
space_saved=$(expr $max_input_size - $max_output_size)
echo "Space save: " $(human_readable_filesize $space_saved)
fi
}
human_readable_filesize()
{
echo -n $1 | awk 'function human(x) {
s=" b Kb Mb Gb Tb"
while (x>=1024 && length(s)>1)
{x/=1024; s=substr(s,4)}
s=substr(s,1,4)
xf=(s==" b ")?"%5d ":"%.2f"
return sprintf( xf"%s", x, s)
}
{gsub(/^[0-9]+/, human($1)); print}'
}
SHORTOPTS="h,i:,o:,q,s,r"
LONGOPTS="help,input:,output:,quiet,no-stats,retain-path"
ARGS=$(getopt -s bash --options $SHORTOPTS --longoptions $LONGOPTS --name $PROGNAME -- "$@")
eval set -- "$ARGS"
while true; do
case $1 in
-h|--help)
usage
exit 0
;;
-i|--input)
shift
INPUT=$1
;;
-o|--output)
shift
OUTPUT=$1
;;
-q|--quiet)
QUIET='1'
;;
-s|--no-stats)
NOSTATS='1'
;;
-r|--retain-path)
RETAINPATH='1'
;;
--)
shift
break
;;
*)
shift
break
;;
esac
shift
done
if ! command_exists optipng ; then
echo "Please install optipng.";
exit;
fi
# if ! command_exists pngcrush ; then
# echo "Please install pngcrush.";
# exit;
# fi
if ! command_exists jpegtran ; then
echo "Please install jpegtran.";
exit;
fi
main
@LiamKarlMitchell
Copy link
Author

LiamKarlMitchell commented Jan 19, 2017

Changes:
Checks if programs are installed.
clobber is not an option for optipng on ubuntu anymore? Removed.
Can retain directory structure when writing files into output with the -r argument.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment