I just updated the design on this website (finally!) and needed to make image sprites for the github/twitter/linkedin icons. I know there’s ways to create image sprite sets NodeJS and Gulp/Grunt, but what’s the fun in that!?

Instead, I used a shell script and Imagemagick to generate a 3x4 sprite set PNG from 3 source PNG images, plus the CSS background-position values required. Each source image has a color overlay applied four times to generate the four (technically only three right now) required image colors. Conveniently, Imagemagick has a +level-colors feature which works similarly to the “Color Overlay” adjustment layer in Photoshop. The details of the process are thoroughly documented in the script below.

Hopefully this can be of use for other purposes. Let me know in the comments!

#!/bin/bash

# Specify colors in an associative array.
# Key names used as CSS selectors.
declare -A COLORS
COLORS[header]="#1b7c4b"
COLORS[header:hover]="#75f6b4"
COLORS[footer]="#1d1e20"
COLORS[footer:hover]="#1b7c4b"

# Image pixel dimensions. All source images must be the same.
HEIGHT=32
WIDTH=32

SOURCE=images-source/icons
TEMP=/tmp
DEST=images

# X/Y image counts in sprite sheet.
X=0 # left/right
Y=0 # up/down

#List of files to be made into a montage sprite
MONTAGE_FILES=""

# Loop through all of the colors.
for color in "${!COLORS[@]}"; do
  # Loop through all of the files.
  for file in $SOURCE/*; do
    # Get just the filename /path/name.png -> name
    NAME=`basename $file .png`
    # Generate an output filename
    OUTFILE=$TEMP/$NAME-$color.png
    # Apply the color overlay
    convert $file +level-colors "${COLORS[$color]}" $OUTFILE
    # Print the CSS selector
    echo "a#${NAME}-${color} {"
    # Print the sprite background position value
    echo "  background-position: $(($X * -$WIDTH))px $(($Y * -$HEIGHT))px;"
    echo "}"
    # Add the new image to the list of created files
    MONTAGE_FILES="$MONTAGE_FILES $OUTFILE"
    X=$(($X + 1))
  done
  Y=$(($Y + 1))
  X=0
done

echo
MONTAGE_OUT=$TEMP/montage.png
echo "Doing the montage..."
montage -background transparent -tile ${X}x${Y} -geometry ${HEIGHT}x${WIDTH} \
$MONTAGE_FILES $MONTAGE_OUT
echo "Running pngcrush..."
pngcrush -q -brute $TEMP/montage.png $DEST/icons-sprite.png
# Clean up
rm $MONTAGE_OUT $MONTAGE_FILES

echo "Done!"

This is the actual output as used in the SASS/CSS on this website.

$ ./make-icon-sprite.sh
a#github-bottom:hover {
  background-position: 0px 0px;
}
a#linkedin-bottom:hover {
  background-position: -32px 0px;
}
a#twitter-bottom:hover {
  background-position: -64px 0px;
}
a#github-bottom {
  background-position: 0px -32px;
}
a#linkedin-bottom {
  background-position: -32px -32px;
}
a#twitter-bottom {
  background-position: -64px -32px;
}
a#github-top:hover {
  background-position: 0px -64px;
}
a#linkedin-top:hover {
  background-position: -32px -64px;
}
a#twitter-top:hover {
  background-position: -64px -64px;
}
a#github-top {
  background-position: 0px -96px;
}
a#linkedin-top {
  background-position: -32px -96px;
}
a#twitter-top {
  background-position: -64px -96px;
}

Doing the montage...
Running pngcrush...
Done!
```s