投稿日:2022年11月27日

先日、2022年11月8日の皆既月食はご覧になりましたでしょうか?
私は地元、所沢市の狭山湖堰堤から観望しました。

▲一眼でタイムラプスを撮影。望遠鏡にiPhone6sを装着して拡大写真を撮りました。

▲タイムラプス動画です。
iPhoneで撮影したものがサムネールになっています。

さて、ニュースサイトなどでよく見かける比較明合成という画像ですが、Photoshopのレイヤーモード「カラー比較(明)」を使用すれば作れるということを最近知りました。
ある程度の間隔を空けて撮影した画像を選び、合成したのが下図になります。

▲24コマ置きに合成しました。

数枚置きに画像を選択といっても2,000枚近い画像から選ぶとなると、数え違いが起きたり、大変な労力と時間が費やされます。

そこでPhotoshopのJSXで自動処理できないかと考察し、作ってみました。
下図がその動きです。

▲1,777枚の画像を格納したフォルダを選択し、25枚置きに合成しています。
レイヤーモードを「カラー比較(明)」にし、レイヤー複製で最初の画像に配置します。

JSXの編集

JSXのソースコードは以下です。

▲71〜116行目、Adobeが配布している無料プラグイン ScriptingListener から書き出されるソースコードを使用しています。

JSXの編集はVisual Studio Codeを使用します。
以前の紹介記事 ではExtendScript Debugger 1.x系の紹介をしていましたが、ver2.x系 ではlaunch.jsonが不要など大きく仕様が変更されたようです。

▲VS Codeのextension、ExtendScript Debugger ver2.0.3

▲プログラムの実行には、実行 > デバッグの開始を選択します。

▲もしくはアクティビティバー実行とデバッグから開始します。

▲表示されるデバッグモードからLaunchを選択します。
翻訳は以下です。
Launch
ホストアプリケーションでアクティブなスクリプトをデバッグします。
スクリプトを直接デバッグするのに便利です。

Attach
ホストアプリケーションにアタッチします。すぐにスクリプトが実行されるわけではありません。
CEP および ScriptUI のデバッグに便利です。

▲続いて実行プログラムを選択します。今回はPhotoshopを選択します。

▲対象のアプリケーションが起動してないと上図のような警告が表示されます。

ScriptingListener プラグイン

Adobeのサイト からダウンロードします。
ダウンロードしたZIPを解凍し下図の階層にインストールします。
Photoshopを再起動します。

▲許可を求める画面が表示されるので許可します。

▲Photoshopを起動するとセキュリティに関する警告が表示されるのでキャンセルをクリックします。

システム設定プライバシーとセキュリティからインストールしたScriptListener.pliginを探し「このまま許可」をクリックします。

▲Photoshopを起動すると再度警告が表示されるので開くをクリックします。

▲起動するとデスクトップにlogファイルができます。
このファイルに実行した内容が記述されていきます。
Photoshop 2019 以前のバージョンでは記述のON、OFFができましたが、Photoshop 2020以降はできない仕様のようです。
以下は記述の一部です。

// =======================================================
var idfeatureInfo = stringIDToTypeID( "featureInfo" );
    var desc1 = new ActionDescriptor();
    var idactive = stringIDToTypeID( "active" );
    desc1.putBoolean( idactive, true );
    var idcommand = stringIDToTypeID( "command" );
    desc1.putString( idcommand, """getFeatureActive""" );
    var iddontRecord = stringIDToTypeID( "dontRecord" );
    desc1.putBoolean( iddontRecord, true );
    var idforceNotify = stringIDToTypeID( "forceNotify" );
    desc1.putBoolean( idforceNotify, true );
executeAction( idfeatureInfo, desc1, DialogModes.NO );

// =======================================================
var idhostFocusChanged = stringIDToTypeID( "hostFocusChanged" );
    var desc2 = new ActionDescriptor();
    var idactive = stringIDToTypeID( "active" );
    desc2.putBoolean( idactive, true );
    var iddontRecord = stringIDToTypeID( "dontRecord" );
    desc2.putBoolean( iddontRecord, true );
    var idforceNotify = stringIDToTypeID( "forceNotify" );
    desc2.putBoolean( idforceNotify, true );
executeAction( idhostFocusChanged, desc2, DialogModes.NO );

