結論
BridgeTalkを使えばできるよ!
BridgeTalkまとめ
基本的に以下で紹介されている内容が詳しいです。
特に 「中綴製作所」 様は他のExtendScriptについても詳しく説明されていて、お世話になっております。
他のアプリケーションにスクリプトを実行させる
BridgeTalk考
BridgeTalkまとめ…というか覚え書き
ともあれ、この記事では私が使った技術と、詰まったところだけメモ的に残します。
Photoshopに処理させたいFunctionを呼ぶときはunevalを使う
(function () {
function openPsd() {
alert( "alert" );
}
const bridgeTalk = new BridgeTalk();
bridgeTalk.target = 'photoshop';
bridgeTalk.body = uneval( openPsd + "()" );
bridgeTalk.send();
})()
引数を渡したい場合は次のようにする。
(function () {
function openPsd( filePath: string ) {
alert( filePath );
}
const bridgeTalk = new BridgeTalk();
bridgeTalk.target = 'photoshop';
bridgeTalk.body = uneval( openPsd ) + "(" + uneval( filePath ) + ")";
bridgeTalk.send();
})()
unevalで呼び出すFunction内にコメントを書くと、エラーになる
(function () {
function openPsd( filePath: string ) {
// ここにコメントを書くとエラーになる
alert( filePath );
}
// ここにはコメントを書いても問題ない
const bridgeTalk = new BridgeTalk();
bridgeTalk.target = 'photoshop';
bridgeTalk.body = uneval( openPsd ) + "(" + uneval( filePath ) + ")";
bridgeTalk.send();
})()
Photoshopの処理終了を受け取る
(function () {
function openPsd() {
alert( "Photoshop" );
}
const bridgeTalk = new BridgeTalk();
bridgeTalk.target = 'photoshop';
bridgeTalk.body = uneval( openPsd + "()" );
bridgeTalk.onResult = function () {
alert( "処理が終了したようです。" );
};
bridgeTalk.send();
})()
今回の要件
- InDesignで開いたドキュメントに含まれる全てのリンクをPhotoshopで開く。
- Photoshopで開けないデータがリンク先に存在する可能性は考慮しない。
(テストで使用していたのはepsファイルとpsdファイル)
- Photoshopで開けないデータがリンク先に存在する可能性は考慮しない。
- Photoshopで開いたリンクは、全てJPEGで保存する。
コード
typescriptで書いています。
実装した時は複数ファイルに分けてましたけど、多分以下のコードを1ファイルにまとめても動くのではないかと。(未検証)
あと、もっと綺麗に書けるなぁというところもありますが、面倒だったので作成時点の当時の実力を忘れないために、そのまま載せます。
開き終わったクラス数をカウントするためのクラス
複数リンクを全てPhotoshopで開くが、BridgeTalkは非同期。
そのため、開き終わったリンク先の数をカウントするために使う。
class Counter {
private count: number = 0;
constructor( private maxCount: number ) {
}
increment() {
if ( this.count + 1 < this.maxCount ) {
this.count = this.count + 1;
}
}
isMax() {
return this.count === this.maxCount - 1;
}
}
外部から呼ばれる窓口
InDesign側で実行される処理。
リンク画像のパスを取得して、そのパスをbridgeOpenPsd
に渡す。
そのあとbridgeSavePsd
を呼ぶ。
export function saveLink(
outputPath: string
) {
const doc = app.activeDocument; // 必要に応じてドキュメントを開いたり、アクティブに切り替えたりする
const graphics = doc.allGraphics;
const len = graphics.length;
const counter = new Counter( len );
for ( let i = 0; i < len; i++ ) {
bridgeOpenPsd( graphics[ i ].itemLink.filePath, counter );
}
bridgeSavePsd( counter, outputPath );
}
Photoshopで指定されたファイルを開くBridgeTalkを起動する
処理が終わったらカウンターをインクリメント。
function bridgeOpenPsd(
filePath: string,
counter: Counter
) {
const btObj = new BridgeTalk();
btObj.target = 'photoshop';
btObj.body = uneval( openPsd ) + "(" + uneval( filePath ) + ")";
btObj.onResult = function () {
counter.increment();
};
btObj.send();
}
Photoshopで指定されたファイルを開く(Photoshop用スクリプト)
bridgeOpenPsdから呼ばれる。
指定されたファイルを開くだけ。
丁寧に作るなら、ファイルが存在するかどうかとか、拡張子とか判定する。(ここを呼ぶ前にInDesgin側で調べておいても良い)
この中にコメントを書くとエラーになる。
function openPsd(
path: string
): void {
app.open( new File( path ) );
}
Photoshopでファイルを保存するBrideTalkを起動する
タイムアウトの書き方は適当。
Promise使ってやりたいところだけど、処理している間に他の処理を挟むわけではないので妥協。
処理後のalertは処理確認のためなので、本番時は不要。
function bridgeSavePsd(
counter: Counter,
outputPath: string,
timeout: number = 30
) {
const dObj = new Date();
while ( counter.isMax() === false ) {
if ( (new Date()).getTime() > dObj.getTime() + 1000 * timeout ) {
throw new Error( "タイムアウトしました。" );
}
}
const btObj = new BridgeTalk();
btObj.target = 'photoshop';
btObj.body = uneval( savePsd ) + "(" + uneval( outputPath ) + ")";
btObj.onResult = function () {
alert( "complete" );
};
btObj.send();
}
Photoshopで開いているファイルを保存する(Photoshop用スクリプト)
bridgeSavePsdから呼ばれる。
JPEG保存時のオプションは適当。
JPEGじゃない形式に書き出したければここで色々と指定する。
保存するJPEGのファイル名は、元ファイル名の拡張子をJPEGに変更したものとなるように修正。
この中にコメントを書くとエラーになる。
function savePsd( outputPath: string ): void {
const jpegOptions = new JPEGSaveOptions();
jpegOptions.embedColorProfile = false;
jpegOptions.formatOptions = FormatOptions.STANDARDBASELINE;
jpegOptions.matte = MatteType.NONE;
jpegOptions.quality = 12;
const len = app.documents.length;
for ( let i = 0; i < len; i++ ) {
const doc = app.documents[ i ];
app.activeDocument = doc;
const name = doc.name;
const dotIndex = name.lastIndexOf( "." );
const filename = name.substring( 0, dotIndex );
const saveFile = createFile( outputPath + filename + ".jpg" );
doc.saveAs( saveFile, jpegOptions, true );
}
}
さいごに
この手の記事は、数がとても少ないと感じます。
引っかかるのは10年くらい前のものが多いです。
それだけ使われていない、ニッチな技術なのだと再確認してしまう今日この頃です。