/dev/trouble
Eric Roller's Development Blog

Bash Script to Scale AppIcons

- Posted in iOS by

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:

  1. The workflow document is not easily edited, at least not on a slow machine like mine;

  2. 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.

[Update 2019-10-23: I am no longer using this; I have switched to a bash script solution.]

For iOS development, it is necessary to provide a set of app icons of different sizes, all the way from a high-resolution icon for the AppStore to a tiny icon that will be used in Spotlight search results. The trouble is, how to create the icons, again, and again,...

Well, here's how...

Starting off with a 1024 x 1024 pixels source image (in PNG format), one would have to scale it multiple times in an image editing tool, to export it into all the sizes. But can't this be automated with AppleScript?

Well, yes, but it gets better: Use Automator !

I have set up this Automator workflow to create all icon images. It works like this:

  • Launch the workflow in Automator and Run it.
  • You will be prompted to select the 1024x1024 PNG source image.
  • You will be prompted to select a destination folder.
  • Wait...

When the workflow is finished, you will find these files in the output folder:

  • iTunesArtwork@2x (1024x1024)
  • iTunesArtwork (512x512)
  • Icon-1024.png (1024x1024)
  • Icon-512.png (512x512)
  • Icon-60@3x.png (180x180)
  • Icon-76@2x.png (152x152)
  • Icon-72@2x.png (144x144)
  • Icon-60@2x.png (120x120)
  • Icon@2x.png (114x114)
  • Icon-Small-50@2x.png (100x100)
  • Icon-40@2x.png (80x80)
  • Icon-Small@2x.png (58x58)
  • Icon-76.png (76x76)
  • Icon-72.png (72x72)
  • Icon-60.png (60x60)
  • Icon.png (57x57)
  • Icon-Small-50.png (50x50)
  • Icon-40.png (40x40)
  • Icon-Small.png (29x29)

But wait, there's more!

Are you missing an icon size? Just edit the workflow to fit your needs.