画像の数だけレイヤー別に配置し、スマートオブジェクトに変換するツールを作ってみた。

昨年、「Photoshopで個別の画像をレイヤー別に配置し、すべて「スマートオブジェクト」に変換したい。」
とおっしゃっている知人がいました。
自動化できないものか？　と、力試しに作ってみました。


###仕様
Illustratorでレイヤーを保持した状態でPSDに書き出す方法を知っていたので、IllustratorとPhotoshopの2段構えの処理としました。
####**1. Illustrator**
#####01_Illustrator_複数画像をレイヤー別に中央配置.jsx
実行すると、210X297mm(A4サイズ)、RGBモードの新規ドキュメントを作成。
次に、ファイルが格納されたフォルダを指定するダイアログが開き、フォルダを指定すると、フォルダ内にある画像の数だけ、Illustratorでレイヤー別に配置（中央揃え）します。
最後に、ai形式で保存し、psd形式で書き出します。
yyyy年mm月dd日hh時mm分ss秒.ai
yyyy年mm月dd日hh時mm分ss秒.psd
上記のようなファイル名になります。
※A4以上のサイズだとドキュメントサイズでトリミングされてしまいます。

![WS001.JPG](https://qiita-image-store.s3.amazonaws.com/0/122812/22d2b2c8-e46e-0a4d-58bc-f9afeeac5b02.jpeg)
▲処理する画像を格納したフォルダを選択。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/90ae9853-64d5-f6e9-2519-fb77441983a2.png)
▲処理終了。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/dcde270f-e24a-a383-8e5b-ece2e4786fa6.png)
▲デスクトップに保存されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/3e6613ab-5ecb-90c4-b1b0-833a55831a84.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/b5659539-be71-8601-74de-94a713209487.png)
▲処理した画像は5つ。Illustratorのレイヤーごとに配置されました。

####**2. Photoshop**
実行するとファイルを選択するダイアログが表示されるので、処理したいPSDファイルを選びます。
すでに開いていた場合、このダイアログは表示されません。
全てのレイヤーを「スマートオブジェクトに変換」します。
最後に画像を開いた状態で保存します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/a0f0c49b-b667-02d4-c3bc-18dac76f80f8.png)
▲処理したいPSDファイルを選びます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/0657d705-2a1a-c872-228c-f60b09457911.png)
▲終了。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/7e6f8072-ccb9-fd69-10c7-7a7b49358ccb.png)
▲「スマートオブジェクトに変換」されてます。

コードは以下です。

