MacOSXシェルスクリプトだけでiOSアプリ用アイコン全サイズを作成する(iOS9, iPad Pro対応)

##追記
- 2015/12/26 :   
  512x512でアイコンを生成したとき、そのままスクリプトを抜けてしまっていた不具合を修正。また、ドキュメントの方の情報ではなく、Xcode上の表記からスクリプト含めてまとめ直してみました。
- 2015/10/24 ：    
 iOS9、iPad Proの解像度に対応しました。また、分かりやすいように出力するファイル名の規則を変えてみました。
- 2015/04/05 ：
ご指摘があり、180サイズが正しくリサイズされていなかった箇所を修正しました。
- 2015/03/18 ：
iPhone6 Plus相当（@3x）を追加しました。

>※ちなみに、Androidもついでにまとめて出力したい、という方は以下の記事を参照ください。
>__MacOSXのシェルスクリプトだけで、iOS, Android両アプリアイコンの全サイズを生成する__
>http://qiita.com/hibara/items/c25054f336a95d58f591

# 1024x1024が全デバイスで必須になった。

iPhone 6 Plusや、iPad Proの登場で、さらにアイコンの解像度がカオス化しました。
さらに、iPhone6が出たときにiTunes用のアートワークとして使う1024x1024だけを「必須」としていましたが、今回からは**全デバイス**で「必須」となったようです。

このスクリプトでは、1024x1024がなくとも、512x512があれば動作するようになっていますが、512x512だけですと、単純に２倍、無理やり拡大して1024x1024を用意することになります。やはり可能なら、icon_1024x1024.pngを用意しておいた方が、各アイコンの仕上がりもキレイになります。

僕の経験上、一つのファイルからすべてをリサイズすると、特に小さくなったとき、キレイにならないんですよね。Windowsのアイコン仕様では、16x16まであるのですが、ここまで小さいと、ドット単位での修正は必須です。

なので、iOSアプリでも、理想は各サイズ毎に、多少の手直しは必要かな、と考えており、すでにあるファイルは処理せずスキップするようにしています。もしスクリプトで、再度一括で作り直したいときは、各サイズアイコンをいったん全削除してから行ってみてください。


# ドキュメントとXcode上でつくるアイコンのアセット表記が異なる

そしてようやくスクリプトを書き始めるのですが、ふとドキュメントの表記と、Xcode上の表記がが異なっていて戸惑う。。。

公式のAppleドキュメントは以下にあります。↓ 
https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html

よく見れば、カラム「Spotlight search results icon (recommended)」にあるiPadのサイズが、実際のXcode上でつくるアイコンアセットの表記と異なります。

