iPhone アプリのアイコンはデバイスや解像度の種類に合わせて、多くのサイズの画像を登録する必要があります。2019年の執筆現在、19種類もの画像ファイルを必要とします。
$ ls -1 PlaceN-20@2x.png PlaceN-20@3x.png PlaceN-29.png PlaceN-29@2x.png PlaceN-29@3x.png PlaceN-40@2x.png PlaceN-40@3x.png PlaceN-60@2x.png PlaceN-60@3x.png PlaceN-Small-20.png PlaceN-Small-20@2x.png PlaceN-Small-29.png PlaceN-Small-29@2x.png PlaceN-Small-40.png PlaceN-Small-40@2x.png PlaceN-76.png PlaceN-76@2x.png PlaceN-83.5@2x.png PlaceN-1024.jpg
ここで、PlaceN
はアプリのプロダクト名と思ってください、その次、ハイフンに続く文字列がサイズ、及び、アットマークに続く解像度に伴う倍率、そして、拡張子となっています。一つの JPEG 形式を除き他は PNG 形式です。JPEG 形式は AppStore 用アイコンで、サイズが特別大きいので非可逆圧縮形式が推奨されています。用途が異なるだけで実質的にサイズが等しい画像ファイルがいくつもありますが、ここでは同じ画像を自動的に生成するものとします。適宜、手作業で別の図柄を用意してもよろしいでしょう。
ここで、おすすめの元画像ファイル形式を決めます。それは SVG 形式です。スケーラブルベクターグラフィックス (SVG: Scalable Vector Graphics) の名前の通り、拡大縮小しても画質が劣化しませんので、今後の解像度の増加に対応が容易です。
手っ取り早くオンラインで画像を作成したいという方にいくつかフリーのオンライン SVG エディタを紹介します。他にも探せば色々ありますので、自分が使いやすいものを選べばよいでしょう。
Inkscape を macOS にインストールするには、2019年の執筆現在、1.0beta2 版の dmg ファイルをダウンロードするか、MacPorts もしくは Homebrew 経由でインストールするか、などです。
ところで、MacPorts と Homebrew の両方をインストールしている人が稀に見受けられますが「混ぜるな危険」であることを知らない人が多いようです。これは Homebrew に非があって、ビルドに用いる configure スクリプトは /usr/local
に依存するように作られているわけですから、そのままの Homebrew が存在すると MacPorts 他が Homebrew に徐々に依存し始めてしまい、提供者が意図しないビルドや障害が生じ得ます。そこで、Homebrew を /usr/local
ではない場所「/Users/Homebrew
」にインストールするためのシェルスクリプトを以下に示しますので、Homebrew を使う人は参考にしてください。
#!/bin/ksh prefix="${prefix:-/Users/Homebrew}" (cd "$(dirname "$prefix")" && sudo mkdir "$(basename "$prefix")" && sudo chown ${LOGNAME}:staff "$(basename "$prefix")" && curl -L https://github.com/Homebrew/brew/tarball/master | tar xz --strip 1 -C "$(basename "$prefix")" && sudo chown -R "${LOGNAME}:staff" "$(basename "$prefix")" && (cd "$(basename "$prefix")" && sudo mkdir -p etc include lib opt sbin share var/homebrew/linked Cellar && sudo chown -R "${LOGNAME}:staff" etc include lib opt sbin share var Cellar ) ) && "$prefix"/bin/brew doctor echo $ sudo xcode-select --install echo $ "$prefix"/bin/brew tap homebrew/cask echo $ "$prefix"/bin/brew update
echo
で表示されたコマンドは手動で実行しておいてください。
Homebrew Cask は App を /Applications
へ Homebrew 経由でインストールするための拡張です。MacPorts や Homebrew の使い方、Inkscape の使い方は他に譲ります。
さて、肝心のアイコン画像の作成に掛かります。非可逆圧縮の JPEG 形式は論外として、PNG 形式でもよいのですが、前提として 1024x1024 ピクセルの画像をアイコン画像として、SVG 形式で用意してください。
重要な注意事項としては、1024x1024 ギリギリまで描かずに、少なくとも1ドット余白を残すようにすることです。なぜかと言うと、画像の縮小時にアンチエイリアスを用いて美麗に見えるようにするのですが、縁のピクセルにはアンチエイリアスを上手く効かすことが出来ないからです。
SVG のレンダリングを何に任せれば最も高性能かを考えます。普通に考えれば Inkscape 本体に PNG 形式で出力をさせればよいと考えがちですが、実はフォントがらみであまり性能がよろしくない場合が多々あります。例えば、最新の Unicode 規格に対応していないなどです。これでは SVG の表現力のすべてを発揮できません。
SVG のレンダリングに最も適しているのは「ブラウザ」です。しかし、自動化したいわけですからブラウザを「いつものように」使うわけではなくヘッドレスモードでコマンドラインで使用します。ここでは Firefox と Google Chrome を前提にして進めます。以下「$*
」はベースネームであるプロダクト名を指しています。
Chrome の場合、以下のように SVG から PNG が生成できます。
$ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --lang=ja --headless --window-size=1024,1024 --screenshot="$*-1024.png" "$*.svg"
ここで Chrome では、なぜか絵文字が表示されないというフォント処理機構上の問題があります。無視できるならこれで良いのですが(2022/09/10追記) 一部のグリフが化けてしまうというフォント処理機構上の問題が多少あります。念の為、同様の処理を Firefox でも出来るようにしましょう (但し、一筋縄では行かないのでした)。
$ /Applications/Firefox.app/Contents/MacOS/firefox --headless --profile .profile --window-size 1024,1024 --screenshot "$*-1024.png" "$*.svg"
しかしこんな簡単なことが Firefox では不可能なのです。ローカルファイル "$*.svg"
を受理してくれません (http://〜
なら受理されますが、それだとウェブサーバ上にファイルを置かざるを得ず、非常に面倒です)。では URL なら受理してくれるかと、絶対パスで以下のようにしてみます。
$ /Applications/Firefox.app/Contents/MacOS/firefox --headless --profile .profile --window-size 1024,1024 --screenshot "$*-1024.png" "file://$PWD/$*.svg"
ここで環境変数 PWD
にはカレントディレクトリのパスが入っています。これでも受理してくれません。苦肉の策で、データ URL を用います。
$ /Applications/Firefox.app/Contents/MacOS/firefox --headless --profile .profile --window-size 1024,1024 --screenshot "$*-1024.png" "data:image/svg+xml;base64,$(base64 -b 0 "$*.svg")"
base64(1)
コマンドでデータ URL のデータをソースファイルから生成しています。これでめでたく、Firefox でも SVG のレンダリングが可能となりました。本当にこれを見つけるのに苦労しましたが、将来的にはこうした問題は解決されると思います。
かつて WebKit ベースのヘッドレスブラウザ PhantomJS がありましたが、開発が凍結されました。とは言え、2019年の執筆現在、試してみても十分に使用することが出来ています。また、Firefox を利用する SlimerJS がありますが、古い Firefox 56.0.2 を必要とし、少々品質が劣るようです。昨今は Selenium WebDriver などを使って柔軟かつ堅牢に自動化するのが主流のようですが、ここではいささか大げさになるのでブラウザ本来のヘッドレスモードを紹介しました。
さて、これで十分な解像度の PNG 画像が得られたので、そこから画像を縮小して各種アイコンファイルを生成しましょう。幸い、macOS には標準で sips(1)
という画像処理コマンドがありますので、それを利用します。一例だけ示します。
$ sips -Z 180 "$*-1024.png" --out "$*-60@3x.png"
さて、ここまでコマンドラインでの処理方法を説明していますが、結論から言うと、配布物の make-icons-*.zip
の makefile
にて自動化されているので、それをそのまま使えば事足ります。
$ make $ make backup $ make cleanこれで
by_firefox
にすべてのアイコンセットが生成されます。Chrome の方が調子が良いなら
$ make headless_browser=chrome all backup clean
とすれば by_chrome
にすべてアイコンセットが生成されます。以下の例のように、2019年の執筆現在、Chrome では絵文字が表示されません。
プロジェクト毎で Assets の AppIcon に生成されたアイコンファイルをすべて選んでドラッグ&ドロップして下さい。すると、いくつかは警告が出て枠に入れてくれませんが、手動で一つずつ警告で枠外のアイコンを適切に配置すれば登録完了です。
make-icons-*.zip
— makefile, *.svg, index.html
同梱の zip ファイル、両 iOS, macOS App 対応版、背景透過対応版make-icons-20220911.zip
— makefile, *.svg, index.html
同梱の zip ファイル、両 iOS, macOS App 対応版make-icons-20191212.zip
— makefile, *.svg, index.html
同梱の zip ファイル本文中の外部リンクを参考にして下さい。
makefile
配布物に入っている、このアイコンセットを SVG ファイルから生成するための GNU make 用の makefile
を解説付きで紹介します。(2022/09/10追記) macOS 非対応版のままですが、解説が煩雑になるのでそのままにしておきます。
# # makefile - create icons of various sizes # # Copyright (C) 2019 Taiji Yamada <taiji@aihara.co.jp> # # usage: # # $ make clean all backup # $ make headless_browser=chrome clean all backup # SVGS=\ # 変数 SVGS の定義−ソースファイル群 PlaceN.svg \ eMojiCalc.svg \ SUFS=\ # 変数 SUFS の定義−生成されるターゲットファイル名に付加されるサフィックス群 -20@2x.png \ -20@3x.png \ -29.png \ -29@2x.png \ -29@3x.png \ -40@2x.png \ -40@3x.png \ -60@2x.png \ -60@3x.png \ -Small-20.png \ -Small-20@2x.png \ -Small-29.png \ -Small-29@2x.png \ -Small-40.png \ -Small-40@2x.png \ -76.png \ -76@2x.png \ -83.5@2x.png \ -1024.jpg \ IMGS=\ # 変数 IMGS の定義−生成されるターゲットファイル群、foreach 関数により PlaceN-20@2x.png PlaceN-20@3x.png ... eMojiCalc-20@2x.png eMojiCalc-20@3x.png ... と変数展開される。 $(foreach svg, $(SVGS),$(foreach suf,$(SUFS),$(svg:%.svg=%$(suf)))) \ all:: $(IMGS) # 最初に現れるターゲット行が規定のターゲット:変数 IMGS を展開したもの #headless_browser=chrome # 条件分岐のための変数 headless_browser の定義 headless_browser=firefox # これらのどちらかを選ぶ ifeq ($(headless_browser),chrome) chrome="$(shell find /Applications -maxdepth 2 -name 'Google Chrome.app' -print -quit)/Contents/MacOS/Google Chrome" chrome_headless_flags=--lang=ja --headless --window-size=1024,1024 %-1024.png: %.svg # ターゲットファイル名のパターン:ソースファイル名のパターンーコロンを挟んで左が「$@」右が「$<」 $(chrome) $(chrome_headless_flags) --screenshot="$@" "$<" # 行頭がタブ:ターゲットを生成するためのシェルのコマンドを記述 # # これは以下のように変数展開されて実行される # # "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --lang=ja --headless --window-size=1024,1024 --screenshot="$*-1024.png" "$*.svg" # endif ifeq ($(headless_browser),firefox) firefox="$(shell find /Applications -maxdepth 2 -name Firefox.app -print -quit)/Contents/MacOS/firefox" firefox_headless_flags=--headless --profile .profile --window-size 1024,1024 %-1024.png: %.svg $(firefox) $(firefox_headless_flags) --screenshot "$@" "data:image/svg+xml;base64,$$(base64 -b 0 "$<")" # 行頭がタブ:ターゲットを生成するためのシェルのコマンドを記述 # # これは以下のように変数展開されて実行される(タブ行でシェルの「$」を使いたいとき「$$」とすること。さもなくばすべての「$」は makefile の変数展開である) # # /Applications/Firefox.app/Contents/MacOS/firefox --headless --profile .profile --window-size 1024,1024 --screenshot "$*-1024.png" "data:image/svg+xml;base64,$(base64 -b 0 "$*.svg")" # endif %-20.png: %-1024.png # ターゲットファイル名のパターン:ソースファイル名のパターン—コロンを挟んで左が「$@」右が「$<」 sips -Z 20 "$<" --out "$@" # アンチエイリアスで美麗に縮小するために macOS 純正の sips コマンドを利用 %-20@2x.png: %-1024.png sips -Z 40 "$<" --out "$@" %-20@3x.png: %-1024.png sips -Z 60 "$<" --out "$@" %-29.png: %-1024.png sips -Z 29 "$<" --out "$@" %-29@2x.png: %-1024.png sips -Z 58 "$<" --out "$@" %-29@3x.png: %-1024.png sips -Z 87 "$<" --out "$@" %-40.png: %-1024.png sips -Z 40 "$<" --out "$@" %-40@2x.png: %-1024.png sips -Z 80 "$<" --out "$@" %-40@3x.png: %-1024.png sips -Z 120 "$<" --out "$@" %-60@2x.png: %-1024.png sips -Z 120 "$<" --out "$@" %-60@3x.png: %-1024.png sips -Z 180 "$<" --out "$@" %-76.png: %-1024.png sips -Z 76 "$<" --out "$@" %-76@2x.png: %-1024.png sips -Z 152 "$<" --out "$@" %-83.5@2x.png: %-1024.png sips -Z 167 "$<" --out "$@" %-1024.jpg: %-1024.png sips -s format jpeg "$<" --out "$@" # 画像のファイル形式を変換するために macOS 純正の sips コマンドを利用 %-Small-20.png: %-20.png cp -p "$<" "$@" # 既に生成されているものと同一なのでコピーで生成 %-Small-20@2x.png: %-20@2x.png cp -p "$<" "$@" %-Small-29.png: %-29.png cp -p "$<" "$@" %-Small-29@2x.png: %-29@2x.png cp -p "$<" "$@" %-Small-40.png: %-40.png cp -p "$<" "$@" %-Small-40@2x.png: %-40@2x.png cp -p "$<" "$@" clean: # 生成されたターゲットファイル群をやり直すために全て削除するための PHONY ターゲット rm -f $(IMGS) *-1024.png backup: # 生成されたターゲットファイル群をバックアップしておくための PHONY ターゲット [ -d by_$(headless_browser)/for_ios ] || mkdir by_$(headless_browser)/for_ios cp -p $(IMGS) by_$(headless_browser)//for_ios/
ちなみに、%-20.png
はターゲットに含まれませんが、%-Small-20.png
がターゲットに含まれ、それが %-20.png
に依存しているので途中でしっかりと生成されます。しかし、あくまで %-20.png
は中間ファイルとなるので、のちに消されます。こうした依存関係に応じて上手く一連の処理を行ってくれるのが make システムなのです。