Home About Contact
InDesign , ExtendScript , Node.js

InDesign ExtendScript で現在開いているドキュメントから画像やテキストを抽出する

久しぶりに ExtendScript を書く機会があったのですが、 処理させたいことのひとつが InDesignドキュメントにある画像全部を JPEG 保存することでした。 面倒かと思ったのですが、予想外に簡単だったのでコードをメモしておきます。

画像をJPEGファイルに書き出す

doc.allPageItems から 画像のページアイテムを見つけて、 そこにリンクしている実体画像のファイル名をつかって JPEG 保存しています。

// main.js

require("extendscript-es5-shim")
const _ = require("./node_modules/underscore/underscore-node.cjs")

const console = {};
console.log = (text)=>{ $.writeln(text) }


const doc = app.activeDocument
console.log(doc)

_.chain(doc.allPageItems)
  .filter((pageItem)=> pageItem.constructor.name=="Image" )
  .each((pageItem, index)=>{
    const link = pageItem.itemLink

    /*
    const currentDir = File($.fileName).parent
    const filename = `${currentDir}/${index}_${link.name}.jpg`
    */

    const filename = `${Folder.desktop}/${index}_${link.name}.jpg`
    console.log(filename)

    if( pageItem.parent!=null ){
      pageItem.parent.exportFile(ExportFormat.JPG, File(filename))
    } else {
      pageItem.exportFile(ExportFormat.JPG, File(filename))
    }
  })

もちろん、このコードそのままでは ExtendScript として作動しないので変換が必要です。 その辺は、 このエントリー(電子書籍「Node.js による InDesign ExtendScript モダン開発入門2024」をリリース)をご覧ください。 ExtendScript への変換のための Node.js プロジェクトをつくるのは手間ですが、初回だけなのでそこは我慢しましょう。 これでコードを現代風にJSスタイルでシンプルに書くことができる。

なお、画像は Desktop に export されます。

ここでは見つけてきた Image オブジェクトである pageItem そのものでなく、その親の pageItem.parent を使って JPEG画像を書き出ししています。 これは pageItem (Image オブジェクト) をそのまま保存するより、 pageItem.parent (Rectangle オブジェクト) を exportFile して JPEG 保存した方がたいていの場合都合がよいからです。 なぜなら画像自体ではなくその外側(parent)にある Rectangle オブジェクトであれば、InDesign 上で(その Rectangle を使って設定している)トリミング位置が維持できるから。

ただし、この方法で JPEG を作成すると画像サイズが小さくなりすぎるという問題があります。 回避方法は別の機会に書きます、たぶん。

テキストフレームのコンテンツを全部書き出す

同じようにして、ドキュメント中の TextFrame 内のコンテンツを全部書き出すのも簡単です。

require("extendscript-es5-shim")
const _ = require("./node_modules/underscore/underscore-node.cjs")

const console = {};
console.log = (text)=>{ $.writeln(text) }

const doc = app.activeDocument
console.log(doc)

const allContents = _.chain(doc.allPageItems)
  .filter((pageItem)=> pageItem.constructor.name=="TextFrame" )
  .map((textFrame)=>{
      return textFrame.contents
  }).value().join(",")

console.log(allContents)

さらに JSONとして書き出すのも簡単です。

require("extendscript-es5-shim")
const _ = require("./node_modules/underscore/underscore-node.cjs")

const console = {};
console.log = (text)=>{ $.writeln(text) }

const doc = app.activeDocument
console.log(doc)

const textList = _.chain(doc.allPageItems)
  .filter((pageItem)=> pageItem.constructor.name=="TextFrame" )
  .map((textFrame)=>{
      return { text: textFrame.contents }
  }).value()

console.log(JSON.stringify({"textList": textList }))

以上です。