読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

スクリプトで効率大アップ! Photoshop Scripting Guide

こんにちは、デザイナーの上松です。
今回は、デザインワークの要となるPhotoshopをスクリプトで自動化して、単純作業を効率化しよう!
ということで、スクリプト作成のスタートアップとなる記事を書いてみました。
思えば、いつも面倒な同じ作業を繰り返してるなあ…と思う方必見です。

【対象】
・面倒な繰り返し作業で飽き飽きしているデザイナ(多少のプログラム経験あり)
・ワークフロー改善を検討するプログラマ

【必要なもの】
・Adobe Photoshop
・Adobe ExtendScript Toolkit
・使い勝手の良いエディタ(Sublimeとか)

0. 何ができるの?

Photoshopで手軽な自動化の手段と言えばアクションです。
アクションだけでできることはアクションで済ますべきです。なぜなら、工数が圧倒的に少ないからです。
しかし、複雑なことはできず、直線的な処理しか行うことができません。
例えば、フォルダで区切ってデータを書き出したり、自動的にフォルダ分けをしたり、
任意のオブジェクトを綺麗に並べたり、任意のパーセンテージでガイドを作成するといったのものです。

これらはスクリプトを使うことで、解決できます。
アプリや書類の状態を取得・設定、計算、場合分け、繰り返しなどを行うことができるからです。

あなたのワークフローにうまくマッチすれば、あなたのストレスと作業時間を解消できるかもしれません!

1. スクリプトの作成と使い方

まずは簡単な、「Hello World」プログラムを作ってみましょう。
なお、Photoshopで使用できる言語は、WebでもおなじみのJavaScriptです。
おなじみの機能に加え、Photoshopで使用できるAPIが用意されています。

それでは、はじめてましょう。

アプリの立ち上げ

・Photoshopを立ち上げます
・ExtendScript Toolkitを立ち上げます

ExtendScript Toolkitは、コネクトしたAdobeアプリへスクリプトを送信し、即座に実行できるソフトです。
しかし、Macではエディタの性能があまり良くないため、書類の編集自体は別のエディタで作成することをお勧めします。

エディタで新規書類を作成します。

下記コードを入力してください

alert("Hello World!");  

1

これをコピーして、ExtendScript Toolkitに貼付けます。

ExtendScript ToolkitをPhotoshopにコネクトします。

画面左上のプルダウンメニューから、立ち上げているPhotoshopを選択するだけでOKです。

2

実行してみる

この状態で、再生ボタンを押してみましょう。

3

以下のようにアラートウィンドウが表示されたでしょうか?

4

表示されれば大成功です。
次に、保存したスクリプトをPhotoshopから呼び出してみます。

ファイルから実行してみる

・エディタから、適当なフォルダに保存します。

5

・Photoshopからスクリプトを開きます
 Photoshopのメニューの「ファイル」 > 「スクリプト」 > 「参照」をクリックし、
 先ほど保存したファイルを選択します。

6

こちらからでもアラートが表示されたでしょうか?

このようにして、開発中はExtendScript Toolkit経由で実行させると便利ですし、
作成が終わったスクリプトは、メニューから実行するのが便利です。(後者の方法は、スクリプトの実行までをアクションとして登録できます)

2. 文法

初学者の方は適宜「JavaScript 文法」と言った感じで、各自予習をしていただければと思います。
プログラミング経験者向けに、簡単なサンプルをメモしておきます。

/* 変数 */  
a = 10; //グローバル変数として定義されます  
var b = false; //ローカル変数になります。  
var s = "ABC"; //変数型は気にしなくてもOKです  
var f = function(x,a,b){ return x*x*a+b; }; //関数を入れることもできます。  
var ret = f(10,2,5); //関数として使うことができます  
  
/* 配列 */  
var arr = [1,2,3]; //配列です  
arr[0]; //"1" アクセスはCと同じ形です  
arr.push(4); //"[1,2,3,4]" いろいろなメソッドが使えます。pop, shift, unshift, join, contact, sliceなどなど  
  
/* オブジェクト */  
var obj = { //連想配列のようなものとして使えます  
    a : "あ",  
    i : "い",  
    u : "う",  
    num : 20, //入るものの種類が違っても大丈夫です  
    fn : function(x){ return x*2; } //関数だって入ります(配列でもできます)  
};  
obj["i"]; //"い"  
obj.u; //"う" 半角英数であれば、.でアクセスできます。  
obj.fn(20); //"40" 関数を呼び出すこともできます  
  
/* 条件分岐 */  
if( a < b ){ //よく見かける形のif文を使えます  
    alert("if");  
} elseif ( obj.num != 30 ){  
    alert("elseif")  
} else {  
    alert("else")  
}  
  
/* ループ */  
while( true ){ //よくあるwhile文です  
    if(a > 100){  
        break;//breakとcontinueを使います  
    }  
  
    a++;  
}  
  
for(var i=0; i<arr.length; i++){//よくあるfor文です  
    alert(arr[i]);//1,2,3の順にalertします  
}  
  
/* 関数 */  
//無名関数が先にでちゃいましたが、普通にこんな感じで書けます  
function pow2(x){  
    return x*x;  
}  
  
pow2(3);//"9"  
  
/* クラス */  
function MyClass(){//関数がそのままコンストラクタになります  
    this.a = 10;//メンバ変数を設定します  
    this.b = 20;//thisは、上の方に出ていた「オブジェクト」と同じような扱いができます  
}  
  