![AppIconList.png](https://qiita-image-store.s3.amazonaws.com/0/30945/bbf2aed6-0b77-5ab9-516c-a3e2f5798a10.png)


# そこで自分でも整理するため、Xcodeの方を見ながら表にまとめ直した

|使用箇所|大きさ |倍率 |サイズ |ファイル名 |優先度 |デバイス１ |デバイス２ |
|--------------------------------------------------------|--------|------|-----------|--------------------|--------|--------------------------------------|-----------------------------|
| iPhone Spotlight - iOS 5,6　/ iPhone Settings  iOS 5-9 | 29pt | @1x | 29x29 | icon-small.png |  |  |  |
|  |  | @2x | 58x58 | icon-small@2x.png | 推奨 | iPhone 6s,iPhone 6, andiPhone 5(@2x) | iPhone 4s(@2x) |
|  |  | @3x | 87x87 | icon-small@3x.png | 推奨 | iPhone 6sPlus andiPhone 6Plus (@3x) |  |
| iPhone Spotlight iOS 7-9 | 40pt | @2x | 80x80 | icon-40@2x.png | 推奨 | iPhone 5(@2x) | iPhone 4s(@2x) |
|  |  | @3x | 120x120 | icon-40@3x.png | 推奨 | iPhone 6s,iPhone 6(@2x) |  |
| iPhone App iOS 5,6 | 57pt | @1x | 57x57 | icon.png |  |  |  |
|  |  | @2x | 114x114 | icon@2x.png |  |  |  |
| iPhone App iOS 7-9 | 60pt | @2x | 120x120 | icon-60@2x.png | **必須** | iPhone 6s,iPhone 6, andiPhone 5(@2x) | iPhone 4s(@2x) |
|  |  | @3x | 180x180 | icon-60@3x.png | **必須** | iPhone 6sPlus andiPhone 6Plus (@3x) | Spotlight search results icon |
| iPad Settings iOS 5-9 | 29pt | @1x | 29x29 | icon-small.png | 推奨 | iPad 2 andiPad mini(@1x) |  |
|  |  | @2x | 58x58 | icon-small@2x.png | 推奨 | iPad andiPad mini(@2x) | iPad Pro(@2x) |
| iPad Spotlight iOS 7-9 | 40pt | @1x | 40x40 | icon-40.png | 推奨 | iPad 2 andiPad mini(@1x) ※1 |  |
|  |  | @2x | 80x80 | icon-40@2x.png | 推奨 | iPad andiPad mini(@2x) ※2 | iPad Pro(@2x) ※3 |
| iPad Spotlight iOS 5,6 | 50pt | @1x | 50x50 | icon-50.png |  |  |  |
|  |  | @2x | 100x100 | icon-50@2x.png |  |  |  |
| iPad App iOS 5,6 | 72pt | @1x | 72x72 | icon-72.png |  |  |  |
|  |  | @2x | 144x144 | icon-72@2x.png |  |  |  |
| iPad App iOS 7-9 | 76pt | @1x | 76x76 | icon-76.png | **必須** | iPad 2 andiPad mini(@1x) |  |
|  |  | @2x | 152x152 | icon-76@2x.png | **必須** | iPad andiPad mini(@2x) |  |
| iPad Pro App iOS 9 | 83.5pt | @2x | 167x167 | icon-83.5@2x.png | **必須** | iPad Pro(@2x) |  |
| Unassigned | 60pt |  | 60x60 | icon_60x60.png |  |  |  |
| App icon for the App Store | 1024pt |  | 1024x1024 | icon_1024x1024.png | **必須** | 全デバイス |  |

- ※1. Spotlight アイコンサイズは、ドキュメントでは「120x120」となっており、iPhone 6s, iPhone 6, iPhone 5(@2x)と同等。    
- ※2 , ※3：Spotlight アイコンサイズは、ドキュメントでは「180x180」となっており、iPhone 6s Plus, iPhone 6 Plus (@3x)と同等。							

# どういったサイズのアイコンを用意するか

けっきょく公式ドキュメントではなく、実際に作業するXcode上の表記を参照することにしました。

揃え出したらキリがありませんが、基本的には「必須」項目にあるアイコンを生成すると良いでしょう。

スクリプトでは一応、全アイコンサイズを出力するようになっています。コメントアウトでどこで使用するアイコンかは書き込んでありますので、必要に応じて書き換えてください。


# シェルスクリプトの「sips」コマンドを使う

とはいえ、これだけの量を全部手動でやるにも限界があります。

そこで調べてみると、MacOSXの標準コマンドだけで出来るということが判明。

ならば、と、一種類のサイズのPNGファイルから、リサイズし、Xcode用に必要なすべてのサイズに変換して、ファイルとして出力するスクリプトを書いてみました。

MacOSXではデフォルトで、「sips」という画像処理のコマンドが用意されています。
sipsとは、scriptable image processing system の略だそうです。１へぇ。
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/sips.1.html

ちなみに、使う前に、その書いたスクリプトファイルに実行権限を与えておくことを忘れずに。

```sh
$ chmod a+x /Users/mhibara/Desktop/create_ios_icons.command
```

ってな感じで。

なお、以下のソースファイルを含む、サンプルアイコンはGitHubに上げてあるので、ご自由にお試しください。
![octcat.png](https://qiita-image-store.s3.amazonaws.com/0/30945/a0dc5ea9-c9b8-dfcd-8a30-2a1c8a1c58e5.png) https://github.com/hibara/create-ios-all-icons-shellscript

```sh
#!/bin/sh
#このシェルスクリプトを実行した場所をカレントディレクトリにする（お約束）
cd `dirname $0`

# 出力ディレクトリの生成
outdir="ios"
mkdir -p $outdir

#----------------------------------------------------------------------
# iTunes Artwork アイコン
#----------------------------------------------------------------------

# iPhone6, iPhone6 Plus登場以降、全デバイスで1024x1024が必須となりました。↓
# https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/IconMatrix.html
# ですので、このスクリプトでは最低でも、512x512サイズのアイコン画像がないと処理を終了するように修正しました。

# App icon for the App Store (すべてのアプリで必須)
if [ -e "icon_1024x1024.png" ]; then
	if [ -e "icon_512x512.png" ]; then
		echo "icon_512x512.png はすでに存在しています。処理をスキップします。"
		BASE_FILE="icon_1024x1024.png"
	else
		sips -Z 512 icon_1024x1024.png --out icon_512x512.png
		BASE_FILE="icon_1024x1024.png"
	fi
fi

if [ -e "icon_512x512.png" ]; then
	if [ -e "icon_1024x1024.png" ]; then
		echo "icon_1024x1024.png はすでに存在しています。処理をスキップします。"
	else
		sips -Z 1024 icon_1024x1024.png --out icon_512x512.png
		BASE_FILE="icon_512x512.png"
	fi
else
	echo "iTunes Artworkに設定できる適当なサイズが見つかりません。\niPhone6, iPhone6 Plus登場以降から、1024x1024が必須となりました。"
	exit
fi

#----------------------------------------------------------------------
# アプリアイコン（ファイル名）
#----------------------------------------------------------------------

echo "BASE_ICON: "
echo ${BASE_FILE}

# iPhone Spotlight - iOS 5,6　推奨
#        Settings - iOS 5-9　推奨
if [ -e "${outdir}/icon-small.png" ]; then
	echo "icon-small.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 29 ${BASE_FILE} --out ${outdir}/icon-small.png
fi

# iPhone 6s,iPhone 6, and iPhone 5(@2x)　推奨
# iPhone 4s(@2x)　推奨
if [ -e "${outdir}/icon-small@2x.png" ]; then
	echo "icon-small@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 58 ${BASE_FILE} --out ${outdir}/icon-small@2x.png
fi

# iPhone 6s Plus and iPhone 6 Plus (@3x)　推奨
if [ -e "${outdir}/icon-small@3x.png" ]; then
	echo "icon-small@3x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 87 ${BASE_FILE} --out ${outdir}/icon-small@3x.png
fi

#----------------------------------------------------------------------
# iPhone Spotlight iOS 7-9

# iPhone 5(@2x)　推奨
# iPhone 4s(@2x)　推奨
if [ -e "${outdir}/icon-40@2x.png" ]; then
	echo "icon-40@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 80 ${BASE_FILE} --out ${outdir}/icon-40@2x.png
fi

# iPhone 6s, iPhone 6(@2x)　推奨
if [ -e "${outdir}/icon-40@3x.png" ]; then
	echo "icon-40@3x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 120 ${BASE_FILE} --out ${outdir}/icon-40@3x.png
fi

# iPhone App iOS 5,6
if [ -e "${outdir}/icon.png" ]; then
	echo "icon.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 57 ${BASE_FILE} --out ${outdir}/icon.png
fi

if [ -e "${outdir}/icon@2x.png" ]; then
	echo "icon@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 114 ${BASE_FILE} --out ${outdir}/icon@2x.png
fi

#----------------------------------------------------------------------
#iPhone App iOS 7-9

# iPhone 6s,iPhone 6, and iPhone 5(@2x)　必須
# iPhone 4s(@2x)　必須
if [ -e "${outdir}/icon-60@2x.png" ]; then
	echo "icon-60@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 120 ${BASE_FILE} --out ${outdir}/icon-60@2x.png
fi

# iPhone 6s Plus and iPhone 6 Plus (@3x)　必須
# iPhone 6s Plus and iPhone 6 Plus (@3x) Spotlight search results icon　推奨
if [ -e "${outdir}/icon-60@3x.png" ]; then
	echo "icon-60@3x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 180 ${BASE_FILE} --out ${outdir}/icon-60@3x.png
fi

#----------------------------------------------------------------------
# iPad Settings iOS 5-9

# iPad 2 and iPad mini(@1x)　推奨
if [ -e "${outdir}/icon-small.png" ]; then
	echo "icon-small.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 29 ${BASE_FILE} --out ${outdir}/icon-small.png
fi

# iPad and iPad mini(@2x)　推奨
# iPad Pro(@2x)　推奨
if [ -e "${outdir}/icon-small@2x.png" ]; then
	echo "icon-small@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 58 ${BASE_FILE} --out ${outdir}/icon-small@2x.png
fi

#----------------------------------------------------------------------
# iPad Spotlight iOS 7-9

# iPad 2 and iPad mini(@1x)　推奨　※ただしドキュメントでは120x120サイズとなっている。
if [ -e "${outdir}/icon-40.png" ]; then
	echo "icon-40.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 40 ${BASE_FILE} --out ${outdir}/icon-40.png
fi

# iPad and iPad mini(@2x)　推奨　※ただしドキュメントでは180x180サイズとなっている。
# iPad Pro(@2x)　推奨　※ただしドキュメントでは180x180サイズとなっている。
if [ -e "${outdir}/icon-40@2x.png" ]; then
	echo "icon-40@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 80 ${BASE_FILE} --out ${outdir}/icon-40@2x.png
fi

#----------------------------------------------------------------------
# iPad Spotlight iOS 5,6

if [ -e "${outdir}/icon-50.png" ]; then
	echo "icon-50.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 50 ${BASE_FILE} --out ${outdir}/icon-50.png
fi

if [ -e "${outdir}/icon-50@2x.png" ]; then
	echo "icon-50@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 100 ${BASE_FILE} --out ${outdir}/icon-50.png
fi

#----------------------------------------------------------------------
# iPad App iOS 5,6

if [ -e "${outdir}/icon-72.png" ]; then
	echo "icon-72.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 72 ${BASE_FILE} --out ${outdir}/icon-72.png
fi

if [ -e "${outdir}/icon-72@2x.png" ]; then
	echo "icon-72@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 144 ${BASE_FILE} --out ${outdir}/icon-72@2x.png
fi

#----------------------------------------------------------------------
# iPad App iOS 7-9

# iPad 2 and iPad mini(@1x)　必須
if [ -e "${outdir}/icon-76.png" ]; then
	echo "icon-76.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 76 ${BASE_FILE} --out ${outdir}/icon-76.png
fi

# iPad and iPad mini(@2x)　必須
if [ -e "${outdir}/icon-76@2x.png" ]; then
	echo "icon-76@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 152 ${BASE_FILE} --out ${outdir}/icon-76@2x.png
fi

#----------------------------------------------------------------------
# iPad Pro App iOS 9

# iPad Pro(@2x)　必須
if [ -e "${outdir}/icon-83.5@2x.png" ]; then
	echo "icon-83.5@2x.png はすでに存在しています。処理をスキップします。"
else
	sips -Z 167 ${BASE_FILE} --out ${outdir}/icon-83.5@2x.png
fi

```