Skip to content

Instantly share code, notes, and snippets.

@avioli
Last active August 27, 2020 08:29
Show Gist options
  • Save avioli/3416de488c96cad8a2d31ce4b72718a8 to your computer and use it in GitHub Desktop.
Save avioli/3416de488c96cad8a2d31ce4b72718a8 to your computer and use it in GitHub Desktop.
A simple bash script to generate iOS icons
#!/bin/bash
# Requirements
# - bc - for some math
# - convert - from ImageMagick (or any alternative that provides `convert` util with -resize param)
# - optipng - to optimize the output from convert
# - jq - to read Contents.json if no GEN_SIZES
# Usage:
# ------
#
# generate-icons.sh input.png
#
# Will generate:
# ./AppIcon.appiconset/Icon-App-20x20@2x.png
# ./AppIcon.appiconset/Icon-App-20x20@3x.png
# ./AppIcon.appiconset/Icon-App-29x29@1x.png
# ./AppIcon.appiconset/Icon-App-29x29@2x.png
# ./AppIcon.appiconset/Icon-App-29x29@3x.png
# ./AppIcon.appiconset/Icon-App-40x40@2x.png
# ./AppIcon.appiconset/Icon-App-40x40@3x.png
# ./AppIcon.appiconset/Icon-App-60x60@2x.png
# ./AppIcon.appiconset/Icon-App-60x60@4x.png
# ./AppIcon.appiconset/Icon-App-1024x1024@1x.png
#
# ###
#
# GEN_SIZES=512:1024 generate-icons.sh input.png .
#
# Will generate:
# ./Icon-App-512x512@1x.png
# ./Icon-App-1024x1024@1x.png
#
# Env variables:
# --------------
#
# ICONSET_DIR=AppIcon.appiconset
# PREFIX=Icon-App-
# GEN_SIZES=20@2,3:29@1,2,3:40@2,3:60@2,3:1024
#
# Generated sizes format: SIDE[@SCALE[,SCALE]...][:SIDE]...
# -----------------------
#
# 20:30:40 = 20x20@1x 30x30@1x 40x40@1x
# 20@1:30@2:40@3 = 20x20@1x 30x30@2x 40x40@3x
# 20@1,2:83.5@1,2,3 = 20x20@1x 20x20@2x 83.5x83.5@1x 83.5x83.5@2x 83.5x83.5@3x
#
# If there's no GEN_SIZES env var but a file ./AppIcon.appiconset/Contents.json
# then it will be read to use the filenames, sizes and scales from it.
#
# If a filename is missing in the json (aka null) it will be generated from the
# param.
IMAGE="$1"
ICONSET_DIR="${2:-AppIcon.appiconset}"
PREFIX="${PREFIX:-Icon-App-}"
FILENAMES=""
SIZES=""
SCALES=""
if [[ -z "$GEN_SIZES" ]]; then
if [[ -f "$ICONSET_DIR/Contents.json" ]]; then
FILENAMES=$(cat "$ICONSET_DIR/Contents.json" | jq -r ".images[].filename")
SIZES=$(cat "$ICONSET_DIR/Contents.json" | jq -r ".images[].size")
SCALES=$(cat "$ICONSET_DIR/Contents.json" | jq -r ".images[].scale")
else
GEN_SIZES="20@2,3:29@1,2,3:40@2,3:60@2,3:1024"
fi
fi
if [[ -n "$GEN_SIZES" ]]; then
for size in $(echo "$GEN_SIZES" | tr ":" "\n"); do
side=$(echo "$size" | cut -d "@" -f 1)
scales=$(echo "$size" | cut -d "@" -s -f 2)
scales=${scales:-1}
for scale in $(echo "$scales" | tr "," "\n"); do
FILENAMES="$FILENAMES${PREFIX}${side}x${side}@${scale}x.png:"
SIZES="$SIZES${side}x${side}:"
SCALES="$SCALES${scale}x:"
done
done
FILENAMES=$(echo "${FILENAMES%?}" | tr ":" "\n")
SIZES=$(echo "${SIZES%?}" | tr ":" "\n")
SCALES=$(echo "${SCALES%?}" | tr ":" "\n")
fi
FILENAMES=($(echo "$FILENAMES"))
SIZES=($(echo "$SIZES"))
SCALES=($(echo "$SCALES"))
for i in $(seq 1 ${#FILENAMES[@]}); do
filename="${FILENAMES[$i-1]}"
size=$(echo "${SIZES[$i-1]}" | cut -d 'x' -f 1)
scale="${SCALES[$i-1]%?}"
if [[ "$filename" == "null" ]]; then
filename="${PREFIX}${size}x${size}@${scale}x.png"
fi
echo "$filename"
scaled_size=$(echo "($scale * $size) / 1" | bc)
convert "$IMAGE" -resize "${scaled_size}x${scaled_size}" "${ICONSET_DIR}/${filename}"
optipng -quiet "${ICONSET_DIR}/${filename}"
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment