Photoshop Scripting Tips

実際にスクリプトを組んでみたところで覚えた知識、色々出てきた癖やバグのような動作の対策など


Photoshop CS以降

複数のダイアログを扱う場合のフォーカス操作
スクロールバーの初期位置設定
PhotoshopCSのUnitValue

Photoshop 7以降

レイヤーの領域
レイヤーセットを統合する際の注意点
カレントフォルダの設定
OSを調べる
スクリプトエンジンのバージョンを調べる
WindowsXPでの日本語対応
文字化け対策(WindowsXPでの日本語対応)
文字化け対策(WindowsXP/2000での日本語対応・その2)
フォント名の取得

■複数のダイアログを扱う場合のフォーカス操作

ダイアログ(1)から別のダイアログ(2)を開き、ダイアログ(2)を閉じて元のダイアログ(1)に戻る、などの操作を行うとき、フォーカスの移動が行われますが、それに対応する内部の値が正しく更新されません。ダイアログにはactiveというプロパティがありますが、この値が、実際の状態と異なります。このため明示的に値を操作する必要があります。

dialog1.active = false;
dialog2.show();
dialog1.active = true;

元のダイアログ(1)を別のダイアログ(2)を表示する前にactive=falseに設定し、戻ってきたときにactive=trueを設定します。

戻ってきたときのみの操作では内部的にはtrueの状態でtrueを再指定することになり、変化が無いため実際のフォーカスが正しく移動しません。フォーカスを正しく反映させるためには一旦falseに指定した後、trueに戻す、という操作が必要になります。

また、alert、prompt、openDialog等、Photoshopで用意されているダイアログへ移動する際は、enabledも同様に操作する必要があります。

dialog.active = false;
dialog.enabled = false;
alert("Test");
dialog.enabled = true;
dialog.active = true;

これを行わない場合、スクリプト実行中であるにもかかわらず、Photoshop本体のGUI操作が行えるようになる等、奇妙な動作が発生します。

更新: 2005.3.29 / 対象: CS以降

■スクロールバーの初期位置設定

GUIでスクロールバーを作成する際、サムの初期位置を設定できません。マニュアルでは初期値valueを作成時に設定できるようになっているのですが、サムの初期位置はvalueに関係なく0の位置になってしまいます。このため実質的にvalue=0以外を作成時に指定しても正しく動作しません。

初期位置を設定するためには、minvalueとmaxvalueからそれぞれ初期値valueを引いてやることで擬似的に実現します。値を使用する際は逆に初期値valueを足すことで数値を元に戻します。valueの部分は0で作成します。

dlg.scbar = dlg.add('scrollbar',[16,16,320,36], 0, minvalue-value, maxvalue-value);

スライダーの初期値も同様に0以外設定できません。ただしこちらは後でvalueを設定しなおすことで初期位置が正しく設定できます。

dlg.sld = dlg.add('slider',[16,16,320,36], 0, minvalue, maxvalue);
dlg.sld.value = val;
更新: 2005.3.29 / 対象: CS以降

■PhotoshopCSのUnitValue

CSで単位値(UnitValue)の扱いが7から変更になっており、このため7で作成したスクリプトが正しく動作しない場合があります。

7のスクリプトではUnitValueもNumberとして扱われていましたが、CSではUnitValueオブジェクトに変更になっているようです。このため、座標指定、移動などの引数に数値を渡しても正しく動作しません。preferences.rulerUnitsの設定に関わらずこの場合は Number×解像度÷72ピクセル として解釈されます。

正しく動作させるためには設定した単位文字列を付加する必要があります(' px'や' mm'等)。しかしこの場合は引数が文字列になり、7では正しく動作しなくなります。

この問題は下記関数の処理を行うことで修正できます。

function Cast(number){
  return number + activeDocument.width - activeDocument.width;
}

activeDocument.width に関しては設定された単位での単位値が戻ってくるため、これらの数値と加減算を行うことで必要な単位に明示的に変換することが出来ます。数値を指定する部分を、Cast(number)とすることで設定した単位値になります。

更新: 2004.12.24 / 対象: CS以降

■レイヤーの領域

ArtLayer.bounds でレイヤーのピクセルが存在する領域を取得できます。

left = activeDocument.activeLayer.bounds[0];
top =  activeDocument.activeLayer.bounds[1];
right =  activeDocument.activeLayer.bounds[2];
bottom =  activeDocument.activeLayer.bounds[3];

LayerSet.bounds で同様にレイヤーセットのピクセルが存在する領域を取得できます。

更新: 2004.12.24 / 対象: 7以降

■レイヤーセットを統合する際の注意点

スクリプトでレイヤーセットを統合する際、アクティブレイヤーが対象のレイヤーセット以外になっていると、アクティブレイヤーが統合前の状態に関わらず必ず可視状態になります。

GUI操作の場合は統合対象がアクティブレイヤーのため問題は発生しないのですが、スクリプトではアクティブレイヤー以外を統合できるので注意する必要があります。

更新: 2004.12.24 / 対象: 7以降

■カレントフォルダの設定

Folder.current で、カレントフォルダを設定できます。

Folder.current = pathname;

カレントフォルダは画像やスクリプトを開くダイアログを使用すると最後に開いた場所に移動します。このため、スクリプトを参照(Browse)から開いた場合はスクリプトのフォルダがカレントになりますが、アクションやショートカットキーからスクリプトを起動した場合、カレントがスクリプトのフォルダではない場合が発生します。

