syghの新フラグメント置き場

プログラミングTipsやコード断片の保管場所です。お絵描きもときどき載せます。

Photoshopのスクリプトでテキストレイヤーを作成してラスター化

Photoshop含めAdobe製品ではAdobe ExtendScriptというのを使って作業を自動化できるので、コードでテキストレイヤーを作ってラスター化するというスクリプトを試しに書いてみました。ExtendScriptJavaScriptと互換性が高いらしいです。

var doc = app.activeDocument;
var layerObj = doc.artLayers;
const text = "hoge";
const x = 20;
const y = 20;
var newLayer = layerObj.add(); // 新規レイヤーを追加。
newLayer.kind = LayerKind.TEXT; // レイヤー種別をテキストレイヤーに設定。
newLayer.textItem.contents = text; // テキストレイヤーに文字列を設定。
newLayer.textItem.position = Array(x, y); // レイヤー位置を指定(配列)。フォントのベースラインが基準?
newLayer.textItem.font = "Consolas"; // フォント名。
newLayer.textItem.size = 14; // フォントサイズ。

// レイヤーをラスタライズ。
newLayer.rasterize(RasterizeType.TEXTCONTENTS);
// 画像を統合。
doc.flatten();

なんでこんなスクリプトを書こうと思ったかというと、ゲーム制作で使うSpriteFont画像(ラスター化したフォントが1文字ずつ並べてあり、アルファマップテクスチャとして使うグレースケール画像)を生成するのに、Photoshopレンダリングエンジンを使いたかったから。
WindowsでのテキストレンダリングAPIにはGDI/GDI+、それとDirectWrite/WPFがあって、これらのAPIを使って自動画像生成ツールとか作ることもできるんですが、どちらのレンダリングエンジンもフォントの描画結果がいまいちなので、クロスプラットフォームでOSに依存しない自前レンダリングエンジンを搭載しているPhotoshopを使いたかったわけです*1。またPhotoshopでは文字のアンチエイリアス種別もいくつか用意されていて、好みに応じて自由に選択することができます("なし"、"シャープ"、"鮮明"、"強く"、"滑らかに")。

1文字ごとにテキストレイヤーを作成していくこともできますが、ラスタライズと統合を繰り返しながらSpriteFont画像を作成していくほうが省メモリです。かなり昔のバージョン、Photoshop v5.5まではレイヤー数の上限が99(背景を含めると100)だったそうです。v6.0以降は上限8000とかいう話を見かけたことがありますが、正式仕様かどうかは不明です。

ちなみにtextItem.fontを指定する方法だと、すべての文字に対してフォントを一括指定することになるので注意。たとえばfontConsolasフォントを指定してcontentsに日本語文字列などを指定した場合に豆腐化します*2
もし1つのテキストレイヤーにおいて文字単位で個別にフォント指定する場合、もう少し複雑なスクリプトを書く必要がありそうです。IllustratorInDesignで文字単位の処理をするスクリプトはすぐ見つかるんですが……

なお、プログラマー的視点から言わせてもらうと、JavaScriptプログラミングに不慣れなデザイナーさんが書いて公開してるExtendScriptには、変数・定数宣言時のvarconstがないコードが散見されます。varconstなしで宣言するとグローバル変数になってしまい、特にfunctionを定義して再利用するときに意図しない誤動作(バグ)を引き起こすことがあるので注意しましょう。Lualocalもそうですね。

あとExtendScript ToolkitのエディタフォントはWindows版の場合Unicode対応のMSゴシックあたりに設定しときましょう。
ホントはConsolasとか使いたいんですが、ExtendScriptのエディタで使われてるのはEclipse同様GDIらしく、こいつのフォントリンクはUnicode文字に対してはうまく効かないことがあります……(MSゴシックも実際はUnicode完全対応かと言われると微妙ではあるんですが)
さっさとGDIを捨ててDirectWriteに対応してください><

*1:余談ですがComicStudioの縦書きはWindows GDIの縦書きフォントに依存しているらしく、GDIの縦書きにバグがあるWindows 8では正しく動作しません。8.1では改善されていますが、OSのAPIに依存するとバージョンアップ時にこういう弊害があります。ていうかComicStudioはつまりWin版とMac版で最終レンダリング結果が異なるってことでしょうか? それともプレビューのみ? 前者はいくらなんでもマズいんじゃ……CLIP STUDIO PAINTはそのあたりどうなんでしょうか?

*2:PhotoshopGUIを使って手動で日本語対応フォントから英文フォントに設定変更した場合、日本語部分には日本語対応フォントが設定されたままになります。MS Officeも似たような挙動をします。こういった操作をスクリプトでも簡単に実現できればいいのですが……