InDesignの配置画像の拡大率を調べ、Photoshopでリサイズするツールを作ってみた話。

よく、巨大な画像を縮小して貼り込んでくるデータってあるじゃないですか？
昔、A1サイズのPOPのデータをEPS保存し、1桁の％で小さく配置したデータに遭遇したときには度肝を抜かれました！
いやっ、いまだに横着したデータで入稿してくるケースも多々あります。

そこでExtendScript Toolkitを使い、InDesignの画像の配置倍率を取得し、Photoshopでリサイズ、InDesignで更新。ログを書き出すツールを作ってみました。

## 仕様
行程を3つに別けました。
**●その1　グループ解除**
画像フレームを選択し倍率を取得する仕様上、
ロックがかかっていると選択できないので下記のロックを解除します。
・レイヤーのロック。
・アイテムのロック。
最後に、グループ化を解除します。
このとき、テキストフレーム内にアンカーオブジェクトがある場合エラーになるので、アンカーオブジェクトのあるテキストフレームにロックをかけます。
・再度、グループ化を解除。
・最後に、グラフィックフレーム以外の全てにロックをかけます。

**●その2　InDesignから拡大率を取得、Photoshopでリサイズ処理**
InDesignから配置画像の拡大率を取得し、その数値をPhotoshopに渡します。PhotoshopでInDesignから受け取った数値をもとにリサイズ処理を行います。
InDesignで100%の配置サイズでのリサイズが理想ですが、多少の誤差があり100%に近い数値での処理になります。

**●その3　InDesignで画像の更新。処理後、textファイルでログを書き出します。**
InDesignで画像を更新します。
デスクトップにログファイルを書き出します。
ログファイルには、
ファイル名、幅・高さの倍率、縦横比が等しいか、を記述します。

※InDesignドキュメントは1ページ物
※画像は上書きされます。
※あくまでもPhohoshopの画像に関しての処理です。
　IllustratorのイラストなどはPhotoshopで開くときにラスタライズのアラートが出て次の処理を求められます。
※処理後、InDesignは保存しません。

## 手順
JSXをInDesignの下記のディレクトリに配置します。
C:\Users\UsersName\AppData\Roaming\Adobe\InDesign\Version 13.0-J\ja_JP\Scripts\Scripts 
下図のようなドキュメントを用意しました。
画像とキャプションをグループ化し、さらにそれらをグループ化、さらに全てをグループ化してあります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/acffa97e-de73-451b-5f30-0d52b2b282c1.png)
**●その1　グループ解除**
グループ解除ツール「01_ungroup.jsx」をスクリプトパネルから実行します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/36686243-044f-e300-0169-abb20132a284.png)
警告が表示されるので「OK」を押下します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/0c54822f-11e1-1bcc-485e-475427dd9d85.png)
最後に下図が表示され処理終了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/96f9e05f-a7c7-3a61-6d44-1e5e460cbe33.png)
グラフィックフレーム以外はロックがかかります。

**●その2　InDesignから拡大率を取得、Photoshopでリサイズ処理**
画像フレームを選択し、ツール「02_InDesign2Photoshop_resize.jsx」をスクリプトパネルから実行します。
Photoshopで各画像が開きリサイズ処理が走ります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/1520447a-3acc-f02d-34b6-619a3d0a8b41.png)
処理が終わると下図が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/520eb7af-6e6f-559b-c405-4cec7ba846b1.png)

**●その3　InDesignで画像の更新。処理後、textファイルでログを書き出します。**
ツール「03_画像更新_log書き出し.jsx」をスクリプトパネルから実行します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/c42d4447-3a2d-b520-2e7b-79b9fcadcb42.png)
画像を選択してなくても、自動的に更新してくれます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/25b9f494-d5b3-4e99-a254-fc84520f87e0.png)
下図が表示され処理終了。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/135ea025-cc62-b3b0-bd79-4bcd22a512f2.png)
最後に、デスクトップにタイムスタンプのファイルを付与したログファイルを書き出してくれます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/122812/69dfc2cb-fe85-ac27-cb98-b9c321dcb452.png)
縦横比が同じ数値なら「〇」異なっていたら「×」が表示されます。
※まれに「×」が出ますが、小数点最下部の誤差的な数値です。


## ソースコード
**●その1　グループ解除**