外部ファイルを使用している場合は絶対パスでファイルを指定しておくなど、注意する必要があります。

更新: 2004.12.24 / 対象: 7以降

■OSを調べる

スクリプトを実行している環境のOSの種類は次のコードで得ることが出来ます。

var str = $.os;

これを利用することで、OSによって処理を変えるスクリプトを作成することが出来ます。

更新: 2004.12.24 / 対象: 7以降

■スクリプトエンジンのバージョンを調べる

スクリプトを実行しているエンジンのバージョンは次のコードで得ることが出来ます。

var str = $.version;

これを利用することで、フォトショップのバージョンによって処理を変えるスクリプトを作成することが出来ます。

更新: 2004.12.24 / 対象: 7以降

■WindowsXPでの日本語対応

document や File、Folderオブジェクトで2バイト文字を含むパスを取得する場合に path.toString() を使用すると文字化けが発生します。この問題は path.fsName.toString() を使用することで解決できます。

また、document.fullName を取得する場合も同様に document.fullName.fsName.toString() を使用すると文字化けが発生しません。

ただし、OSによって表記形式が変わってきますので文字列操作を行っている場合は注意してください。あえてfsNameを使用しない場合は下記の文字化け対策などを試してみてください。

更新: 2004.12.24 / 対象: 7以降

■文字化け対策(WindowsXPでの日本語対応)

※先にWindowsXPでの日本語対応をお読みください

XPではフォルダ名に日本語が含まれていると文字化けすることがあります。対策として下記置換を行うと修正できます。ただし確実かどうかは不明です。2000で文字化けが発生しない場合、この処理を追加するとエラーになる場合がありますので、環境によって使い分けてください。

str = escape(str);
str = str.replace(/%25/g,"\%");

パターン名やフォント名等も日本語は通らないようです。ただ、レイヤー名や外部テキストファイルは正しく処理されますのでシステム、アプリケーションが持っている部分でなければ大丈夫のようです。

更新: 2004.12.24 / 対象: 7以降

■文字化け対策(WindowsXP/2000での日本語対応・その2)

※先にWindowsXPでの日本語対応をお読みください

取得したファイルパスに含まれる日本語が文字化けする場合、下記処理を行うことで修正できます。

var tmpFile = new File("name.tmp");
tmpFile.open("w");
tmpFile.encoding = "BINARY";
tmpFile.writeln(unescape(str));<
tmpFile.close();

tmpFile.open("r");
tmpFile.encoding = "UTF-8";
var str = tmpFile.readln();
tmpFile.close();

内容は単純で、文字列をバイナリモードでファイルに書き出し、それをUTF-8エンコードとして読み込むことで、文字化けを修正します。

document.path.toString()で得られる文字列に日本語が含まれる場合、UTF-8エンコードになっていますが、これをうまくデコード出来ていないのが問題のようです。しかし、ファイルの入出力では様々なエンコードがサポートされているので、それを利用することで簡単にデコードすることが出来ます。

更新: 2004.12.24 / 対象: 7以降

■フォント名の取得

スクリプトでテキストレイヤーを作成し、フォントを設定する場合、日本語フォント名ではうまく設定されません。そのため英語フォント名を知る必要があります。

ScriptListenerプラグインを入れた状態でPhotoshopを起動し、新規画像を開いて名前を知りたいフォントを設定し、適当な文字列を打ち込んでテキストレイヤーを作成します。

その後、ScriptingListenerJS.logを開くと作成したテキストレイヤーのコマンドが記述されています。項目が多いため、非常に大きい塊になりますが、この中から、"fontPostScriptName"を検索してください。その次の行に有るフォント名(この場合は"MS-PGothic")がスクリプトで使用できるフォント名です。

// =======================================================
var id15 = charIDToTypeID( "Mk  " );
    var desc3 = new ActionDescriptor();
    var id16 = charIDToTypeID( "null" );
        var ref1 = new ActionReference();
        var id17 = charIDToTypeID( "TxLr" );
        ref1.putClass( id17 );
    desc3.putReference( id16, ref1 );

〜途中省略〜

        var id51 = charIDToTypeID( "Txtt" );
            var list2 = new ActionList();
                var desc8 = new ActionDescriptor();
                var id52 = charIDToTypeID( "From" );
                desc8.putInteger( id52, 0 );
                var id53 = charIDToTypeID( "T   " );
                desc8.putInteger( id53, 9 );
                var id54 = charIDToTypeID( "TxtS" );
                var desc9 = new ActionDescriptor();
    var id55 = stringIDToTypeID( "fontPostScriptName" );
    desc9.putString( id55, "MS-PGothic" );
                    var id56 = charIDToTypeID( "FntN" );
                    desc9.putString( id56, "MS PGothic" );
                    var id57 = charIDToTypeID( "FntS" );
                    desc9.putString( id57, "Regular" );

〜途中省略〜

                var id157 = stringIDToTypeID( "paragraphStyle" );
                desc11.putObject( id115, id157, desc12 );
            var id158 = stringIDToTypeID( "paragraphStyleRange" );
            list3.putObject( id158, desc11 );
        desc4.putList( id112, list3 );
    var id159 = charIDToTypeID( "TxLr" );
    desc3.putObject( id18, id159, desc4 );
executeAction( id15, desc3, DialogModes.NO );
更新: 2004.12.24 / 対象: 7以降

戻る