2
1

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 3 years have passed since last update.

PDFファイル解析にあたって2 PDF.jsの実装

Last updated at Posted at 2021-01-24

書いたこと

PDFファイルの解析にあたって、PDF.jsの実装をまとめる。

PDF.jsの解析手順

  1. streamオブジェクトの生成
  2. ヘッダーを解析
  3. startxrefの値の読み取り
  4. 相互参照テーブルの取得
  5. カタログ辞書の取得

PDFDocument.png

0. streamオブジェクトの生成

物理的なPDFファイルデータはstreamオブジェクトとして抽象化されている。
これによってデータが必要になった際にファイルデータを随時取得が行えるようになっている。

1-4. ドキュメントのグラフ階層の生成

src/core/worker.js
async function loadDocument(recoveryMode) {
  await pdfManager.ensureDoc("checkHeader");            // 1. ヘッダー情報の取得
  await pdfManager.ensureDoc("parseStartXRef");         // 2. startxrefの解析
  await pdfManager.ensureDoc("parse", [recoveryMode]);  // 3-4. 相互参照テーブルとカタログ情報の取得

  if (!recoveryMode) {
	// Check that at least the first page can be successfully loaded,
	// since otherwise the XRef table is definitely not valid.
	await pdfManager.ensureDoc("checkFirstPage");
  }

  const [numPages, fingerprint] = await Promise.all([
	pdfManager.ensureDoc("numPages"),
	pdfManager.ensureDoc("fingerprint"),
  ]);
  return { numPages, fingerprint };
}

PDF.jsの構文解析と字句解析

<<  /Type /Annot
	/Subtype /Link
	/F 4
	/Border [0 0 0]
	/Rect [255.99998 189.7099 467.49997 206.2099]
	/A <</Type /Action
		/S /URI
		/URI (https://doc.rust-lang.org/stable/book/)
	    >>
>>

字句解析

字句解析にかけることによって以下のトークン列に変換する

pdfオブジェクトトークン列.png

src/core/perser.js
  getObj() {

    // Start reading a token.
    switch (ch | 0) {
      case 0x30: // '0'
      case 0x31: // '1'
      case 0x32: // '2'
      case 0x33: // '3'
      case 0x34: // '4'
      case 0x35: // '5'
      case 0x36: // '6'
      case 0x37: // '7'
      case 0x38: // '8'
      case 0x39: // '9'
      case 0x2b: // '+'
      case 0x2d: // '-'
      case 0x2e: // '.'
        return this.getNumber();  // 数字トークンを取得
      case 0x28: // '('
        return this.getString();  // 文字列トークンを取得
      case 0x2f: // '/'
        return this.getName();    // 名前トークンを取得
      // array punctuation
      case 0x5b: // '[
        this.nextChar();
        return Cmd.get("[");      // Cmd("[") トークンを取得
      case 0x5d: // ']'

構文解析

トークン列からプログラミング言語の型に変換する

構文解析結果.png

  1. << から辞書を生成する
  2. >> までキーと値を交互に設定していく

2を繰り返すことで、トークン列から辞書インスタンスを得ることが出来る。

構文解析結果.js
{ 
	Name("Type"): Name("Annotate"),
	Name("SubType"): Name("Link"),
	Name("F"): 4,
	Name("Border"): [0, 0, 0],
	Name("Rect"): [255.99998, 189.7099, 467.49997, 206.2099],
	Name("A"): {
			Name("Type"): Name("Action"),
			Name("S"):	Name("URI"),
			Name("URI"): "https://doc.rust-lang.org/stable/book/",
		}
}
2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?