##Illustrator JSX
```JavaScript:01_Illustrator_複数画像をレイヤー別に中央配置.jsx
//▼新規ドキュメント作成
var docWidth = 841.89; //ページの横幅。297mm
var docHeight = 595.276; //ページの縦幅。210mm
var docObj = documents.add(DocumentColorSpace.RGB, docWidth, docHeight); //RGB空スペースでドキュメント作成
var recObj = docObj.pathItems.rectangle(0, 0, 841.89, -595.276); //ドキュメントサイズに矩形を作成
recObj.filled = false; //塗りなし
recObj.stroked = false; //線なし

//▼日付を取得
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
var saveDate = year + "年" + zeroPad02(month) + "月" + zeroPad02(day) + "日" + zeroPad02(hour) + "時" + zeroPad02(minute) + "分" + zeroPad02(second) + "秒"; //保存時の時刻を取得→ファイル名

MAIN: { //ラベル
    //▼ドキュメント操作
    var doc = app.activeDocument;

    var selFolder = Folder.selectDialog("処理するフォルダを選択してください");
    if (selFolder == null) {
        alert("キャンセルしました。");
        doc.close(); //保存しないで閉じる
        break MAIN; //処理を抜ける
    }
    var selFiles = new Array;
    var selFiles = selFolder.getFiles(); //処理前のフォルダから全てのファイルを取得
    var myLayer = doc.layers;

    //▼1番目のレイヤーの処理
    activeDocument.layers[0].name = "001"; //1番目のレイヤー名を"001"に
    myItem = myLayer[0].placedItems.add();
    myItem.file = selFiles[0];

    centerAlig(myItem.file); //「アートボードに整列、天地左右センター配置」関数実行

    //▼2番目以降のレイヤーの処理
    for (var i = 1, selFilesLength = selFiles.length; i < selFilesLength; i++) {
        myLayer = doc.layers.add();
        myLayer.name = zeroPad03([i + 1]); //2番目以降のレイヤー名を"002～"に
        myItem = myLayer.placedItems.add();
        myItem.file = selFiles[i];
        centerAlig(myItem.file); //「アートボードに整列、天地左右センター配置」関数実行
    }

    //▼ai保存
    var saveOptions = new IllustratorSaveOptions;
    with(saveOptions) { //ai保存のデフォルト設定
        pdfCompatible = true; //PDF互換ファイルを作成
        embedLinkedFiles = false; //配置した画像を埋め込まない
        embedICCProfile = true; //ICCプロファイルを埋め込む
        compressed = true; //圧縮を使用
    }

    //var saveFolder = Folder.selectDialog("保存先のフォルダを選択してください") ;
    var saveFolder = "~/Desktop/"; //saveFolder+"/"
    var saveFile = new File(saveFolder + saveDate + ".ai");
    doc.saveAs(saveFile, saveOptions);

    //▼PSD書き出し
    var exportOptions = new ExportOptionsPhotoshop();
    var type = ExportType.PHOTOSHOP;
    var saveDir = new File(saveFolder + saveDate + ".psd");
    exportOptions.antiAliasing = true;
    exportOptions.writeLayers = true;
    exportOptions.resolution = 240;
    doc.exportFile(saveDir, type, exportOptions);

    doc.close(); //閉じる
    alert("処理が終わりました");
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
            関数定義
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/
//▼アートボードに整列、天地左右センター配置。
function centerAlig() {
    app.coordinateSystem = CoordinateSystem.ARTBOARDCOORDINATESYSTEM;
    var abIdx = app.activeDocument.artboards.getActiveArtboardIndex();
    var actAbBds = app.activeDocument.artboards[abIdx].artboardRect;
    moveObj = myItem;
    moveObj.position = new Array((actAbBds[2] - actAbBds[0]) / 2 - moveObj.width / 2, (actAbBds[3] - actAbBds[1]) / 2 + moveObj.height / 2);
    return moveObj;
}

//▼ゼロパディング3桁・レイヤー名用
function zeroPad03(num) {
    var num = ("00" + num).slice(-3);
    return num;
}

//▼ゼロパディング2桁。ファイル名用
function zeroPad02(num) {
    var num = ("00" + num).slice(-2);
    return num;
}
```

##Photoshop JSX
```JavaScript:02_Photoshop_全てのレイヤーをスマートオブジェクトに変換.jsx
MAIN: { //ラベル
    if (documents.length == 0) { //ファイルが開いていない場合ダイアログを表示する
        var selFile = File.openDialog("処理したいファイルを選んでください。");
        if (selFile == null) {
            alert("キャンセルされました。");
            break MAIN; //キャンセルしたら処理を抜ける
        } else {
            var openFile = new File(selFile);
            app.open(openFile);
        }
    }

    var doc = app.activeDocument;
    var _layer = doc.artLayers;

    for (var i = 0, layerLength = _layer.length; i < layerLength; i++) {
        //▼ScriptListaner使用。
        var idslct = charIDToTypeID("slct");
        var desc3 = new ActionDescriptor();
        var idnull = charIDToTypeID("null");
        var ref1 = new ActionReference();
        var idLyr = charIDToTypeID("Lyr ");
        ref1.putName(idLyr, _layer[i].name); //ここの第二引数にレイヤー数分指定。nameプロパティは必要。
        desc3.putReference(idnull, ref1);
        var idMkVs = charIDToTypeID("MkVs");
        desc3.putBoolean(idMkVs, false);
        var idLyrI = charIDToTypeID("LyrI");
        var list1 = new ActionList();
        list1.putInteger(13);
        desc3.putList(idLyrI, list1);

        executeAction(idslct, desc3, DialogModes.NO); //レイヤーを順次選択。

        var idnewPlacedLayer = stringIDToTypeID("newPlacedLayer"); //スマートオブジェクトに変換。
        executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
    }
    activeDocument.save();
    alert("全てのレイヤーをスマートオブジェクトに変換し、\r\n保存しました。");
```

###感想
Photoshopのレイヤー複製処理をどうするか、あれこれ悩んだのですが、時間をかけるより進めた方がいいとIllustratorの機能を使ってみました。
Photoshopレイヤーは、数種類の数がありますが、取得することはできても、変更できるプロパティは「Text」と「normal」だけみたいです。
この箇所だけScriptListanerを使用しました。

###課題
・IllustratorとPhotoshopと処理を分けてしまったが、BridgeTalkを使用して1つにできないか要検証。
・Illustratorの処理中にプログレスバーを設けてもよかったかも。。。

動作確認はWindows10 Adobe CC 2017、2018でしか行っていませんので責任は負いかねます。