Amazonで商品を見るセール会場へ

Photoshop│リンクスマートオブジェクトからレイヤーカンプ一覧を取得するスクリプト

Photoshopでリンク配置したスマートオブジェクト(.psd)のレイヤーカンプを活用して管理する場面は多く見られます。

しかし、スマートオブジェクト内のレイヤーカンプを取得する標準のAPIは用意されていません。

それでも、Photoshopの非公開内部情報にアクセスする手法を用いれば、レイヤーカンプ一覧を取得できます。

この記事では、アクティブなドキュメント内にある全スマートオブジェクトレイヤーからレイヤーカンプ一覧を取得し、ダイアログに表示するExtendScript(JSX)を紹介します。

スマートオブジェクトから取得したレイヤーカンプ一覧がダイアログに表示された様子。
目次

標準APIを使わずにレイヤーカンプを取得する方法

Photoshopのほかの自動化手順は、まとめ記事で確認できます。

処理の要となるのは、executeActionGet() と ActionReference の組み合わせです。

var ref = new ActionReference();
ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
var desc = executeActionGet(ref);

この処理により、レイヤーのプロパティ情報に直接アクセスできます。

取得したプロパティ内には、スマートオブジェクト専用の smartObject キーが存在し、その階層下に compsList というリスト構造が格納されています。

内部データ構造からレイヤーカンプ一覧を取得する手順

layer (ArtLayer) →
  executeActionGet(ref) →
    desc.getObjectValue("smartObject") →
      getObjectValue("compsList") →
        getList("compList") → 各カンプ情報

各 comp オブジェクトには以下の情報が含まれています。

キー名意味
nameレイヤーカンプの名前
IDカンプに割り当てられたID

補足:公式ドキュメントに記載のないActionManagerの利用について

このデータ構造は、公式のDOM(Document Object Model)では取得できません。

代替手段として、ActionManager(AMコード)と呼ばれる低レベルAPIを利用し、Photoshop内部のプロパティを参照しています。

こうした記述方法は、Photoshopの操作をコード化するScripting Listenerプラグインなどで出力ログを解析して特定されています。

サンプルコード

以下のスクリプトを拡張子 .jsx のファイルとして保存し、Photoshopの[ファイル]メニューなどから実行してください。

※リンク配置だけでなく、埋め込みスマートオブジェクトにも対応しています。

#target photoshop

// 対象レイヤーを再帰的に収集
function collectAllLayers(layerCollection, result) {
    for (var i = 0; i < layerCollection.length; i++) {
        var layer = layerCollection[i];
        if (layer.typename === "ArtLayer") {
            result.push(layer);
        } else if (layer.typename === "LayerSet") {
            collectAllLayers(layer.layers, result);
        }
    }
}

// スマートオブジェクトのレイヤーカンプ一覧を取得
function getLayerCompsFromSmartObject(layer) {
    var list = [];

    try {
        var ref = new ActionReference();
        ref.putIdentifier(charIDToTypeID("Lyr "), layer.id);
        var desc = executeActionGet(ref);

        if (!desc.hasKey(stringIDToTypeID("smartObject"))) return [];

        var soDesc = desc.getObjectValue(stringIDToTypeID("smartObject"));

        if (!soDesc.hasKey(stringIDToTypeID("compsList"))) return [];

        var compsList = soDesc.getObjectValue(stringIDToTypeID("compsList")).getList(stringIDToTypeID("compList"));
        for (var i = 0; i < compsList.count; i++) {
            var comp = compsList.getObjectValue(i);
            var name = comp.getString(stringIDToTypeID("name"));
            var id = comp.getInteger(stringIDToTypeID("ID"));
            list.push({ name: name, id: id });
        }
    } catch (e) {
        // 無視(対象外)
    }

    return list;
}

// メイン処理
function main() {
    if (app.documents.length === 0) {
        alert("ドキュメントが開かれていません。");
        return;
    }

    var allLayers = [];
    collectAllLayers(app.activeDocument.layers, allLayers);

    var output = "スマートオブジェクトのレイヤーカンプ一覧:\n\n";
    var found = false;

    for (var i = 0; i < allLayers.length; i++) {
        var layer = allLayers[i];
        if (layer.kind === LayerKind.SMARTOBJECT) {
            var comps = getLayerCompsFromSmartObject(layer);
            if (comps.length > 0) {
                found = true;
                output += "【" + layer.name + "】\n";
                for (var j = 0; j < comps.length; j++) {
                    output += "  ・[" + comps[j].id + "] " + comps[j].name + "\n";
                }
                output += "\n";
            }
        }
    }

    if (!found) {
        alert("レイヤーカンプ付きスマートオブジェクトは見つかりませんでした。");
    } else {
        alert(output);
    }
}

main();

スクリプトを実行すると、レイヤーカンプを保持するスマートオブジェクトを検出し、その一覧情報をダイアログに表示します。

スクリプトを実行してスマートオブジェクトから検出されたレイヤーカンプ一覧情報が表示されたダイアログ。

この記事で紹介しているコードは、GitHubのMOTOKI-LLC/cg-method-codeにもまとめています。

レイヤーを操作するスクリプトは、ほかにもあります。

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

Photoshopのおすすめ書籍

動作要件とPCの確認項目

周辺機器の優先度

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次