2017/10/18

Photoshop Script シェイプサイズ取得の際の誤差

シェイプのサイズを取得すると1px誤差が出る現象。
おそらくPhotoshopの仕様なのでしょうが、シェイプ以外のサイズと比べる場合やオブジェクトに対して処理する場合にシェイプだけサイズがずれるのが気持ち悪いのでなんとかならないのかという話。
そこで解決策としてシェイプを選択しているときだけサイズを-1してやるというもの。
しかしそれだとシェイプがにじんでいるときは見事にズレます。
シェイプを適当に書くと確実にズレますし作業時にずれることはママあります。

さらにその解決策がこちら。
function select_shape(active_shape_name){
    var actName_dammy = activeDocument.activeLayer.name;
    var desc8 = new ActionDescriptor();
        var ref4 = new ActionReference();
        ref4.putProperty( charIDToTypeID( "Chnl" ), charIDToTypeID( "fsel" ) );
    desc8.putReference( charIDToTypeID( "null" ), ref4 );
        var ref5 = new ActionReference();
        ref5.putEnumerated( charIDToTypeID( "Path" ), charIDToTypeID( "Path" ), stringIDToTypeID( "vectorMask" ) );
        ref5.putName( charIDToTypeID( "Lyr " ), actName_dammy);
    desc8.putReference( charIDToTypeID( "T   " ), ref5 );
    desc8.putInteger( charIDToTypeID( "Vrsn" ), 1 );
    desc8.putBoolean( stringIDToTypeID( "vectorMaskParams" ), true );
    executeAction( charIDToTypeID( "setd" ), desc8, DialogModes.NO );
    var rect_a = activeDocument.selection.bounds;
    activeDocument.selection.deselect();
    return rect_a
}
シェイプを選択しているとき、シェイプから選択範囲を作成して、その選択範囲のサイズを取得すると誤差を丸めてくれます。
if(layType == "LayerKind.SOLIDFILL")layer_bounds = select_shape(layer);
呼び出す際は塗りつぶしレイヤーかどうかの判断をする必要がありますので上記のようにするとなんとなくエラーは減ると思います。

オブジェクトのサイズに対して処理をする場合にPhotoshop上で表示されるサイズを使用したいときに便利です。

2017/10/03

Photoshop script ファイルパスをファイルシステム形式で取得する

Photoshopから外部アプリケーションを使用してバッチ処理したいときなどに各種ファイルパスをOSの形式で取得する方法。
var SELF = File($.fileName).parent.fsName;
スクリプト自身の格納パスを絶対パスで取得。
スクリプトと各種バッチ用アプリケーションを一緒に格納したりするときに実行用で格納先の絶対パスを取得できて便利。
通常「$.fileName」は自身のファイル名も含めて取得しますが「.parent」でディレクトリのみ取得できます。
しかしながらJSX用のパス形式はバッチで使用する分には不都合がありますので。
「.fsName」でファイルシステムに合わせてくれます。
var outputDir = Folder.selectDialog (["Plese select output directory"]).fsName;
フォルダ選択ダイアログで選択したフォルダの絶対パスを取得。
「.selectDialog()」でフォルダ選択ダイアログを表示し取得したパスをファイルシステム形式に合わせます。
バッチ処理時に保存先や作業先を指定する際に便利です。

2017/09/29

Photoshop script 小ネタ

まずはスクリプトを実行する上で悩ましいヒストリーの管理。
普通に処理すると自動化した操作分ヒストリーが増えてしまいます。
activeDocument.suspendHistory('ヒストリー名','function()');
上記とすることにより関数内の処理を1つのヒストリーにまとめておけます。
こうすることでアンドゥ1回で元に戻せるので非常に助かります。
処理を関数で用意しておけば簡単に導入できるのでおすすめです。

次にアンドゥ。
スクリプトリスナーで拾ってくるととてつもなく長い関数が返ってきます。
executeAction(charIDToTypeID( "undo" ),undefined,DialogModes.NO);
こう記述することが出来るようです。
1行になりました。エラー処理で終了したあとなどに書いておけば元に戻せていいですね。

更にスタイルのコピーとペースト。
function styleCopy() {
executeAction( charIDToTypeID( "CpFX" ), undefined, DialogModes.NO );
}

function stylePe() {
executeAction( charIDToTypeID( "PaFX" ), undefined, DialogModes.NO );
}
スクリプトリスナーは面倒なことこの上なしで。実はココまで短くなります。アンドゥと同じですね。
どうもこの手の処理はcharIDToTypeID( "hoge" )の部分を変更することで色々できそうですが、こういった情報はどこにあるのでしょうか?

特にヒストリーの統合に関してアドオンなどで配布する際には是非導入したいですね。

2017/09/28

Photoshop script テキストをメモ帳で開く

クリップボードへ送ってコピー処理をする方法は以前書きましたが
今回はそれを改変し直接メモ帳で開くというもの。
別にクリップボードに送っちゃってそれをメモ帳に貼り付ければ?ってことですが。微妙に面倒なので直接開くのもありかと思いまして。
var folderForTempFiles = Folder.temp.fsName;

var clipTxtFile =new File(folderForTempFiles + "/ClipBoard.txt"); 
clipTxtFile.open('w'); 
clipTxtFile.write(curLayer); 
clipTxtFile.close();

