Crush .png images at commit time with git hooks

If you are a little involved into writing web applications, you have to know Yahoo!’s YSlow and Google’s PageSpeed. These are two Firefox plugins to help you accelerate a web site.

One thing they will help you do is to reduce the size of all those png images to decrease bandwidth. Sure png images are lighter than gifs but still you can remove some fat out of them keeping quality constant. Take a look at Smush.it if you want to learn more.

There are tools that can do similar things on the desktop. Pngcrush is one of them. This is as simple as this:

pngcrush imageIn.png imageOut.png

or even better:

pngcrush -rem allb -brute -reduce imageIn.png imageOut.png

Now how can we automate that? If pngcrush was java-based, you could do it dynamically with a servlet filter or at build time using ant/maven. A more effective way to do it, is at commit time using git.

The idea is to crush each png image added to the project the first time it is committed or each time it is updated. Git can do that with a simple hook script that will be executed pre-commit.

#!/bin/sh
if ! which -s pngcrush
then
  echo "Please install pngcrush to reduce png images size before commit"
  exit 1;
fi
 
for file in `git diff --cached --name-only | grep ".png$"`
do
  echo "Crushing $file"
  pngcrush -rem allb -brute -reduce $file ${file%.png}.new | grep "filesize"
  mv -f ${file%.png}.new $file
done

Get this code on Gist.

Have fun!