champkeh / pdf-notes

研究pdf格式以及相关技术

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pdf文档结构

champkeh opened this issue · comments

commented

基本元素

PDF 文档的基本元素是 PDF 对象(PDF Object),PDF 对象包括直接对象(Direct Object)和间接对象(Indirect Object)。

直接对象

直接对象有8种类型,如下:

  1. Boolean
    布尔类型,值只能是truefalse

  2. Integer and Real number
    数值类型,包括整数和实数

  3. String
    字符串类型,包括包含在圆括号( )内的文字字符串(literal string)和包含在尖括号< >内的十六进制字符串<hexadecimal string>

例如:

1. (Hello World)
2. <9ADCF1>
  1. Name
    用字符组成的字符串,用/作为前导符号,在PDF文件中具有唯一性。相同的名字表示相同的对象,常出现在Dictionary里面作为Key,用来表示对象名称

例如:

/Page
/Kid
  1. Array
    数组类型,存在于方括号[ ]内,元素可以是除Stream之外的所有类型。只支持一维数组

例如:

[/Page false 17 (hello)]
上面这个数组包含了4种元素类型
  1. Dictionary
    字典类型,包含在双尖括号<< >>内,每两个元素为一对,第一个为key,第二个为valuekey的类型只能为Namevalue可以是任意类型。Dictionary可以嵌套

例如:

<</Page 1 0 obj /Filter /FlateDecode /Name (Hello)>>
上面这个字典包含了3对:
/Page -> 1 0 obj
/Filter -> /FlateDecode
/Name -> (Hello)
  1. Stream
    流对象,使用字节表示的序列,长度理论上无限制。包含在streamendstream之间,以CRLFLF结尾,不能单独以CR结尾。stream前面的dictionary用来描述该stream的相关信息。

例如:

dictionary
stream
...
endstream
  1. Null
    空对象类型,用关键字null表示

间接对象

间接对象,又叫labelled object,嵌套在关键词 n 0 objendobj 之间,使用一种标识来表示一个PDF对象,通过标识来让别的PDF对象进行引用,这个标识叫做间接对象的ID。

结构如下:

12 0 obj
...
endobj

第一行的12规定为positive integer,表示对象ID;0表示生成号(generation number),通常为0;objendobj中间的是对象内容。

其他地方引用该对象时,使用如下格式:

12 0 R
commented

文件结构

+----------------------+
|        Header        |  <-----文件头,表示版本.格式为: %PDF-1.M
+----------------------+
|         Body         |  <-----文件体,由一系列PDF对象组成
+----------------------+
|    Cross-reference   |
|         table        |  <-----交叉引用表,包含指向所有间接对象的文件位置索引的列表
|        (xref)        |
+----------------------+
|        Trailer       |  <-----包含文件的根节点信息和文件解析的起点信息
+----------------------+

交叉引用表

结构:

xref
0 22
0000000002 65535 f
0000000016 00000 n
0000000004 00001 f
0000000066 00000 n
0000000006 00001 f
0000000169 00000 n
0000000008 00001 f
0000000229 00000 n
0000000010 00001 f
0000000353 00000 n
0000000011 00001 f
0000000012 00001 f
0000000013 00001 f
0000000015 00001 f
0000000373 00000 n
0000000016 00001 f
0000000017 00001 f
0000000018 00001 f
0000000019 00001 f
0000000020 00001 f
0000000000 00001 f
0000000394 00000 n

第一行 xref 表示交叉引用表开始;第二行 0 22 表示下面部分引用的对象从 0 开始,共有 22 个对象;第三行开始相同的结构,每行20字节,包括换行符。 nnnnnnnnnn 10位,字节偏移地址,表示从 文件开始(beginning of the file) 到 该对象开始(beginning of the object) 的偏移; ggggg 5位,生成号; N 可以为 n 或者 f,其中 n 表示该对象在使用,f 表示该对象为free状态,未被使用。

commented

示例

%PDF-1.6            # 文件头,表示该文档符合 PDF 1.6 规范 , % 表示注释
%鲣                # (binary data)二进制, 主要用来表示文件内容是 text 还是 binary
12 0 obj            # object 对象, 12是顺序号,0是生成号, obj 为关键词
<</Filter /FlateDecode     # 过滤器类别,处理stream 和 endstream 之间的数据时候需要用到的, FlateDecode表示使用zip算法
/Length 1732>>      # 表示 stream 和 endstream 之间数据的长度
stream              # stream的内容部分
......
endstream
endobj              # 标识该对象结束

1 0 obj
<</Contents 12 0 R
/Parent 2 0 R
/MediaBox [0 0 595 842]
/Resources 7 0 R
/Rotate 0
/Type /Page>>
endobj
2 0 obj
<</Kids [1 0 R] /Type/Pages /Count 1>>
endobj
......
9 0 obj
<</Fields [11 0 R] /XFA [5 0 R] /DA (/Helv 0 Tf 0 g )>>
endobj
11 0 obj
<</T (gapejess[0]) /Kids [4 0 R]>>
endobj
13 0 obj
<</AcroForm 9 0 R /Lang (en-us) /Pages 2 0 R /Type/Catalog>>
endobj
5 0 obj
<</Length 3602 /Filter/FlateDecode>>
stream
......
endstream
endobj

xref                    # 标识交叉引用表开始
0 14                    # 说明下面对象编号是从0开始,总共有14个对象, 从 0 到 13
0000000000 65535 f      # 第0个对象,规定生成号为65535,f 表示 free entry,对象不存在或者删除
0000003079 00000 n      # 第1个对象,偏移地址为3079,生成号为0表示未被修改过, n 表示 in use
0000003191 00000 n
0000003245 00000 n
0000003695 00000 n
0000003955 00000 n
0000003515 00000 n
0000003347 00000 n
0000003446 00000 n
0000003756 00000 n
0000001823 00000 n
0000003827 00000 n
0000000017 00000 n
0000003878 00000 n


trailer                 # 标识文件尾trailer对象开始
<</Root 13 0 R          # 表明根对象的对象号为13,即交叉表中的最后一个对象
/ID [<4E76CDCEDB1E2EC4AC47475DB4EE376E> <C8B1AEBC2C6615E39860F1C150A2847C>]
/Size 14                # 表明PDF文件的对象数目
/Info 8 0 R>>

startxref
7630       # 交叉引用表的偏移地址,相对于文件开始
%%EOF      # 标识文件结束