// =======================================================
var idLoadedPluginsNames = stringIDToTypeID( "LoadedPluginsNames" );
    var desc3 = new ActionDescriptor();
    var idpolygon = stringIDToTypeID( "polygon" );
        var list1 = new ActionList();
        list1.putString( """広角補正...""" );
        list1.putString( """平均""" );
        list1.putString( """Camera Raw""" );
        list1.putString( """Camera Raw フィルター""" );
        list1.putString( """ピクチャパッケージフィルター...""" );
        list1.putString( """Matlab 操作""" );
        list1.putString( """Cineon""" );
        list1.putString( """雲模様 1""" );
        list1.putString( """雲模様 2""" );
        list1.putString( """角度補正して切り抜き""" );

// 〜〜〜〜〜〜〜〜〜〜〜 以下省略 〜〜〜〜〜〜〜〜〜〜〜

▲起動しただけで3,000行弱のソースが書き出されます。
読み込んだプラグインも全て書き出されるようです。
ScriptingListenerJS.log 自体を削除し、Photoshopをアクティブにしても「アクティブにした」というログが記述されます。
実行したコマンドの箇所を見定めJSXに追記するのがコツです。

上記のソースコードのScriptListenerの箇所です。

var idset = stringIDToTypeID("set");
var desc1080 = new ActionDescriptor();
var idnull = stringIDToTypeID("null");
var ref205 = new ActionReference();
var idlayer = stringIDToTypeID("layer");
var idordinal = stringIDToTypeID("ordinal");
var idtargetEnum = stringIDToTypeID("targetEnum");
ref205.putEnumerated(idlayer, idordinal, idtargetEnum);
desc1080.putReference(idnull, ref205);
var idto = stringIDToTypeID("to");
var desc1081 = new ActionDescriptor();
var idmode = stringIDToTypeID("mode");
var idblendMode = stringIDToTypeID("blendMode");
var idlighterColor = stringIDToTypeID("lighterColor");
desc1081.putEnumerated(idmode, idblendMode, idlighterColor);
var idlayer = stringIDToTypeID("layer");
desc1080.putObject(idto, idlayer, desc1081);
executeAction(idset, desc1080, DialogModes.NO);

レイヤーモードを「カラー比較(明るい)」に設定
14行目の lighterColor が「カラー比較(明るい)」に該当します。

var idduplicate = stringIDToTypeID("duplicate");
var desc687 = new ActionDescriptor();
var idnull = stringIDToTypeID("null");
var ref136 = new ActionReference();
var idlayer = stringIDToTypeID("layer");
var idordinal = stringIDToTypeID("ordinal");
var idtargetEnum = stringIDToTypeID("targetEnum");
ref136.putEnumerated(idlayer, idordinal, idtargetEnum);
desc687.putReference(idnull, ref136);
var idto = stringIDToTypeID("to");
var ref137 = new ActionReference();
var iddocument = stringIDToTypeID("document");
ref137.putName(iddocument, firstFileName); //最初のファイルに複製
desc687.putReference(idto, ref137);
var iddestinationDocumentID = stringIDToTypeID("destinationDocumentID");
desc687.putInteger(iddestinationDocumentID, 283);
var idversion = stringIDToTypeID("version");
desc687.putInteger(idversion, 5);
executeAction(idduplicate, desc687, DialogModes.NO);

レイヤーを複製(対象のファイルに複製)
13行目の第2引数に対象のファイルを記述しています。変数 firstFileName に最初に開いたファイル名を定義しています。

まとめ

以前検証したExtendScript DebuggerScriptListener
いつの間にか仕様も変更され再検証の必要がありました。

Adobeソフトの自動化からも離れていましたが、必要に応じて検証してみたいと思いました。
ScriptListenerを使った箇所も、できればJSXで記述したかったのですが、力及びませんでした。
他にもアクションを併用し柔軟な自動化を行えればと思います。

最後まで読んでくださりありがとうございました。

お断りとして、紹介しているソースコードはご自由に使用していただいても構いませんが、生じたトラブル、損害などについては、本サイト、紹介しているサイトさま共に、一切の責任を追わないものとします。

参考にしたサイト

古籏 一浩さまのサイト

Adobe Photoshop CC JavaScript Reference

関連記事
Pocket