MyClass.prototype.func1 = function(){ //メンバ関数は、[クラス名].prototype.[メンバ関数名]に、  
    alert( this.a + this.b ); //無名関数を代入して実現します  
    //MyClass.prototypeは、MyClassというオブジェクトが共通で参照するオブジェクトです  
    //MyClass.prototype.constVar = 20;と定義すると、全MyClassインスタンスで共有できます  
}  
  
var myobj = new MyClass();//コンストラクタを呼び出してインスタンス化します  
myobj.a = 20;//メンバ変数はすべてpublic扱いです  
alert(myobj.func1());//"40"

3. サンプルプログラム - ドキュメントの名前とサイズを取得する

まずは、現在のドキュメントの情報を取得して表示してみましょう。
今回は簡単な関数として作ってみます。

ShowImageInfo();  
  
function ShowImageInfo(){  
    var str = "Info\n";  
  
    var doc = activeDocument;//アクティブドキュメントを取得  
    str += "タイトル\t: " + doc.name + "\n";  
    str += "Width\t: " + doc.width + "\n";  
    str += "Height\t: " + doc.height + "\n";  
  
    alert(str);  
}

これを既存のファイルに対して実行すると以下のように表示されます。

7

activeDocumentは、現在フォーカスされているファイルのDocumentオブジェクトを返します。
Documentオブジェクトには、「name」「width」「height」などのプロパティがあるため、「.」でアクセスして取得します。

4. サンプルプログラム - ドキュメントの中央を通る縦横のガイドを作成する

上記のデータを使用して、垂直・水平線を引いてみます。

CreateCenteredGuides();  
  
function CreateCenteredGuides(){  
  
    var doc = activeDocument;//アクティブドキュメントを取得  
  
    var v,h;  
    v = doc.width/2;  
    h = doc.height/2;  
    doc.guides.add(Direction.VERTICAL, v);  
    doc.guides.add(Direction.HORIZONTAL, h);  
}

8

うまくできました!
ガイドラインを引くためには、Guidesオブジェクトのadd()メソッドを使用します。
Direction.VERTICAL, DIRECTION.HORIZONTALは、定数です。

5. サンプルプログラム - レイヤー名を列挙する

では、最後にPhotoshopへアクセスするサンプルとして、レイヤー名を列挙するプログラムを作成してみます。

RaiseLayername();  
  
function RaiseLayername(){  
    var padString = " ";  
    var findLayer = function( layers, pad ){  
        var arr = [];  
  
        //レイヤー分だけループ  
        for(var i=0; i < layers.length; i++){  
            //レイヤーを取得  
            var item = layers[i];  
  
            //名前を取得  
            var name = layers[i].name;  
  
            //名前の頭に階層分だけのスペースを追加  
            var prefix = "";  
            for(var n=0; n<pad; n++){  
                prefix += padString;  
            }  
  
            //名前を追加  
            arr.push(prefix + item);  
  
            //フォルダだったら中身の捜索(再帰呼び出し)  
            if(item.typename == "LayerSet"){  
                found_item = findLayer( item.layers, pad+1 );  
                if(found_item){  
                    //子レイヤーがあれば、結合  
                    arr = arr.concat(found_item);  
                }  
            }  
        }  
  
        return arr;  
    }  
  
    //メインスクリプトはここから  
    var doc = activeDocument;//アクティブドキュメントを取得  
    var layers = findLayer( doc.layers, 0 );//レイヤー名を取得  
    alert("RaiseLayername\n"+layers.join("\n"));//一覧を表示  
}

こちらを実行した結果が以下になります。

9

Documentクラスのlayersプロパティに、ファイルのレイヤーが格納されており、以下階層構造になっています。
このサンプルではfindLayer関数を作り、再帰的にレイヤーを辿っていきます。

このスクリプトがすぐに役立つことはまずありませんが、このスクリプトに処理を挟むことで、
特定のレイヤーのON/OFFをしたり、いらない物を削除したりといろいろできそうな感じがしますね!
実際、このサンプルは稼働中のスクリプトの一部をいじったものです。

6. 作成の資料集

Photoshopでスクリプトを作る上で必要な資料はAdobeのサイト上に公開されています。
photoshop scripting guide」で検索してDeveloperサイト上にある「Photoshop [VERSION] JavaScript Reference」というpdfファイルをダウンロードしましょう。
また、前バージョンのドキュメントでもほとんど問題はありません。今回の作成に当たってはCS5のものを使用しました。

英語ではありますが、全クラスのプロパティ名やメソッド名、引数や、読み書きの可否などが網羅されていますので、困った時にはこのpdfファイルを検索すれば事足りると思います。

7. 最後に

スクリプト作成は、アクション作成に比べるとなかなか敷居の高い物です。
しかし、一度作り方を覚えて作ってしまえば、長く使える代物です。

弊社でもいくつかのスクリプトを作成していますが、一番ゲーム作りに貢献しているのは書き出しに特化したスクリプトでしょうか。
使用用途は多く、1つのpsdファイルから、複数言語分の素材を自動的に書き出したり、数十体のキャラクターの画像を一度に書き出す、1枚のpsdファイルから複数のテクスチャパスを書き出したり…などなど
スクリプトの力を借りれば、作業している裏で任意の名前を付けながら数百枚の画像を書き出すことだって可能です。

このように大幅な作業改善にもつながるスクリプト機能、ぜひぜひご活用ください!