
【JavaScript】イラレのアートボードをオブジェクトぴったりに調整してJPEG保存したい

私たちMIGは、主に『病気がみえる』『薬がみえる』など「みえる系」と呼ばれるビジュアル書籍を制作していますが、アプリやオンラインコンテンツの制作に関わることも少なくありません。
先日、医療系国家試験のオンライン問題集である『クエスチョン・バンク(以下、QB)オンライン』の担当者から、「『みえる系』書籍の図版を『QBオンライン』に流用したい」と依頼がありました。
1,200点の図版を微修正してJPEGでください!
依頼の概要はこんな感じです。
発行済みの「みえる系」書籍と、現在進行中の「みえる系」最新刊から、1,200点ほどの画像を流用(一部改変)したい。
掲載媒体はオンラインコンテンツのため、.jpgファイルで納品してほしい。
図版の拡大・縮小は『QBオンライン』上で自動調整されるので、ひとまず大きめのサイズでほしい。
jpgは図版の天地左右サイズに合わせてトリミングしてほしい。
微修正が生じる可能性があるので、オリジナルデータの.inddファイルと.aiファイルも保管したい。
納品ファイル名は、一定のルールに従ってつけてほしい。

「元データの.aiファイルがあるなら、Illustratorのバッチ機能で一括.jpg保存しちゃえばいいんじゃない?」と思われる方もいるかもしれません。
しかし、
「最新の国試問題に合わせて、統計データを修正したい」
「もともとある図版の、この部分だけほしい」
など、一部改変が生じるため、どうしても人の手が必要になります。
ファイル名も、書籍データとは別のルールで命名することになるため、手作業が発生します。
また、「みえる系」図版の.aiファイルは紙面サイズ=B5に合わせて、B5のアートボート上で制作されています。このため、流用する図版のアートボードサイズを調整するという作業が生じます。

そこで、作業手順を整理して、部分的にJavaScriptで自動化できないかな?と考えました。
手順を整理して、ChatGPTでスクリプト化
手順
各書籍の本文組版データから、必要な図版のaiファイルをローカルに取り出す。
編集者の赤字指示をもとに、データを修正する。
オブジェクト全体の天地左右サイズ +3ptにアートボードサイズを調整する。
※理由:オブジェクトとアートボードサイズをぴったり合わせてしまうと、.jpg保存したときに端が切れることがあるため、余白をもたせる。編集者から指示のあったファイル名で保存する。
「ファイル>web用に保存」から、「JPEG、最高画質、画像サイズ%400、アートボードサイズでクリップに✓」の条件で書き出す。
「4」の.aiファイルと「5」の.jpgファイルを指定のフォルダに保管する。
このうち、「3〜6」を自動化するべく、ChatGPTにスクリプトを書いてもらいました。
プロンプト
Adobe Illustratorで動作する下記のようなJavaScriptを作成してください。
【要旨】
Illustratorファイルのアートボードサイズを適宜調整し、高解像度のJPEG画像で別名保存する。
【要件】
Illustratorで、現在開いているaiファイルに対して下記の操作を行う。
●アートボードを「オブジェクト全体」のサイズに合わせる。
●上記操作の後、アートボードを天地左右ともに中心から3ptずつ広げる。
●保存用の新規フォルダを作成する。新規フォルダ名とファイル名を入力するためのダイアログが立ち上がる。
●書き出し>WEB用に保存で、「JPEG」「最高画質(画質100%)」「アートに最適」「変更後のサイズ:400%」「アートボードサイズでクリップ」の条件で、.aiファイルと同じ階層に保存する。
●新規フォルダと、アートボードサイズを調整したaiファイル、書き出したJPEGファイルの名前は全て同じになる。
たとえば、ダイアログに「240614」と入力すると、240614という名前の新規フォルダが生成され、その中に「240614.ai」と「240614.jpg」が保存される。
生成されたJavaScript
var doc = app.activeDocument;
// アートボードをオブジェクト全体のサイズに合わせる
doc.artboards[doc.artboards.getActiveArtboardIndex()].artboardRect = doc.visibleBounds;
// アートボードを天地左右ともに中心から3ptずつ広げる
var activeAB = doc.artboards[doc.artboards.getActiveArtboardIndex()];
var artboardLeft = activeAB.artboardRect[0];
var artboardTop = activeAB.artboardRect[1];
var artboardRight = activeAB.artboardRect[2];
var artboardBottom = activeAB.artboardRect[3];
var newArtboardRect = [
artboardLeft - 3,
artboardTop + 3,
artboardRight + 3,
artboardBottom - 3
];
activeAB.artboardRect = newArtboardRect;
// ダイアログで保存先フォルダを取得
var saveFolder = Folder.selectDialog("保存先フォルダを選択してください");
if (saveFolder != null) {
// JPEG保存オプションを設定
var saveOptions = new ExportOptionsJPEG();
saveOptions.qualitySetting = 100;
saveOptions.artBoardClipping = true;
saveOptions.verticalScale = 400;
saveOptions.horizontalScale = 400;
saveOptions.antiAliasing = true;
saveOptions.optimization = true;
// ファイル名を取得
var fileName = prompt("ファイル名を入力してください", "");
if (fileName != null && fileName != "") {
// JPEG保存用のフォルダを作成
var saveFolderPath = saveFolder.fsName + "/" + fileName;
var saveFolderJPEG = new Folder(saveFolderPath);
if (!saveFolderJPEG.exists) {
saveFolderJPEG.create();
}
// aiファイルの保存
var aiFile = new File(saveFolderPath + "/" + fileName + ".ai");
doc.saveAs(aiFile);
// アートボード毎にJPEG書き出し
for (var i = 0; i < doc.artboards.length; i++) {
doc.artboards.setActiveArtboardIndex(i);
var exportFile = new File(saveFolderPath + "/" + fileName + ".jpg");
doc.exportFile(exportFile, ExportType.JPEG, saveOptions);
}
alert("aiとJPEGが保存されました!");
}
}

エラーが出るのでスクリプト修正のために再度プロンプト入力→スクリプト再生成→
…を5往復ほどしています。
このスクリプトを実際に使ったところ、図版1点あたりの書き出し時間が数分から20秒ほどに短縮されたので、「みえる系」書籍制作と並行して作業しながらポンポンと納品できるようになりました。
便利にはなった、けど…
しかし、このスクリプトにも欠点はあります。一つは、
アートボード外に不要なオブジェクトが残っていた場合、それも含めてアートボードサイズが調整されてしまう
というものです。
社内コンテンツへの流用が多い「みえる系」書籍では、校了後のデータチェックでアートボード外のオブジェクトを削除するルールにしています。そのため、発行済みの書籍ではこの問題は発生しませんが、校了前はアートボード外に作りかけのイラストや素材を置いておくことがあるため、制作中の書籍から流用する場合は問題になることがあります。
というわけで、アートボード外のオブジェクトを一発で削除するスクリプトも作りました。ChatGPTいわく「Adobe IllustratorのAPIにはアートボード外のオブジェクトを取得するための関数が存在しない」とのことで、まわりくどいやり方になっているようです。
// アクティブなドキュメントを取得する
var doc = app.activeDocument;
// アートボードの範囲を取得する
var artboardRect = doc.artboards[doc.artboards.getActiveArtboardIndex()].artboardRect;
// ドキュメント内の全てのオブジェクトを検査する
for (var i = doc.pageItems.length - 1; i >= 0; i--) {
var item = doc.pageItems[i];
// オブジェクトの座標を取得する
var itemBounds = item.geometricBounds;
// オブジェクトがアートボード内にあるかどうかを確認する
if (itemBounds[0] < artboardRect[0] || itemBounds[1] > artboardRect[1] || itemBounds[2] > artboardRect[2] || itemBounds[3] < artboardRect[3]) {
// アートボード外にあるオブジェクトを削除する
item.remove();
}
}
もう一つの欠点は、
クリッピングマスクが適用されたオブジェクトは、マスクの内側のオブジェクトの天地左右サイズを拾ってしまう
というものでした。これについてはスクリプトを修正できなかった(エイリアンが力尽きた)ので、そこだけ手作業で対応しました。解決策をご存知の方はぜひコメントで教えてください。

今回ご紹介したように、MIGのメンバーは自分たちの業務を効率化するため、自動組版やJavaScriptによる自動化を日々検討しています。
▼関連記事もぜひ読んでみてください。
