PDFの構造について3

日曜日にお買い物に出たんですが、駐車場で追突されてしまって(x_x;

対応で時間取られてあっぷあっぷでした。また微妙な壊れ方なんですけど、見積り取るとそれなりの修理費で自身も注意して運転しようと思った次第です。

今回は第3章で内容的にはPDFのデータを記述する時の文法的なものになります。まだまだお約束事の説明に終始するわけですが、これも最低限必要な知識となりますのでお付き合いください。

シンタックス(3)

この章では、オブジェクト、ファイル、およびドキュメントレベルでのPDFの構文について解説します。これはPDFファイルのコンテンツがページ定義、インタラクティブナビゲーション支援、およびアプリケーションレベルでの論理構造としてどのように解釈されるかを説明する以降の章の基礎となる情報です。

PDF構文は、以下に示す4つの部分で考えると最もよく理解できます。

•オブジェクト
PDFドキュメントは、基本的なタイプのデータオブジェクトの小さなセットで構成されるデータ構造であり、3.1シンタックスの項目では、オブジェクトやその他の構文要素の記述に使用される文字セットについて説明します。セクション3.2「オブジェクト」では、オブジェクトの構文と基本的なプロパティについて説明します。セクション3.2.7「ストリームオブジェクト」は、最も複雑なデータ型であるストリームオブジェクトの完全な詳細を説明します。

•コンテンツストリーム
PDFコンテンツストリームには、ページまたはその他のグラフィック実体の外観を構成する一連のコマンドが含まれています。これらのコマンドは、オブジェクトとしても表されますが、ドキュメント構造を表すオブジェクトとは概念的に異なり、個別に説明されています。セクション3.7「コンテンツストリームとリソース」では、PDFコンテンツストリームとそれに関連するリソースについて説明します。

•ドキュメント構造
PDFドキュメント構造は、基本的なオブジェクトタイプを使用してPDFドキュメントのコンポーネント(ページ、フォント、注釈など)を表す方法を指定します。セクション3.6「ドキュメント構造」では、ドキュメント構造全体について説明します。後の章では、コンポーネントについて詳説します。

•ファイル構造
PDFファイル構造は、オブジェクトがPDFファイルに保存される方法、オブジェクトへのアクセス方法、およびオブジェクトの更新方法を決定します。この構造は、オブジェクトのセマンティクスとは無関係です。 3.4項「ファイル構造」では、ファイル構造について説明します。 3.5項「暗号化」では、ドキュメントのコンテンツを不正アクセスから保護するためのファイルレベルのメカニズムについて説明します。

※体系的にまとめられた構造のようにも読めますが、実際には各種コンポーネントがオブジェクトの組み合わせによりストリームがオブジェクトとしてあつかわれたりします。実体は思うより複雑怪奇です。

さらに、この章では、基本オブジェクトから構築され非常に広く使用されているため、それ自体が基本オブジェクトタイプとほぼ見なすことができるいくつかのデータ構造についても説明します。これらのオブジェクトは、セクション3.8「一般的なデータ構造」で解説されます。
PDFのオブジェクトとファイルの構文は、他のファイル形式の基礎としても使用されます。これには、8.6.6項「フォームデータフォーマット」で説明されているフォームデータフォーマット(FDF)、およびアドビテクニカルノート#5620「ポータブルジョブチケットフォーマット」で説明されているポータブルジョブチケットフォーマット(PJTF)が含まれます。

シンタックス(3.1)

最も基本的なレベルでは、PDFファイルは8ビットのバイトシーケンスです。これらのバイトは、以下で説明する構文規則に則ってトークンにグループ化可能です。1つ以上のトークンが組み合わされて、PDFドキュメントを構成する基本的なデータ単位であるオブジェクトの高レベルの構文エンティティが形成されます。
PDFは、ASCII文字セットで表示・印刷可能なサブセットに対応するバイト値に加えて、スペース、タブ、キャリッジリターン、ラインフィードなどの空白文字を使用して完全に表すことができます。

利用されるデータ形式
PDFでは128文字の特定のセットを2進数としてエンコードします。ただし、PDFファイルはASCII文字セットに制限されません。次のルールに従って、任意の8ビットバイトを含めることができます。

  • オブジェクトを区切り、PDFファイルの構造を説明するトークンは、標準のディクショナリでキーとして使用されるすべての予約語と名称も含め、すべてASCII文字セットで記述されます。
  • 特定タイプのオブジェクト(文字列やストリーム)のデータ値は、必要であれば完全にASCIIキャラクタを用いて記述することができます。ビットマップ画像など、元来バイナリであるデータについてもASCIIキャラクタを用いたエンコーディングを利用可能ですが、ファイル容量と効率のためにバイナリで直接記述するのが一般的です。
  • バイナリデータを含むPDFファイルは、ファイルのすべてのバイトを忠実に保存する為にテキストファイルではなくバイナリファイルとして転送および保存する必要があります。このようなファイルは、予約文字コード、最大行長、行末規則、またはその他の制限を課す利用環境に移植できません。

注:この章では、文字という用語はバイトと同義であり、特定の8ビット値を指します。この使用法は、人間が読めるテキストの表現やフォントからのグリフの選択など、特定のコンテキストでデータとして扱われるときに値が持つ可能性のある論理的な意味とは異なります。

 

文字セット(3.1.1)

PDF文字セットは、通常文字、区切り文字、および空白文字と呼ばれる3つのクラスに分けられます。この分類は、文字列、ストリーム、およびコメント内を除いて、文字のトークンへのグループ化を決定し、それらの文脈において異なるルールが適用されます。
下表に示す空白文字は、名称や数字などの構文構造を互いに分離します。コメント、文字列、およびストリームを除いて、すべての空白文字は同等であり、他のすべてのコンテキストでは、PDFは連続する空白文字のシーケンスを1つとして扱います

10進数16進数8進数名称
000000Null(NUL)
909011Tab(HT)
100A012Line feed(LF)
120C014Form feed(FF)
130D015Carriage return(CR)
3220040Space(SP)

 

CRやLFは改行コードと呼ばれ、EOL(end of line)マーカーとして機能します。Windowsの改行コードのようにCRの後にLFが続く場合もEOLとして処理されます。多くの場合これらの改行コードも単なる空白文字として取り扱われますが、次のトークンを行の先頭に配置する為にEOLを利用する必要がある場合もあります。

注:Adobe社がリリースしているPDFリファレンスのサンプルコードでは、各トークンを読みやすくする目的で改行処理やインデント処理を加えています。実際のドキュメントではこの様な構造は容量増等のデメリットがあり、推奨される表記ルールではないことに留意ください。当該サイトにおいても可読性を優先した表記となっていることにご注意ください。

区切り文字「()<>[]{}/」および「」は文字列、配列、名称、コメントなどの構文エンティティの構造を組み立てます。これらの文字はいずれも、その前のエンティティを終了し、エンティティには含まれません。空白文字と区切り文字を除くすべての文字は、通常の文字と呼ばれます。これらの文字には、ASCII文字セットの外にある8ビットのバイナリ文字が含まれます。連続する通常の文字のシーケンスは、単一のトークンで構成されます。また、PDFでは大文字と小文字が区別されます。

 

コメント(3.1.2)

文字列またはストリーム外に%(パーセント)が出現すると、コメントとみなされ、パーセント記号から始まりEOLキャラクタまでに配置されたキャラクタがコメントとして処理されます。コメントには通常の文字、区切り文字、スペース文字、およびタブ文字を含含めることができます。PDFを取り扱うアプリケションはコメントを無視し、コメントを単一の空白文字と同様に取り扱い、その前のトークンとその後ろのトークンを区切ります。

abc% comment { /% ) hoge hoge fuga
123

上記の例は構文的には、「abc 123」に相当します。

後述のファイル構造で解説されるヘッダ及びフッタに利用される%PDF及び%%EOFを除きコメントにはファイル構造的には意味がありません。また、PDFファイルを生成するアプリケーションによって必ず保存されるとは限りません。また、PostScriptのDSC(ドキュメント構造化規則)に相当する仕組みはPDFにはありません。

 

オブジェクト(3.2)

PDFがサポートする基本的なオブジェクトには以下のようなものがあります。

  • 真偽値(Boolean)
  • 数値(整数/Integer又は実数/Real)
  • 文字列(String)
  • Name(Names)
  • 配列(Arrays)
  • ディクショナリ(Dictionaries)
  • ストリーム(Streams)
  • ヌルオブジェクト(Null)

オブジェクトは他のオブジェクトから参照する為のラベルを付加できます。ラベル付けされたオブジェクトは、間接(インダイレクト)オブジェクトと呼ばれます。
この章では各オブジェクトの生成方法と参照の方法を解説します。

 

真偽値(Boolean)(3.2.1)

真偽値は「true」と「false」の2つのキーワードで表されます。真偽値は主に配列要素やディクショナリエントリの値として利用されます。また、PostScript関数では、boolean演算子と関係演算子の結果として、又は条件演算子ifやifelseのオペランドとして利用されます。

 

数値オブジェクト(3.2.2)

PDFでは、整数と実数の2種類の数値オブジェクトが存在します。整数オブジェクトは、0を中心とする特定の範囲内の数学的整数を表します。実数オブジェクトは数学的実数と似ていますが、その取りうる範囲と精度に制限があります。これらは通常、浮動小数点形式ではなく固定小数点形式で表されます。数値の範囲と精度は、PDFを取り扱うアプリケーションが実行されているコンピューターで使用される内部表現によって制限されます。

整数は、1つ以上の数字で記述され符号を付加することができます。

123
43445
+17
−98
0

値は符号付き10進整数として解釈され、整数オブジェクトに変換されます。整数の実装制限を超えると、実数オブジェクトに変換されます。
実数値は、符号とピリオド(小数点)と1つ以上の数字で記述されます。PDFでは1.0未満の実数値は頭の0を省略しピリオドから始まります。

34.5
−3.62
+123.6
4.
−.002
0.0

値は実数として解釈され、実数オブジェクトに変換されます。実数の実装制限を超えるとエラーが発生します。

注:PDFではPostScript構文で利用される16進数等の非10進基数(16#FFFEなど)や指数表現(6.02E23など)をサポートしません。

PDFレファレンスでは、数値という用語はタイプが整数または実数のいずれかであるオブジェクトを指します。実数が予想される場合にも整数が利用可能で、自動的に実数値に変換されます。たとえば、実数値「1.0」は通常「1」と記述されます。

 

文字列オブジェクト(3.2.3)

文字列オブジェクトは、一連のバイト(0〜255の範囲の符号なし整数値)で構成されます。文字列オブジェクトは整数オブジェクトではありませんが、よりコンパクトな形式で格納されます。文字列の長さは、実装上の制限の対象となる場合があります。
文字列オブジェクトは、次の2つの方法で記述できます。

  • 括弧「()」で囲まれたリテラル文字のシーケンスとして
  • 山括弧「<>;」で囲まれた16進表記の文字コードとして

このセクションでは、文字列をバイトシーケンスとして書き込むための基本的な構文についてのみ説明します。文字列はさまざまな目的に使用可能であり、さまざまな方法でフォーマット可能です。
文字列が特定の目的(たとえば、日付を表すため)に使用される場合、その目的のためのフォーマットがあると便利ですが、このようなフォーマットは、文字列の内容を解釈するための単なるルールであって、個別のオブジェクトタイプではありません。
特定のフォーマットの利用については、フォーマットを利用するする文字列オブジェクトの定義で解説します。

 

リテラル文字列

リテラル文字列は、括弧で囲まれた任意の数の文字として記述されます。リテラル文字列に利用可能なキャラクタは、いわゆるシングルバイトキャラクタであり、ASCIIコードに含まれるキャラクタと考えてよいでしょう。ただし、別途特殊な処理が必要なキャラクタも存在します。
次の文字列はいずれも正しく認識されます。

(This is a string)

(Strings may contain newlines
and such . )

(Strings may contain balanced parentheses ( ) and special characters (* ! & } ^ % and so on).)
% balanced parentheses = 両方揃ったパーレン

(The following is an empty string.) ※空の文字列で、文字列長は0となります。
()

リテラル文字列内では、バックスラッシュ(\)は、改行文字等の制御文字、閉じられていない(片方だけの)括弧など片方だけのパーレン、またはバックスラッシュ文字自体を文字列に含めるなど、さまざまなケースでエスケープ文字として使用されます。
バックスラッシュの直後の文字によってそのキャラクタが何かを判断しますが、バックスラッシュに続く文字が意味をなさない場合、バックスラッシュは無視されます。

  • \n ……Line feed (LF)
  • \r ……Carriage return (CR)
  • \t ……Horizontal tab (HT)
  • \b ……Backspace (BS)
  • \f ……Form feed (FF)
  • \( ……カッコ
  • \) ……閉じカッコ
  • \\ ……バックスラッシュ
  • \ddd ……文字コードddd (8進数)

リテラルが長くなる場合で改行が含まれない場合でもリテラルを折り返すことが可能です。そのような場合、折り返した部分にバックスラッシュを配置しEOLをエスケープします。

(These \
two strings \
are the same . )

(These two strings are the same .)

EOLマーカーの前にバックスラッシュなしでリテラル文字列内に表示される場合の結果は「\n」と等価です。この場合でもEOLに利用される制御文字の違いによる相違はありません。

(This string has an end−of−line at the end of it .
)
( So does this one .\n )

\dddエスケープシーケンスは、印刷可能なASCIIコード外のキャラクタを表す方法を提供します。

(This string contains \245two octal characters\307 .)

数値dddは、1桁、2桁、または3桁の8進数で構成され、上位オーバーフローは無視されます。文字列の次の文字も数字である場合は、必要に応じて先行ゼロを使用して、3桁の8進数を使用する必要があります。
たとえば、

(\0053)

は、\005(Control-E)の後に「3」が続く2つの文字を含む文字列を示しますが、(\053)又は(\53)は単一のキャラクタである+(プラス記号)になります。

この表記により、ASCII文字のみを使用して7ビットASCII文字セット範囲外のキャラクタが指定可能となります。

日本語の例

(\003K\003M\003O\003Q\003S)

8進数と続くアルファベットでcmapを構成します。
頭の8進数部分はいずれも3で16進数に変換しても0x3となり、続くキャラクタの文字コードとつなげて…

0x34B 0x34d 0x34f 0x351 0x353

となります。これを10進数に変換すると

843 845 847 849 851

となり、サブセット化されたCIDテーブルを参照すると

U+3042 U+3044 U+3046 U+3048 U+304A

が得られます。このサンプルのテキストは「あいうえお」ですが、実際にPDFにレンダリングされるキャラクタは埋め込まれたフォントのcharstringから得られるグリフがピックアップされます。

 

16進文字列

文字列は16進形式で記述することもできます。これは、PDFファイルに任意のバイナリデータを含める場合に利用されます。16進文字列は、山括弧で囲まれた16進数字(0〜9およびA〜Fまたはa〜fのいずれか)のシーケンスとして記述されます。

(< and >):
< 4E6F762073686D6F7A206B6120706F702E >

16進数の各ペアは、文字列の1バイトを定義します。空白文字(スペース、タブ、キャリッジリターン、改行、フォームフィードなど)は無視されます。
16進数で表現されるコードは常に2つがペアになりますが、16進文字列が奇数で与えられた場合ペアを構成するために最後尾に0を付加します。

<901FA3>

は、16進コードが0x90、0x1F、および0xA3の文字で構成される3バイトの文字列ですが、

<901FA>

は、16進コードが0x90、0x1F、および0xA0の文字を含む3バイトの文字列となります。

 

3.2.4 Nameオブジェクト

Nameオブジェクトは、一連の文字によって一意に定義されるアトミックシンボルです。一意に定義されているということは、同じ文字シーケンスで構成されている2つのNameオブジェクトがまったく同じオブジェクトであることを意味します。
アトミックとは、Nameオブジェクトは内部に副次的な構造を含まないことを意味します。スラッシュ文字(/)はNameオブジェクトを宣言する接頭辞を表します。スラッシュはNameオブジェクトの一部ではありませんが、次のテキストシーケンスがNameオブジェクトを構成することを明示します。接頭辞であるスラッシュとNameオブジェクトの最初の文字の間に空白文字を含めることはできません。同様にNameオブジェクトには通常の文字を含めることができますが、区切り文字や空白文字を含めることはできません。Nameオブジェクトは大文字と小文字を区別するケースセンシティブな文字列であり、/Aと/ aは異なるNameオブジェクトとなります。
次の例は、有効なリテラルNameオブジェクトです。

/Name1
/ASomewhatLongerName
/A;Name_With−Various***Characters?
/1 . 2
/$$
/@pattern
/. notdef

注:スラッシュの後に通常の文字がない/(スラッシュ)だけのトークンも有効なNameオブジェクトです。
PDF 1.2以降、#(番号記号文字)を前に付けた2桁の16進コードを記述することにより、null(文字コード0)以外の任意の文字をNameオブジェクトに含めることができます。この構文は、区切り文字または空白文字、あるいは「#」自体を表すために必要となります。
コードが33(!)から126(〜)の範囲外の文字には推奨されますが、必須ではありません。以下に示されている例は、PDF1.2以降の有効なリテラル名です。

リテラルName オブジェクト結果
/Adobe#20Green Adobe Green
/PANTONE#205757#20CV PANTONE 5757 CV
/paired#28#29parentheses paired()parentheses
/The_Key_of_F#23_Minor The_Key_of_F#_Minor
/A#42 AB

Nameオブジェクトの長さには、実装上の制限があります。制限はNameオブジェクトの内部表現の文字数に適用されます。たとえば、name/A#20Bには、6文字ではなく4文字(/、A、スペース、B)となります。
通常、Nameオブジェクトを構成するバイトは、PDFを表示するアプリケーション上でレンダリングされるテキストとして扱われることはありません。

ただし、上の例のようにフォント名や構造タイプを表すものなど、Nameオブジェクトをテキストとして扱う必要がある場合があります。このような状況では、バイトシーケンスがUTF-8で書き込まれている可能性があります。UTF-8は、印刷可能なASCII文字がと同じ表現を持つUnicodeの可変長バイトコード表現です。 これにより、Nameオブジェクトは長さの実装制限に従って、任意の自然言語でテキストを表すことができます。
注:PDFは、外部で指定されたテキストの特定の部分をNameオブジェクトとして表すためにUTF-8シーケンスを規定していません。場合によっては、複数のUTF-8シーケンスが同じ論理テキストを表すことがあります。異なるバイトシーケンスで定義されたNameオブジェクトは、UTF-8シーケンスの外部解釈が同じである場合でも、PDFでは別個のNameオブジェクトを構成します。
※PDFでは、true、false、objなどのキーワードとは異なり、Nameオブジェクトは常にスラッシュ文字(/)で始まります。PDF Referenceでは、本文や表での表記の際に先頭にスラッシュを付けない場合があります。当サイトにおいてもソース記述を除く部分ではNameオブジェクトであると認識できない場合を除いてスラッシュの表示を省略します。たとえば、TypeとFullScreenは、PDFファイルおよびPDF Referenceのコード例においてに実際にPDFに書き込まれる文字列として/Typeおよび/FullScreenを示しています。

 

3.2.5 配列オブジェクト

配列オブジェクトはオブジェクトを順番に配置した1次元コレクションです。 PDFでは配列に対して数値、文字列、ディクショナリ、または他の配列を含む他のオブジェクト異なる種類のオブジェクトを収容することができます。
配列内の要素の数は、実装上の制限の対象となります。 配列は、ブラケット([])で囲まれたオブジェクトのシーケンスとして記述されます。

[ 549 3.14 false ( Ralph ) /SomeName ]

上の例では整数・実数・真偽値、リテラル、Nameといったオブジェクトが一つの配列に収容されています。
PDFでは基本的に1次元配列が利用されますが、2次元配列等の高次元配列は配列を入れ子上にすることで実現できます。

3.2.6 ディクショナリオブジェクト
ディクショナリオブジェクトは、ディクショナリ・エントリと呼ばれるオブジェクトとその値のペアで構成される連想テーブルです。 各エントリの第1要素はキーで、第2要素は値です。 キーはNameオブジェクトである必要があります。 値は、他のディクショナリを含む、任意の種類のオブジェクトが利用可能です。 値がnullのディクショナリエントリは、エントリエントリ自体が無いものと認識されます。ディクショナリ内のエントリの数は、実装制限の対象となります。
注:同じディクショナリ内において、2つ以上のエントリが同じキーを持つことはできません。 キーが複数回表示される場合、その値はundefinedとなります。
ディクショナリは、二重山括弧(<<…>>)で囲まれた一連のキーと値のペアとして記述されます。
例えば:

<<
/Type /Example
/Subtype /DictionaryExample
/Version 0 . 01
/IntegerItem 12
/StringItem ( a string )
/Subdictionary
<<
/Item1 0 . 4
/Item2 true
/LastItem ( not ! )
/VeryLastItem ( OK )
>>
>>

注:二重山括弧を、16進文字列を区切る単一山括弧(<>)と混同しないよう注意が必要です。ディクショナリオブジェクトは、PDFドキュメントの重要な構成要素です。これらは通常、フォントやドキュメントページなどの複雑なオブジェクトの属性を収集し結合するために使用され、ディクショナリの各エントリはNameと値を指定します。上に示した例のように多くのディクショナリのTypeエントリは、ディクショナリ自身が記述するオブジェクトのタイプを示します。場合によっては、サブタイプエントリ(Sと省略されることもあります)を使用して、一般的な特殊なサブカテゴリをさらに識別します。 TypeまたはSubtypeエントリの値は常にNameです。たとえば、フォントディクショナリでは、Typeエントリの値は常にFontですが、Subtypeエントリの値はType1、TrueType、またはその他のいくつかの値のうちの1つです。
Typeエントリの値は、ほとんどの場合、コンテキストから推測可能です。たとえば、Tf演算子のオペランドは、フォントオブジェクトである必要があります。フォントディクショナリのTypeエントリは、主にドキュメントおよびエラーチェックの情報として機能します。特に必須の指定が無い限り、Typeエントリは本来必要ありません。ただし、エントリ自体が存在する場合は、正しい値である必要があります。ディクショナリのTypeエントリの値は、メタデータやプライベートデータであっても、Adobe社が提供するPDF Refarences1.7にて定義されている名前または登録名である必要があります。

 

3.2.7 ストリームオブジェクト

文字列オブジェクトのようなストリームオブジェクトは、バイト・シーケンスで構成されます。 ただし、PDFアプリケーションはストリームを段階的に読み込み可能ですが、ストリーム全体を読み取る必要があります。 また、文字列オブジェクトには実装上の制限がありまが、ストリームオブジェクトには制限はありません。 そのため、画像やページ構成など、大量のデータが含まれる可能性のあるオブジェクトはストリームとして表されます。
注:文字列オブジェクトと同様に、このセクションでは、ストリームをバイトのシーケンスとして書き込むための構文についてのみ解説します。 これらのバイトが何を表すかは、ストリームが参照されるコンテキストによって決まります。
ストリームは、ディクショナリと、それに続くキーワードstreamとendstreamで囲まれた0バイト以上のブロックで構成されます。

dictionary
stream
… Zero or more bytes …
endstream

すべてのストリームは間接オブジェクトである必要があり、ストリームディクショナリは直接オブジェクトである必要があります。ストリームディクショナリに続くキーワードstreamの後には、CR(キャリッジリターン)だけではなく、CRとLF(ラインフィード)、またはLFのみで構成される行末マーカーを続ける必要があります。ストリームを構成するバイトのシーケンスは、streamキーワードとendstreamキーワードの間にあります。ストリームディクショナリは、正確なバイト数を指定します。データの後、endstreamの前に行末マーカーを配置することを推奨します。このマーカーはストリームの長さに含まれていません。
または、PDF 1.2以降では外部ファイルに含めることができます。この場合、ストリームディクショナリでファイルが指定され、streamとendstreamの間のバイトはすべて無視されます。

注:streamキーワードに続ける行末マーカーにCR単体を利用できないという制限は、そのストリームがLFを行末マーカーとして利用していた場合において、streramキーワードの後にCRが配置された場合に意図せずCR-LFシーケンスが成立する為にstreamのEOLを誤認する可能性がある為です。

 

ストリーム範囲

すべてのstremディクショナリには、streamのデータに使用されるPDFファイルのバイト数を示すLengthエントリが存在します。(streamにフィルターがある場合、Lengthはエンコード後のバイト数となります)さらに、ほとんどのフィルターは、明示的なEnd Of Data(EOD)マーカーがデータの範囲を区切るエンコードスキームを利用するよう定義されています。最後に、ストリームは、属性から長さを推測できる多くのオブジェクトを表すために使用されます。これらの制約はすべて一貫している必要があります。
たとえば、単一のカラーコンポーネント(グレースケール)又はコンポーネントごとに8ビットを使用する10行✕20列の画像には、正確に200バイトのバイトデータが必要となります。ストリームがフィルターを使用する場合、PDFファイルにはそれらの200バイトを生成するのに十分なバイトのエンコードされたデータが必要であり、データ長の不足、EODマーカーの発生が早すぎる、またはデコードされたデータにおいて必要なデータが含まれていない場合はエラーが発生します。
また、streamに含まれるデータが多すぎる場合もエラーとなります。ただし、PDFファイルのendstreamキーワードの前に余分な行末マーカーがある場合があります。

Length(Integer/Required)
streamキーワードに続く行の先頭から、endstreamキーワードの直前の最後のバイトまでのバイト数。(endstreamの前に、カウントに含まれず、論理的にstreamデータの一部ではない追加のEOLマーカーが存在する場合があります。)詳細については、前述の「ストリーム範囲」を参照してください。

Filter(Name・Array/Option)
streamの処理に適用されるフィルタの名称。複数のフィルタ―が適用されている場合、適用された順序でNameオブジェクトを配列に収容します。

DecodeParms(Dictionary・Dictionary Array/Option)
Filterで指定されたフィルターによって使用されるパラメータディクショナリまたはそれに類するディクショナリの配列。フィルタが1つだけで、そのフィルタにパラメータがある場合、すべてのフィルタのパラメータにデフォルト値がない限り、DecodeParmsをフィルタのパラメータディクショナリに設定する必要があります。デフォルト値が利用される場合はDecodeParmsエントリは省略可能です。複数のフィルターがあり、いずれかのフィルターのパラメーターがデフォルト以外の値に設定されている場合、DecodeParmsは、フィルターごとに1つのエントリを持つ配列とする必要があります。配列には各フィルターのパラメーターディクショナリ、フィルターがパラメーターを取らない場合はnullオブジェクトが含められます。どのフィルターにもパラメーターがない場合、又は全てのパラメーターにデフォルト値が存在する場合は、DecodeParmsエントリを省略できます。

F(file Specification/Option)
streamデータを含む外部ファイル。このエントリが存在する場合、ストリームとエンドストリームの間のバイトは無視され(通常、バイトは存在せず長さは0となります)フィルターはFilterではなくFFilterエントリによって指定され、フィルターパラメーターはDecodeParmsではなくFDecodeParmsによって指定されます。ただし、Lengthエントリでは、これらのバイト数を指定する必要があります。

FFilter(Name・NameArrayオプション:PDF 1.2)
ストリームの外部ファイルで見つかったデータの処理に適用されるフィルターの名称を表すNameオブジェクト、またはそのようなNameオブジェクトの配列。
フィルタの場合と同じルールが適用されます。

FDecodeParms(Dictionary・Dictionary Array/Option:PDF 1.2)
FFilterエントリで指定されたフィルターによって利用されるパラメーターディクショナリまたはディクショナリの配列。DecodeParmsエントリと同じルールが適用されます。

 

※特定のタイプのストリームには追加のディクショナリ・エントリがある場合があります。streamのフィルターに関連するオプションエントリには、stream内のデータを使用する前にデコードする必要があるかどうか、およびその方法を示します。フィルタについては、3.3「フィルタ」で詳しく説明しています。

 

3.2.8 nullオブジェクト

nullオブジェクトのタイプと値は、他のオブジェクトとは異なります。nullキーワードで示されるnullタイプのオブジェクトは1つだけです。存在しないオブジェクトへの間接オブジェクト参照は、nullオブジェクトと同様に扱われます。ディクショナリエントリの値としてnullオブジェクトを指定することは、当該エントリを省略することと等価です。

 

3.2.9間接オブジェクト

PDFファイル内における任意のオブジェクトは、間接オブジェクトとしてラベルを付加できます。このラベルは他のオブジェクトより参照可能な一意のオブジェクト識別子として機能します。。オブジェクト識別子は、次の2つの部分で構成されます。

•正の整数のObject Number
間接オブジェクトは、PDFファイル内で順番に番号が付けられることがよくありますが、これは必須ではありません。Object Numberは、任意の順序で割り当てることができます。
•正の整数のGeneration Number
新しく作成されたファイルでは、すべての間接オブジェクトのGeneration Numberは0となり、ファイルが編集・更新された際に編集されたオブジェクトのGeneration Numberが変更されます。

Object NumberとGeneration Numberの組み合わせがオブジェクト識別子として機能し間接オブジェクトが一意に識別されます。オブジェクトは、値が変更された場合でも、その存在を通じて同じオブジェクト番号と世代番号を保持します。
PDFの構造上オリジナルデータは改変されないので編集前のオブジェクト識別子を持つオブジェクトは常にPDFファイル内に残されます。

 

DL(Integer/Optino:PDF 1.5)

デコードされたstreamのバイト数を表す正の整数。一例として、ファイルにストリームを展開する際に十分なストレージ容量が利用可能かどうかを判定するために利用可能です。この値は参考値値として取り扱われるべきで、一部のフィルタではこの値を正確に決定できない場合があります。

PDFファイルでの間接オブジェクトの定義は、そのオブジェクト番号と世代番号、それに続くキーワードobjとendobjで囲まれたオブジェクトの値で構成されます。

オブジェクト例

12 0 obj
( Brillig )
endobj

Object Number=12、Generation Number=0、値(String)=「Brillig」
このオブジェクトへアクセスする場合、以下の様にRキーワードを利用します。

12 0 R

PDF 1.5以降、間接オブジェクトはオブジェクトストリームとして記述出来ます。その場合も同様の手順で参照可能です。ただし、定義には、obj、endobjキーワードは含まれません。
nullオブジェクトへの間接的な参照はエラーではなく、単なるnullオブジェクトへの参照として扱われるだけです。たとえば、ファイルに間接参照17 0 Rが含まれているが、対応する定義が含まれていない場合

17 0 obj
endobj

間接参照はnullオブジェクトを参照していると見なされます。
注:PDFドキュメントを構成するデータ構造では、特定の値を間接オブジェクト参照として指定する必要があります。これが明示的に呼び出される場合を除いて、任意のオブジェクト(ストリーム以外)は、直接または間接的なオブジェクト参照として指定でき同等の扱いとなります。特に、ドキュメント表示可能なコンテンツを定義するコンテンツストリームには、間接参照が含まれていない場合があることに注意が必要です。
以下の例ではストリーム長を指定するための間接オブジェクトの使用を示しています。
ストリームのLengthエントリの値は、後続のストリーム長を示すIntegerオブジェクトです。こういった構造はストリームを書き込んだ後でストリーム長を記述出来るためPDFを生成するアプリケーションはストリームを扱う際に再帰的にLengthの値を記述せずにシングルパスでファイルを生成可能となり、効率的な処理となります。

 

#Example
7 0 obj
<< /Length 8 0 R >> ←ストリーム長を記述する間接オブジェクトへの参照を示すディクショナリ
stream
BT
/F1 12 Tf
72 712 Td
( A stream with an indirect length ) Tj
ET
endstream
endobj
8 0 obj ←ディクショナリから参照されるオブジェクト
77
endobj

 

今回はここまでなんですが、続くFilter関連の読み方まで把握するとPDFの構造は相当理解しやすくなります。ただし、Filterの個々の処理内容まで理解するには必要な知識が膨大な量になってきます。

という事で続きますw

 

 

コメントを残す

メールアドレスが公開されることはありません。