The Old Automator Flow
In a previous post, I described an Automator workflow to rescale iOS app icons. While that has worked well, it had potential for improvement:
The workflow document is not easily edited, at least not on a slow machine like mine;
When saved, the workflow document contains a preview image which blows up the file to about 1 GB. The preview image can be removed, but it adds another manual hack that is required.
Because of these shortfalls, I became increasingly reluctant to use it and found myself resizing images manually again.
Welcome to sips
I don't know how long it has been there, but it turns out macOS contains a command-line utility to convert images: sips
(scriptable image processing system). You can check if it is installed on your machine using:
$ which sips
/usr/bin/sips
or
$ sips -h
sips - scriptable image processing system.
This tool is used to query or modify raster image files and ColorSync ICC profiles.
Its functionality can also be used through the "Image Events" AppleScript suite.
Usages:
sips [image-functions] imagefile ...
sips [profile-functions] profile ...
[...]
Using sips
With some tips from this post, I have now set up the following script, saved in a file like ~/bin/resizeAppIcons
, (i.e. in a directory listed in your $path
variable):
#!/bin/sh
help=0
errs=0
pngquant=/Applications/ImageAlpha.app/Contents/MacOS/pngquant
colours=256
args=$(getopt h: *) # do not use "$@" to work with 'set' below.
if [ $? != 0 ]; then ((help++)); fi
set -- $args
for i ; do
case "$i" in
-h)
((help++))
shift;;
--)
shift; break;;
esac
done
if [ $help -gt 0 ]; then
echo "USAGE: $(basename $0) [-h] [pngFiles...]"
exit 2
fi
if [ ! -x $pngquant ]; then
echo "Warning: ImageAlpha.app is not installed"
fi
for img in $* ; do
echo "$img"
# Get the current image size: ( width height )
size=( $(sips -g pixelWidth -g pixelHeight "$img" | grep -o '[0-9]*$') )
# We expect 1024 x 1024.
if [[ ${size[0]} -ne ${size[1]} || ${size[0]} -ne 1024 ]]; then
echo "Error: Image size should be 1024 x 1024 (not ${size[0]} x ${size[1]})."
((errs++))
fi
# Split the file path: path/to/filename.png
dirn=$(dirname "$img") # path/to
base=$(basename "${img%.*}") # filename
extn=${img##*.}; # png
if [[ $extn != "png" ]]; then
echo "Error: Expected image format is PNG (not $extn)."
((errs++))
fi
if (( $errs )); then
echo "Too many errors; giving up"
exit 1
fi
# Using all the known image sizes:
for width in 16 18 19 32 36 38 40 48 55 58 60 64 80 87 88 100 120 128 152 167 172 180 196 216 256 512 1024 ; do
outfile="$dirn/$base-$width.$extn"
# Do not overwrite existing files
if [[ -f "$outfile" ]]; then continue; fi
echo "--> $outfile"
# Copy or resize the image
if [ $width -eq 1024 ]; then
cp "$img" "$outfile"
else
sips -Z $width "$img" --out "$outfile" $gt; /dev/null
fi
# Use exec in ImageAlpha to reduce colours and size.
if [[ -x $pngquant ]]; then
$pngquant -f $colours -o "$outfile" "$outfile"
fi
done
done
exit 0
Feel free to adjust the for width in ...
line to use the image sizes that you need.
Usage
The script requires a 1024 x 1024 pixel PNG image as input. It creates the scaled images in the same directory:
$ resizeAppIcons ./work/export/AppIcon.png
./work/export/AppIcon.png
--> ./work/export/AppIcon-16.png
[...]
--> ./work/export/AppIcon-512.png
--> ./work/export/AppIcon-1024.png
Image Alpha
Finally, I can recommend the use of ImageAlpha, which will optimize your images and reduce the colours. Once installed in /Applications, the script will pick it up.
For my simple icons, I can get away with just 256 colours. If your icons are more complex, adjust the $colour
variable as needed.