var clipBatFile =new File(folderForTempFiles + "/ClipBoard.bat"); 
clipBatFile.open('w'); 
clipBatFile.writeln("start notepad.exe \"" + folderForTempFiles + "\\ClipBoard.txt\"");
clipBatFile.close(); 
clipBatFile.execute();

という感じで行けます。テキスト情報は「curLayer」に入れてあげてください。
BAT処理をnotepad.exeにしてやるだけですが、微妙に表記が違うので迷いました。
あと通常の呼び出しではメモ帳を閉じるまでプロンプトが開きっぱなしになるので。

clipBatFile.writeln("start notepad.exe \"" + folderForTempFiles + "\\ClipBoard.txt\"");

の方法で呼び出します。頭に「start」が付いていますね。
通常では別のアプリケーションはBAT処理の一部として扱われそれが終了するまでBATが進まないのですが。
この方法だと「呼び出すだけ」という処理になるらしく、裏でBATが終わります。

2017/09/26

Photoshop script 「レイヤーセット内のオブジェクトをランダムに回転・縮小/拡大する」

紙吹雪や星・花吹雪のようなランダムに表示させたいデザインを作る場合に、オブジェクトをランダムに処理してくれるスクリプト。

var do_flag = false;
var obj_size = false;
var obj_rotate = false;

winObj = new Window("dialog","ランダーム",{ width: 180, height:120, x: 100, y: 100 });

winObj.cBoxsize = winObj.add("checkbox",{ width: 160, height: 20, x: 20, y: 20 }, "サイズ");
winObj.cBoxrotate = winObj.add("checkbox",{ width: 160, height: 20, x: 20, y: 45 }, "回転");

winObj.cBoxsize.value = true;
winObj.cBoxrotate.value = true;

winObj.okBtn = winObj.add("button",{ width: 60, height: 30, x: 20, y: 70 }, "OK", { name:"ok"});
winObj.cancelBtn = winObj.add("button",{ width: 60, height: 30, x: 90, y: 70}, "CANCEL", {name: "cancel"});

winObj.cancelBtn.onClick = function() {
 do_flag = false;
 // ダイアログを閉じる
 winObj.close();
}

winObj.okBtn.onClick = function() {
    if(winObj.cBoxsize.value) obj_size = true;
    if(winObj.cBoxrotate.value) obj_rotate = true;
    
 do_flag = true;
 winObj.close();
}

winObj.show();

/*---------------------main---------------------*/

try{
if(do_flag){

var resultLayers=new Array();

for (var ix=0;ix<app.activeDocument.activeLayer.layers.length;ix++){
    resultLayers.push(app.activeDocument.activeLayer.layers[ix])
}

var allselLinkLysLength = resultLayers.length;

for(i=0;i<allselLinkLysLength;i++){
    activeDocument.activeLayer = resultLayers[i];
    if(obj_rotate){activeDocument.activeLayer.rotate(Math.floor(Math.random() * 360));}
    if(obj_size){var rnd = Math.floor(Math.random() * 60)+70; activeDocument.activeLayer.resize(rnd,rnd);}
}
activeDocument.activeLayer = activeDocument.activeLayer.parent;

}

}catch(e){
alert ('グルーーーーープを選択してないかもよ?\n選択してもこれが出るのなら不具合だぞ。製作者に連絡だ! ','ランダームに於ける例外処理的文言その1')
}
レイヤーセット内のオブジェクトをランダムに回転・リサイズします。
リサイズの振り幅は70~130%
ダイアログで回転とリサイズを選択できます。

2017/09/20

Photoshop script 「テキストレイヤーのテキストをプレーンテキストで取得する」

テキストレイヤーのテキストをコピーするとテキストスタイルや情報もついてきて一旦メモ帳などへコピペしてると思うんですが、いい方法があったので解決策を。
ただしWindowsのみです。

var curLayer = app.activeDocument.activeLayer;

var folderForTempFiles = Folder.temp.fsName;

//バッチファイル用のテキスト生成
var clipTxtFile =new File(folderForTempFiles + "/ClipBoard.txt"); 
clipTxtFile.open('w'); 
clipTxtFile.write(curLayer.textItem.contents); 
clipTxtFile.close();

//バッチファイルを生成して実行
var clipBatFile =new File(folderForTempFiles + "/ClipBoard.bat"); 
clipBatFile.open('w'); 
clipBatFile.writeln("clip.exe < \"" + folderForTempFiles + "\\ClipBoard.txt\"");
clipBatFile.close(); 
clipBatFile.execute();

という感じで作成。

テキストオブジェクトの内容を取得してクリップボードへ渡すのですが。
「コピーする」というOS標準機能を使用するのが案外面倒なのです。
調べた挙句、海外フォーラムで発見したのが・・・

クリップボードを起動するバッチファイルを作成してパラメーターとしてテキストを渡す。という荒業。

実行するとコマンドプロンプトが出てきて外部プログラムであるクリップボードが起動するわけです。一瞬だけ。
コピーした情報は基本的に元来よりクリップボードへ送られるWindowsの仕様なので無事にCtrl+Cの挙動を再現できたわけですね。

使いたい人は自己責任ですが.jsxで保存すれば動くと思います。
動作環境はWin7+Photoshop CS5。