```javascript:01_ungroup.jsx
var doc = app.activeDocument, //アクティブドキュメント
    items = doc.allPageItems, //ページアイテム
    grpItem = doc.groups, //グループアイテム
    txtFrames = doc.textFrames, //テキストフレーム
    layer = doc.layers, //レイヤー
    page = doc.pages[0]; //ページ

//▼テキストフレーム内アンカーオブジェクトの検索設定
app.findGrepPreferences = NothingEnum.nothing; //検索文字列初期化
app.findGrepPreferences.findWhat = "~a"; //検索文字をアンカーに設定→アンカーは正規表現で"~a"

//▼ダイアログを表示
var win = new Window("dialog", "警告！", [200, 100, 450, 210]);
win.add("statictext", [10, -50, 250, 80], "レイヤーのロック、オブジェクトのロック、\r\nグループ化を解除します。\r\n宜しいですか？");
win.cancelBtn = win.add("button", [35, 70, 115, 95], "キャンセル", {
    name: "cancel"
});
win.okBtn = win.add("button", [140, 70, 220, 95], "OK", {
    name: "ok"
});
win.center();
var btnFlg = win.show();
if (btnFlg == 2) {
    alert("処理を中断します。");
    exit();
}

//▼レイヤーのロック解除
for (var i = 0, layLen = layer.length; i < layLen; i++) {
    if (layer[i].locked == true) {
        layer[i].locked = false;
    }
}

//▼一度全てのアイテムロックを解除
for (var j = 0, itemsLen = items.length; j < itemsLen; j++) {
    if (items[j].locked == true) {
        items[j].locked = false;
    }
}

//▼グループ解除
try {
    for (var k = 0, itemsLen = items.length; k < itemsLen; k++) { //一度全てのグループ解除を試みる
        if (items[k].constructor.name == "Group") {
            items[k].ungroup(); //グループ解除
        }
    }
} catch (e) { //エラー処理 → アンカーオブジェクトがあった場合ロックをかける
    for (var l = 0, txtFramesLen = txtFrames.length; l < txtFramesLen; l++) {
        if (txtFrames[l].findGrep().length > 0) {
            txtFrames[l].locked = true; //ロックをかける
        }
    }
    for (var m = 0, itemsLen = items.length; m < itemsLen; m++) { //エラー対象以外で、再度グループ解除
        if (items[m].constructor.name == "Group") {
            doc.selection = grpItem; //グループアイテムを選択
            var sel = doc.selection;
            for (var n = 0, selLen = sel.length; n < selLen; n++) {
                sel[n].ungroup(); //グループ解除
            }
        }
    }
}

//▼テキストフレームにロックをかける
for (var o = 0; o < page.textFrames.length; o++) {
    page.textFrames[o].locked = true;;
}

alert("処理が終わりました。\r\nグラフィックフレーム以外のオブジェクトにロックをかけました。\r\nテキストフレーム内のアンカーオブジェクトのグループは解除できません。");
```

**●その2　InDesignから拡大率を取得、Photoshopでリサイズ処理**

```javascript:02_InDesign2Photoshop_resize.jsx
#target 'indesign'
#targetengine 'imgResize'

var doc = app.activeDocument, //最前面のドキュメント
    sel = doc.selection, //選択しているオブジェクト
    docName = doc.name; //ドキュメント名

//▼エラー処理
if (sel.length < 1) {
    alert("画像フレームを選択してから処理を実行してください。");
    exit();
}

for (var i = 0, selLen = sel.length; i < selLen; i++) { //選択しているオブジェクト分繰り返す
    try {
        if (sel[i].contentType != 1735553140 || sel[i].contentType == 1952412773 || sel[i].contentType == 1970168179) {
            alert("画像フレーム以外が選択されています。処理を中断します。");
            exit();
        } else if (sel[i].allGraphics[0] == undefined) {
            alert("空の画像フレームを選択している可能性があります。\r\n処理を中断します。");
            exit();
        }
    } catch (e) {
        alert("画像フレーム以外が選択されています。処理を中断します。");
        exit();
    }
}

process(endCall); //処理実行

//▼処理
function process(callback) {
for (var i = 0, selLen = sel.length; i < selLen; i++) { //選択しているオブジェクト分繰り返す
    var filePath = sel[i].allGraphics[0].itemLink.filePath; //ファイルパス
    var replacePath = filePath.replace(/\\/g, '\/'); // '\' を '/' に置換

    var horiSize = (sel[i].allGraphics[0].absoluteHorizontalScale) / 100; //幅を取得
    var verSize = (sel[i].allGraphics[0].absoluteVerticalScale) / 100; //高さを取得

    //▼BridgeTalk　Photoshopへ
    var bridgeTalkPH = new BridgeTalk();
    bridgeTalkPH.target = 'photoshop';
    bridgeTalkPH.body = uneval(imgOpen) + '(' + '"' + replacePath + '"' + ',' + horiSize + ',' + verSize + ');'; //Photoshop リサイズ～上書き保存の関数実行
    bridgeTalkPH.send();
}
callback(); //コールバック関数
}

//▼処理終了の表示関数
function endCall() {
    var bridgeTalkPH2 = new BridgeTalk();
    bridgeTalkPH2.target = 'photoshop';
    bridgeTalkPH2.body = 'alert("リサイズ処理が終わりました。");';
    bridgeTalkPH2.send();
}

//▼Photoshop リサイズ～上書き保存の関数
function imgOpen(replacePath, horiSize, verSize) {
    var openFile = new File(replacePath);
    open(openFile);
    var doc = app.activeDocument;
    var docName = doc.name,
        docWidth = doc.width.value,
        docHeight = doc.height.value;
    doc.resizeImage(docWidth * horiSize, docHeight * verSize);
    doc.save();
    doc.close();
}
```

