Skip to content

Instantly share code, notes, and snippets.

@Munter
Created May 2, 2012 12:44
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Munter/2576308 to your computer and use it in GitHub Desktop.
Save Munter/2576308 to your computer and use it in GitHub Desktop.
Shell script to recursively optimize all image in the current directory. WARNING: THIS OVERWRITES YOUR ORIGINALS AND REMOVES METADATA!
#!/bin/sh
set -o errexit
PNGS=`find . -iname "*.png"`
JPGS=`find . -iname "*.jpg"`
TMP1="_TMP1.PNG"
TMP2="_TMP2.PNG"
echo "Optimizing PNG"
for PNG in ${PNGS}
do
BEFORE=`stat -c %s ${PNG}`
echo -n " ${PNG}: ${BEFORE} "
cp ${PNG} ${TMP1}
COLORS=`pngtopnm ${PNG} | ppmhist -noheader | wc -l`
if [ "$COLORS" -lt 2 ]; then
COLORS=2
fi
if [ "$COLORS" -lt 257 ]; then
cat ${PNG} | pngquant ${COLORS} > ${TMP1}
fi
pngcrush -q -l 9 -brute -rem alla ${TMP1} ${TMP2}
rm ${TMP1}
optipng -quiet -o7 -out ${TMP1} ${TMP2}
AFTER=`stat -c %s ${TMP1}`
if [ "$AFTER" -lt "$BEFORE" ]; then
mv ${TMP1} ${PNG}
echo "--> ${AFTER}"
else
echo "(Already optimal)"
fi
rm -f ${TMP1} ${TMP2}
done
echo "Optimizing JPG"
for JPG in ${JPGS}
do
BEFORE=`stat -c %s ${JPG}`
echo -n " ${JPG}: ${BEFORE} "
jpegtran -optimize -copy none ${JPG} > ${TMP1}
AFTER=`stat -c %s ${TMP1}`
if [ "$AFTER" -lt "$BEFORE" ]; then
mv ${TMP1} ${JPG}
echo "--> ${AFTER}"
else
echo "(Already optimal)"
fi
rm -f ${TMP1}
done
@Munter
Copy link
Author

Munter commented May 2, 2012

These are the same optimizations as implemented in Assetgraph-builder

assetgraph/assetgraph#49 (comment)

@Munter
Copy link
Author

Munter commented May 2, 2012

For those that don't read shell script fluidly (I know I don't), here is an explanation of what the script does.

It runs recursively through all directories under your current one and optimizes the pngs with the following tools:

pngquant in case the image has 256 or less colors. This converts the png to an 8bit png with a smaller palette, which makes each pixel be less bytes.
pngcrush for removing ancillary png chunks, like the tedious gamma chunk that always screws up browsers.
optipng for further efficiency in compressing the png file.

Then it overwrites your original pngs, so keep a backup, or even better, version control your files so you can see the difference.
Not that you should be able to see much difference other than on file size, since these optimizations are lossless.

I hope this helps you.

@Munter
Copy link
Author

Munter commented May 2, 2012

Just added jpeg optimization with jpetran, which is also lossless

@eggbean
Copy link

eggbean commented Feb 24, 2014

Cheers, but pngquant had a bad affect on my alpha channel png files. They ended up looking terrible. pngquant is apparently lossy.

@zopieux
Copy link

zopieux commented Mar 12, 2014

Please consider quoting every argument, especially with destructive commands like rm, so as to prevent space-in-file-name-related issues:

rm -f "$TMP1" "$TMP2"

Also, there are two mainstream extensions for JPEG files: jpg and jpeg.

@mjc
Copy link

mjc commented Oct 21, 2019

I made an updated version of this with significant changes (including multi-threading) here:
https://github.com/mjc/optimizeimages.sh

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