Icon Set Maker
Expert guidance for creating complete icon sets across all major platforms.
Available Tools
macOS Native Tools
Tool Command Purpose
sips /usr/bin/sips
Resize, resample, convert between formats
iconutil /usr/bin/iconutil
Convert .iconset ↔ .icns
Homebrew Tools
Tool Install Purpose
ImageMagick brew install imagemagick
Multi-size ICO, advanced compositing
librsvg brew install librsvg
SVG → PNG conversion
optipng brew install optipng
PNG optimization
pngquant brew install pngquant
PNG size reduction
Platform Requirements
macOS (.icns)
Required sizes for App.iconset directory:
icon_16x16.png (16×16) icon_16x16@2x.png (32×32) icon_32x32.png (32×32) icon_32x32@2x.png (64×64) icon_128x128.png (128×128) icon_128x128@2x.png (256×256) icon_256x256.png (256×256) icon_256x256@2x.png (512×512) icon_512x512.png (512×512) icon_512x512@2x.png (1024×1024)
Windows (.ico)
Standard sizes to include:
16×16 - Small icon (taskbar, file lists) 24×24 - Explorer medium 32×32 - Desktop, Explorer 48×48 - Large icon view 64×64 - Extra large 128×128 - Jumbo (Vista+) 256×256 - High DPI displays (Vista+)
Linux (freedesktop.org)
Directory structure under /usr/share/icons/hicolor/ :
16x16/apps/appname.png 22x22/apps/appname.png 24x24/apps/appname.png 32x32/apps/appname.png 48x48/apps/appname.png 64x64/apps/appname.png 128x128/apps/appname.png 256x256/apps/appname.png 512x512/apps/appname.png scalable/apps/appname.svg (optional, preferred)
iOS App Icons
Required for App Store submission:
iPhone
Icon-60@2x.png (120×120) Icon-60@3x.png (180×180)
iPad
Icon-76.png (76×76) Icon-76@2x.png (152×152) Icon-83.5@2x.png (167×167)
App Store
Icon-1024.png (1024×1024) - No transparency!
Spotlight
Icon-40@2x.png (80×80) Icon-40@3x.png (120×120)
Settings
Icon-29@2x.png (58×58) Icon-29@3x.png (87×87)
Notification
Icon-20@2x.png (40×40) Icon-20@3x.png (60×60)
Android App Icons
Density buckets in res/mipmap-*/ :
mipmap-mdpi/ic_launcher.png (48×48) mipmap-hdpi/ic_launcher.png (72×72) mipmap-xhdpi/ic_launcher.png (96×96) mipmap-xxhdpi/ic_launcher.png (144×144) mipmap-xxxhdpi/ic_launcher.png (192×192)
Adaptive icons (Android 8+)
mipmap-anydpi-v26/ic_launcher.xml mipmap-/ic_launcher_foreground.png (108dp with 72dp safe zone) mipmap-/ic_launcher_background.png
Web Favicons
favicon.ico (16×16, 32×32 multi-size) favicon-16x16.png (16×16) favicon-32x32.png (32×32) apple-touch-icon.png (180×180) icon-192.png (192×192) - PWA icon-512.png (512×512) - PWA safari-pinned-tab.svg (monochrome SVG) mstile-150x150.png (150×150) - Windows tiles
Conversion Workflows
From SVG Source (Recommended)
SVG is the ideal source - infinite scalability:
#!/bin/bash
Generate all sizes from SVG source
SOURCE_SVG="icon.svg" OUTPUT_DIR="./icons" mkdir -p "$OUTPUT_DIR"
Define all needed sizes
SIZES=(16 20 24 29 32 40 48 58 60 64 72 76 80 87 96 120 128 144 152 167 180 192 256 512 1024)
for SIZE in "${SIZES[@]}"; do rsvg-convert -w "$SIZE" -h "$SIZE" "$SOURCE_SVG" -o "$OUTPUT_DIR/icon-${SIZE}.png" echo "Generated: icon-${SIZE}.png" done
Using sips (macOS)
Resize a PNG
sips -z 512 512 source.png --out icon_512x512.png
Resize maintaining aspect ratio (fit within box)
sips --resampleHeightWidth 256 256 source.png --out icon_256.png
Convert format
sips -s format png source.jpg --out output.png sips -s format icns source.png --out output.icns
Batch resize
for SIZE in 16 32 64 128 256 512 1024; do sips -z $SIZE $SIZE source.png --out "icon_${SIZE}.png" done
Query image properties
sips -g pixelWidth -g pixelHeight -g format image.png
Create macOS .icns
#!/bin/bash
Create .icns from a 1024×1024 source PNG
SOURCE_PNG="icon-1024.png" ICONSET_DIR="AppIcon.iconset" OUTPUT_ICNS="AppIcon.icns"
Create iconset directory
mkdir -p "$ICONSET_DIR"
Generate all required sizes
sips -z 16 16 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_16x16.png" sips -z 32 32 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_16x16@2x.png" sips -z 32 32 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_32x32.png" sips -z 64 64 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_32x32@2x.png" sips -z 128 128 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_128x128.png" sips -z 256 256 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_128x128@2x.png" sips -z 256 256 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_256x256.png" sips -z 512 512 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_256x256@2x.png" sips -z 512 512 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_512x512.png" sips -z 1024 1024 "$SOURCE_PNG" --out "${ICONSET_DIR}/icon_512x512@2x.png"
Convert to icns
iconutil -c icns "$ICONSET_DIR" -o "$OUTPUT_ICNS"
echo "Created: $OUTPUT_ICNS"
Cleanup (optional)
rm -rf "$ICONSET_DIR"
Create Windows .ico
Using ImageMagick (recommended for multi-size ICO):
#!/bin/bash
Create .ico with multiple sizes
SOURCE_PNG="icon-1024.png" OUTPUT_ICO="app.ico"
Generate individual sizes
magick "$SOURCE_PNG" -resize 16x16 icon-16.png magick "$SOURCE_PNG" -resize 24x24 icon-24.png magick "$SOURCE_PNG" -resize 32x32 icon-32.png magick "$SOURCE_PNG" -resize 48x48 icon-48.png magick "$SOURCE_PNG" -resize 64x64 icon-64.png magick "$SOURCE_PNG" -resize 128x128 icon-128.png magick "$SOURCE_PNG" -resize 256x256 icon-256.png
Combine into multi-size ICO
magick icon-16.png icon-24.png icon-32.png icon-48.png
icon-64.png icon-128.png icon-256.png "$OUTPUT_ICO"
echo "Created: $OUTPUT_ICO"
Cleanup
rm icon-{16,24,32,48,64,128,256}.png
Alternative using sips + ImageMagick:
sips for resize, ImageMagick for ICO assembly
for SIZE in 16 24 32 48 64 128 256; do sips -z $SIZE $SIZE source.png --out "tmp_${SIZE}.png" done
magick tmp_.png app.ico rm tmp_.png
Create Web Favicon Package
#!/bin/bash
Complete web favicon package
SOURCE_PNG="icon-1024.png" OUTPUT_DIR="./favicons" mkdir -p "$OUTPUT_DIR"
Standard favicons
sips -z 16 16 "$SOURCE_PNG" --out "$OUTPUT_DIR/favicon-16x16.png" sips -z 32 32 "$SOURCE_PNG" --out "$OUTPUT_DIR/favicon-32x32.png"
Multi-size favicon.ico
magick "$OUTPUT_DIR/favicon-16x16.png" "$OUTPUT_DIR/favicon-32x32.png" "$OUTPUT_DIR/favicon.ico"
Apple Touch Icon (no transparency, add background if needed)
sips -z 180 180 "$SOURCE_PNG" --out "$OUTPUT_DIR/apple-touch-icon.png"
PWA icons
sips -z 192 192 "$SOURCE_PNG" --out "$OUTPUT_DIR/icon-192.png" sips -z 512 512 "$SOURCE_PNG" --out "$OUTPUT_DIR/icon-512.png"
Microsoft tile
sips -z 150 150 "$SOURCE_PNG" --out "$OUTPUT_DIR/mstile-150x150.png"
echo "Generated web favicon package in $OUTPUT_DIR/"
Create iOS App Icon Set
#!/bin/bash
iOS App Icon generation
SOURCE_PNG="icon-1024.png" OUTPUT_DIR="./AppIcon.appiconset" mkdir -p "$OUTPUT_DIR"
Generate all iOS sizes
declare -A IOS_SIZES=( ["Icon-20@2x.png"]=40 ["Icon-20@3x.png"]=60 ["Icon-29@2x.png"]=58 ["Icon-29@3x.png"]=87 ["Icon-40@2x.png"]=80 ["Icon-40@3x.png"]=120 ["Icon-60@2x.png"]=120 ["Icon-60@3x.png"]=180 ["Icon-76.png"]=76 ["Icon-76@2x.png"]=152 ["Icon-83.5@2x.png"]=167 ["Icon-1024.png"]=1024 )
for FILENAME in "${!IOS_SIZES[@]}"; do SIZE="${IOS_SIZES[$FILENAME]}" sips -z "$SIZE" "$SIZE" "$SOURCE_PNG" --out "$OUTPUT_DIR/$FILENAME" echo "Generated: $FILENAME (${SIZE}×${SIZE})" done
Generate Contents.json for Xcode
cat > "$OUTPUT_DIR/Contents.json" << 'EOF' { "images" : [ {"filename":"Icon-20@2x.png","idiom":"iphone","scale":"2x","size":"20x20"}, {"filename":"Icon-20@3x.png","idiom":"iphone","scale":"3x","size":"20x20"}, {"filename":"Icon-29@2x.png","idiom":"iphone","scale":"2x","size":"29x29"}, {"filename":"Icon-29@3x.png","idiom":"iphone","scale":"3x","size":"29x29"}, {"filename":"Icon-40@2x.png","idiom":"iphone","scale":"2x","size":"40x40"}, {"filename":"Icon-40@3x.png","idiom":"iphone","scale":"3x","size":"40x40"}, {"filename":"Icon-60@2x.png","idiom":"iphone","scale":"2x","size":"60x60"}, {"filename":"Icon-60@3x.png","idiom":"iphone","scale":"3x","size":"60x60"}, {"filename":"Icon-76.png","idiom":"ipad","scale":"1x","size":"76x76"}, {"filename":"Icon-76@2x.png","idiom":"ipad","scale":"2x","size":"76x76"}, {"filename":"Icon-83.5@2x.png","idiom":"ipad","scale":"2x","size":"83.5x83.5"}, {"filename":"Icon-1024.png","idiom":"ios-marketing","scale":"1x","size":"1024x1024"} ], "info" : {"author":"xcode","version":1} } EOF
echo "Created iOS App Icon set in $OUTPUT_DIR/"
Create Android Adaptive Icons
#!/bin/bash
Android adaptive icon generation
SOURCE_PNG="icon-1024.png" OUTPUT_DIR="./android"
Standard launcher icons
declare -A ANDROID_SIZES=( ["mipmap-mdpi"]=48 ["mipmap-hdpi"]=72 ["mipmap-xhdpi"]=96 ["mipmap-xxhdpi"]=144 ["mipmap-xxxhdpi"]=192 )
for DENSITY in "${!ANDROID_SIZES[@]}"; do SIZE="${ANDROID_SIZES[$DENSITY]}" mkdir -p "$OUTPUT_DIR/$DENSITY" sips -z "$SIZE" "$SIZE" "$SOURCE_PNG" --out "$OUTPUT_DIR/$DENSITY/ic_launcher.png" echo "Generated: $DENSITY/ic_launcher.png (${SIZE}×${SIZE})" done
For adaptive icons, also generate foreground/background
Foreground should be 108dp with content in center 72dp
ADAPTIVE_SIZES=( ["mipmap-mdpi"]=108 ["mipmap-hdpi"]=162 ["mipmap-xhdpi"]=216 ["mipmap-xxhdpi"]=324 ["mipmap-xxxhdpi"]=432 )
echo "" echo "For adaptive icons (Android 8+), create:" echo " - ic_launcher_foreground.png (108dp, content in center 72dp)" echo " - ic_launcher_background.png (solid color or pattern)" echo " - ic_launcher.xml referencing both"
Complete Multi-Platform Script
#!/bin/bash
Generate icons for ALL platforms from a single source
set -e
SOURCE="${1:-icon.svg}" OUTPUT_BASE="${2:-./icons}"
if [[ ! -f "$SOURCE" ]]; then echo "Usage: $0 <source-image> [output-directory]" echo "Source should be SVG (preferred) or 1024×1024+ PNG" exit 1 fi
echo "=== Multi-Platform Icon Generator ===" echo "Source: $SOURCE" echo "Output: $OUTPUT_BASE" echo ""
Detect source type
if [[ "$SOURCE" == *.svg ]]; then CONVERT_CMD="rsvg-convert" echo "Source type: SVG (using rsvg-convert)" else CONVERT_CMD="sips" echo "Source type: Raster (using sips)" fi
Function to generate PNG at size
generate_png() { local SIZE=$1 local OUTPUT=$2
if [[ "$CONVERT_CMD" == "rsvg-convert" ]]; then
rsvg-convert -w "$SIZE" -h "$SIZE" "$SOURCE" -o "$OUTPUT"
else
sips -z "$SIZE" "$SIZE" "$SOURCE" --out "$OUTPUT" >/dev/null
fi
}
=== macOS ===
echo "Generating macOS icons..." MACOS_DIR="$OUTPUT_BASE/macos/AppIcon.iconset" mkdir -p "$MACOS_DIR"
generate_png 16 "$MACOS_DIR/icon_16x16.png" generate_png 32 "$MACOS_DIR/icon_16x16@2x.png" generate_png 32 "$MACOS_DIR/icon_32x32.png" generate_png 64 "$MACOS_DIR/icon_32x32@2x.png" generate_png 128 "$MACOS_DIR/icon_128x128.png" generate_png 256 "$MACOS_DIR/icon_128x128@2x.png" generate_png 256 "$MACOS_DIR/icon_256x256.png" generate_png 512 "$MACOS_DIR/icon_256x256@2x.png" generate_png 512 "$MACOS_DIR/icon_512x512.png" generate_png 1024 "$MACOS_DIR/icon_512x512@2x.png"
iconutil -c icns "$MACOS_DIR" -o "$OUTPUT_BASE/macos/AppIcon.icns" echo " ✓ AppIcon.icns"
=== Windows ===
echo "Generating Windows icons..." WIN_DIR="$OUTPUT_BASE/windows" mkdir -p "$WIN_DIR"
for SIZE in 16 24 32 48 64 128 256; do generate_png "$SIZE" "$WIN_DIR/icon-${SIZE}.png" done
magick "$WIN_DIR/icon-16.png" "$WIN_DIR/icon-24.png" "$WIN_DIR/icon-32.png"
"$WIN_DIR/icon-48.png" "$WIN_DIR/icon-64.png" "$WIN_DIR/icon-128.png"
"$WIN_DIR/icon-256.png" "$WIN_DIR/app.ico"
echo " ✓ app.ico"
=== Web ===
echo "Generating web favicons..." WEB_DIR="$OUTPUT_BASE/web" mkdir -p "$WEB_DIR"
generate_png 16 "$WEB_DIR/favicon-16x16.png" generate_png 32 "$WEB_DIR/favicon-32x32.png" generate_png 180 "$WEB_DIR/apple-touch-icon.png" generate_png 192 "$WEB_DIR/icon-192.png" generate_png 512 "$WEB_DIR/icon-512.png" generate_png 150 "$WEB_DIR/mstile-150x150.png"
magick "$WEB_DIR/favicon-16x16.png" "$WEB_DIR/favicon-32x32.png" "$WEB_DIR/favicon.ico" echo " ✓ favicon package"
=== iOS ===
echo "Generating iOS icons..." IOS_DIR="$OUTPUT_BASE/ios/AppIcon.appiconset" mkdir -p "$IOS_DIR"
generate_png 40 "$IOS_DIR/Icon-20@2x.png" generate_png 60 "$IOS_DIR/Icon-20@3x.png" generate_png 58 "$IOS_DIR/Icon-29@2x.png" generate_png 87 "$IOS_DIR/Icon-29@3x.png" generate_png 80 "$IOS_DIR/Icon-40@2x.png" generate_png 120 "$IOS_DIR/Icon-40@3x.png" generate_png 120 "$IOS_DIR/Icon-60@2x.png" generate_png 180 "$IOS_DIR/Icon-60@3x.png" generate_png 76 "$IOS_DIR/Icon-76.png" generate_png 152 "$IOS_DIR/Icon-76@2x.png" generate_png 167 "$IOS_DIR/Icon-83.5@2x.png" generate_png 1024 "$IOS_DIR/Icon-1024.png" echo " ✓ iOS App Icon set"
=== Android ===
echo "Generating Android icons..." ANDROID_DIR="$OUTPUT_BASE/android"
for DENSITY_SIZE in "mdpi:48" "hdpi:72" "xhdpi:96" "xxhdpi:144" "xxxhdpi:192"; do DENSITY="${DENSITY_SIZE%%:}" SIZE="${DENSITY_SIZE##:}" mkdir -p "$ANDROID_DIR/mipmap-$DENSITY" generate_png "$SIZE" "$ANDROID_DIR/mipmap-$DENSITY/ic_launcher.png" done echo " ✓ Android mipmap icons"
=== Linux ===
echo "Generating Linux icons..." LINUX_DIR="$OUTPUT_BASE/linux/hicolor"
for SIZE in 16 22 24 32 48 64 128 256 512; do mkdir -p "$LINUX_DIR/${SIZE}x${SIZE}/apps" generate_png "$SIZE" "$LINUX_DIR/${SIZE}x${SIZE}/apps/app.png" done echo " ✓ Linux hicolor icons"
echo "" echo "=== Complete ===" echo "Icons generated in: $OUTPUT_BASE/" find "$OUTPUT_BASE" -name ".icns" -o -name ".ico" | sort
Quality Tips
Source Image Requirements
-
Minimum size: 1024×1024 pixels for raster, any size for SVG
-
Format: SVG preferred, PNG with transparency for raster
-
Color space: sRGB
-
Transparency: Supported except iOS App Store icon
Optimization
Optimize PNGs (lossless)
optipng -o7 *.png
Reduce PNG file size (lossy but visually identical)
pngquant --quality=80-100 --ext .png --force *.png
Verification
Check generated icon properties
sips -g pixelWidth -g pixelHeight -g format icon.png
Verify .icns contents
iconutil -c iconset AppIcon.icns -o verify.iconset ls -la verify.iconset/
Verify .ico contents
magick identify app.ico
Troubleshooting
Issue Solution
sips: unrecognized format Ensure source is valid PNG/JPEG
iconutil: invalid iconset Check all required sizes present with exact naming
ICO appears blurry Include 256×256 size for high-DPI displays
iOS icon rejected Ensure 1024×1024 has no transparency
Colors look wrong Convert to sRGB color space first
Checklist
Before distribution:
-
Source is 1024×1024+ or SVG
-
All platform-required sizes generated
-
No transparency in iOS App Store icon
-
Windows ICO includes 256×256 for high-DPI
-
PNGs optimized for file size
-
Verified icons render correctly at all sizes