1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

InDesignのリンク画像をPhotoshopで開いて保存するスクリプト

Posted at

結論

BridgeTalkを使えばできるよ!

BridgeTalkまとめ

基本的に以下で紹介されている内容が詳しいです。
特に 「中綴製作所」 様は他のExtendScriptについても詳しく説明されていて、お世話になっております。

他のアプリケーションにスクリプトを実行させる
BridgeTalk考
BridgeTalkまとめ…というか覚え書き

ともあれ、この記事では私が使った技術と、詰まったところだけメモ的に残します。

Photoshopに処理させたいFunctionを呼ぶときはunevalを使う

open-psd.ts
(function () {
	function openPsd() {
		alert( "alert" );
	}

	const bridgeTalk = new BridgeTalk();
	bridgeTalk.target = 'photoshop';
	bridgeTalk.body = uneval( openPsd + "()" );
	bridgeTalk.send();
})()

引数を渡したい場合は次のようにする。

open-psd2.ts
(function () {
	function openPsd( filePath: string ) {
		alert( filePath );
	}

	const bridgeTalk = new BridgeTalk();
	bridgeTalk.target = 'photoshop';
	bridgeTalk.body = uneval( openPsd ) + "(" + uneval( filePath ) + ")";
	bridgeTalk.send();
})()

unevalで呼び出すFunction内にコメントを書くと、エラーになる

open-psd-error.ts
(function () {
	function openPsd( filePath: string ) {
		// ここにコメントを書くとエラーになる
		alert( filePath );
	}

	// ここにはコメントを書いても問題ない
	const bridgeTalk = new BridgeTalk();
	bridgeTalk.target = 'photoshop';
	bridgeTalk.body = uneval( openPsd ) + "(" + uneval( filePath ) + ")";
	bridgeTalk.send();
})()

Photoshopの処理終了を受け取る

onResult.ts
(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で開いたリンクは、全て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年くらい前のものが多いです。
それだけ使われていない、ニッチな技術なのだと再確認してしまう今日この頃です。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?