Phostoshop Scriptingで自動化 - Tips篇

ChainZ(クリエイター)
いろいろやってます。

Photoshop(本記事でPSに略します)のスクリプトを書く時にあった問題とその解決方をこの記事でまとめてみました。PSのスクリプトが初めての方はまずこの記事を読んでもらえると分かりやすいかもしれないです:http://befool.co.jp/blog/chainzhang/photoshop-scripting-basic

パフォーマンス

カード自動化ツールを書いてた時に気になったのは、スクリプトでレイヤーを検索する動作が重いというとこです。例えば:

1
2
3
var doc = app.activeDocument;
var layer = doc.layers.getByName('myLayer');
layer.visible = false

上記のコードは「myLayer」という名前のレイヤーを探して非表示にするスクリプトです。一回ぐらいなら、パフォーマンスとか全く考慮しなくてもいいですが、これが数百レイヤーだと、PSがフリーズするぐらい重くなります。

キャッシュする

レイヤー検索重い理由は、レイヤー名はユニックではないので、単純にループで探してる可能性が高いです。なので、よく使うレイヤーをキャッシュしてあげればパフォーマンスがかなり向上します。これが関数を二つ用意すればオッケーです。

キャッシュといっても、単純に配列に保存することだけです。

1
2
3
4
5
6
7
8
9
10
11
var g_cached = {};

function setCache( key, value )
{
      g_cached[key] = value;
}

function getCache( key )
{
  return g_cached[key];
}

g_で始まるのはglobalという意味なんだけど、ここは個人の好き嫌いで変えても大丈夫です。ちなみに、グローバル変数はよくないという考えが普通ですが、小さなプラグインぐらいなら私は許します。

JSONデータ

JSONは幅広く使われているデータ形式です。JSONとJavaScriptはもっとも相性がよくて、PS自動化に使うデータの取り込むならJSON形式をおすすめします。

JSONの読み込みはライブラリが必要です。しかし、PSのスクリプトでは外部ソースを読む機能がないようです(たぶん)。一番乱暴な方法はライブラリを丸ごとスクリプトにコピーしますが、ここでもう一つちょっとトリッキーな方法を紹介します。それは、eval()を使うのです:

1
2
3
4
5
6
7
8
function loadJSON(file)
{
  var f = new File(file);
  file.open('r');
  var content = file.read();
  file.close();
  return eval(content);
}

これで、簡単なJSONデータは取り込めるようになります。もちろん、eval()を使うのはよくない!という方もいると思います、そいう場合は素直にJSONライブラリをコピペするのが一番いいかもしれないです。

ファイル選び

PSのスクリプトにはFile.openDialog()という便利な関数があります、これを利用すると、ファイル選びウィンドウが開かれて、ユーザーにファイルを選んでもらえます。簡単な使い方:

1
2
var src_file = File.openDialog ("ファイルを選んでください", null, false);
if (! src_file) return alert('ファイル選んでないようです!';

このスクリプトは特に問題はないですが、ユーザーがどんな形式なファイルでも選択できます。しかし、選べるファイル形式を絞りたいという時がありますよね、その時はFile.openDialogの第二引数を使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var src_file = File.openDialog ("ファイルを選んでください", JSON_ONLY, false);
if (! src_file) return alert('ファイル選んでないようです!';

function JSON_ONLY()
{
  // Mac OSの場合
  if ($.os.charAt(0) == 'M')
  {
         return function(f) 
          { 
              if ((new Folder(f.fullName)).getFiles("*").length > 0
                  || f.fullName.split('.').pop() == 'json') {
                  return true;
              }
              return false;
          }
  }
  // Windowsの場合
  return '*.json';
}

$.osが今使ってるOSを取得できます。Mac OSの場合はFile.openDialog()の第二引数がfunctionタイプになります。このfunctionの第一引数にFileオブジェクトが渡されます、このFileのオブジェクトで判定を行って、truefalseで選べるファイルを絞ります。

Windowsの場合は、*.jsonという文字列を返せば問題ないです。(.json拡張子のファイルという意味)

終わりに

PSのスクリプトはスコープ(PS)の制限で、できることは限られているが、真面目なコーディングより、ちょっとトリッキーな方法を考えてみたら、できることが多くなります。