**●その3　InDesignで画像の更新。処理後、textファイルでログを書き出し**

```javascript:03_画像更新_log書き出し.jsx
var doc = app.activeDocument; //アクティブドキュメント
var img = doc.allGraphics; //ドキュメント上の全てのグラフィックフレーム

var imgPropertiesArray = []; //結果の配列を準備

for (var i = 0, imgLen = img.length; i < imgLen; i++) { //グラフィックフレームの数だけ繰り返す
    if (doc.allGraphics[i].itemLink.status == 1819242340) { //更新が必要なフレームだった場合
        doc.allGraphics[i].itemLink.update(); //更新
        var imgName = doc.allGraphics[i].itemLink.name, //画像名の取得
            imgHoriSize = doc.allGraphics[i].absoluteHorizontalScale, //幅の取得
            imgVerSize = doc.allGraphics[i].absoluteVerticalScale; //高さの取得

        if (imgHoriSize == imgVerSize) {
            var comment = "縦横比：○"; //縦横比が同じ場合のコメント
        } else {
            var comment = "縦横比：×"; //縦横比が異なる場合のコメント
        }

        var imgResult = "ファイル名：" + imgName + "\r\n幅：" + imgHoriSize + "%\r\n高：" + imgVerSize + "%\r\n" + comment + "\r\n";
        imgPropertiesArray.push(imgResult);
    }
}

var myArraymyStyleText = imgPropertiesArray.toString(); //スタイルを格納した配列を文字列に変換
var repmyStyleText = myArraymyStyleText.replace(/,/g, "\r\n"); //文字列化したCSVのカンマを改行に置換

//▼ファイル名にする日付を取得
var myDate = new Date(),
    myYear = myDate.getFullYear(), //年を取得
    myMonth = myDate.getMonth() + 1, //月を取得
    myDay = myDate.getDate(), //日を取得
    myHours = myDate.getHours(), //時を取得
    myMinutes = myDate.getMinutes(), //分を取得
    mySeconds = myDate.getSeconds(), //秒を取得
    nowTime = myYear + "年" + myMonth + "月" + myDay + "日" + myHours + "時" + myMinutes + "分" + mySeconds + "秒" + "_log";

/*==============================================================
=======================ファイル保存================================
================================================================*/
(function () { //即時関数を定義し実行
    var fileObj = new File("~/Desktop/" + nowTime + ".txt"); //ファイル名を入力して保存
    var inputFileName = fileObj.open("w");
    if (inputFileName == true) {
        fileObj.encoding = "UTF-8"; //UTF-8を指定。これを入れないと異体字依存で書き出されない場合がある。
        fileObj.writeln(repmyStyleText); //書き出すテキストを連結
        fileObj.close();
        alert("処理が終わりました。\r\nデスクトップにログファイルを保存しました。");
    }
})();
```

動作確認はWindows 10、InDesign CC 2019 でしか行っておりません。

**課題**
本来ならば1度の処理にしたかった。
bridgeTalk で InDesign → Photoshop → InDesign とした場合、ラグがあるのか、InDesignが画像の更新を認知してくれないといった問題がありました。
リサイズの際にPhotoshopがアクティブにならないなど、アプリケーション連携の際、アクティブにする仕組みが必要です。
調べてみたいと思います。