PDF格式详解-ISO 32000-1:2008学习

1、简介

PDF(英语:Portable Document Format,缩写:PDF)

PDF的历史与规范化

ISO 32000-1:2008

2、文件结构

一般的PDF文件由四部分组成

  • header部分:单行,标识文件所遵循的PDF规范的版本
  • body部分:多行,包含了由多个文件对象构成的文件主体
  • cross-reference table 部分:交叉引用表,包含文件中间接对象信息
  • trailer部分:包含交叉引用表的位置以及文件正文中某些特殊对象的位置

另外,PDF支持文件增量更新,新增部分可以附加到原始文件之后,通过同样类似的结构追加进来。

按照规范标准约定,PDF文件按照一定的标记排列成行,每行的终结符可以是回车符(\r、0x0D、ASCII 13),也可以是换行符(\n、0x0A、ASCII 10),也可以两者同时存在(\r\n、0x0D0x0A)表示一行结束。为了统一,行标记占两个字符,通常为空格+回车、空格+换行或者回车+换行这3种形式。包含二进制数据的部分可以是任意多行。

为了增强PDF格式文件解析处理程序的兼容性,不属于流对象数据的行的行数不得超过255个字符。 有个列外情况,从PDF 1.3开始,签名字典的Contents字符串不受行长的限制。

以上为基本的PDF格式,PDF在设计时考虑了扩展结构,以适用于在不同环境下的使用。例如线性化PDF文件是PDF文件的一种特殊格式,可以通过Internet更快地进行查看。线性化PDF文件包含允许的信息字节流服务器一次下载PDF文件一页。如果在服务器上禁用了字节流,或者PDF文件未禁用线性化后,必须先下载整个PDF文件才能查看。所有受支持的IDS版本都会生成线性化的PDF文件。对于PDF线性化来说,在页面数量很多的情况下,能突出表现出它快速网络浏览的优势。 

2.1、Header

PDF文件的第一行,由5个字符组成,%PDF-后跟形式为1.N的版本号,其中N是介于0和7之间的数字。

%PDF–1.0
%PDF–1.1
%PDF–1.2
%PDF–1.3
%PDF–1.4
%PDF–1.5
%PDF–1.6
%PDF–1.7

PDF低于1.4版本时,唯一由Header确定版本。从1.4开始,版本标识可以从文档的目录字典中获取(文档目录字典位于位于文件Trailer部分的中的Root条目),通常PDF生成器遵循两个版本标记一致原则。

2.2、Body

PDF文件的body由代表文档内容的一系列间接对象组成。

  • Boolean values
  • Integer and Real numbers
  • Strings
  • Names
  • Arrays
  • Dictionaries
  • Streams
  • Null object
  • Object Streams

PDF包括八种基本类型的对象:Boolean values, Integer and Real numbers, Strings, Names, Arrays, Dictionaries, Streams, and the null object。通过这8种基本对象可以用来描述文档的各种特征,例如字体、页面和采样的图像。

从PDF 1.5开始,Body还可以包含对象流(Object Streams),每个对象流可以包含一系列的间接对象(Indirect Objects)。

2.3、Cross-Reference Table(交叉引用表)

交叉引用表包含允许随机访问文件中间接对象的信息,因此无需读取整个文件即可找到任何特定对象。 该表应为每个间接对象包含一个单行条目,并指定该对象在文件正文中的字节偏移量。

从PDF 1.5开始,部分或全部交叉引用信息可能会包含在交叉引用流(Cross-Reference Streams)中。

交叉引用表是PDF文件中具有固定格式的唯一部分,它允许随意访问表中的条目。PDF文件可以包含一个或多个交叉引用部分。例如原始文件可能只有一个交叉引用表,如果文件是线性化的,则文件结构是由两部分组成,每次文件进行增量更新时,都应该增加一个交叉引用表结构。

每个交叉引用部分均应以包含关键字xref的行开头。此行之后是一个或多个交叉引用小节,这些引用小节可以以任何顺序出现。

对于从未进行过增量更新的文件,交叉引用节应仅包含一个子节,其对象编号从0开始。子节结构对于增量更新很有用,因为它允许将新的交叉引用节添加到PDF文件中,其中仅包含已添加或删除的对象的条目。

每个交叉引用小节均应包含对象编号连续范围的条目。该小节应以包含以空格隔开的两个数字的行开头,表示该小节中第一个对象的对象编号及该小节中的条目数。

例如以下,表示从28~32的连续5个对象为其中的一个小节

xref
28 5
...

对于给定的对象编号只允许出现在某一个小节,不允许在其他小节重复引用出现。

在编号行之后是交叉引用条目本身,每行一个条目。每个条目为20个字节长,包括行尾标记。

交叉引用条目有两种:一种用于使用中的对象,另一种用于已删除并因此是空闲的对象。两种类型的条目都有类似的基本格式,以关键字n(in-use)或f(free)来区分。条目的格式为:

nnnnnnnnnn ggggg n eol
...
nnnnnnnnnn ggggg f eol
  • nnnnnnnnnn为解码流中10位字节偏移量,绝对占位10,不够10位时用0做前导填充
  • ggggg为5位字节生成编号,绝对占位5,不够5位时用0做前导填充
  • n表示该对象处于使用中,f表示该对象已删除
  • eol表示换行标记,可以是SP CR、SP LF或者CR LF

4节数据默认以空格为间隔,组成一行,每行固定占位20字节。

交叉引用表中的第1个编号为0的对象始终是(f),并且生成号为65535。

除了编号0的对象外,交叉引用表中的所有对象最初的生成号应为0。

删除间接对象时,应将其交叉引用条目标记为(f),并将其添加到free条目的链表中。

下次创建具有该对象编号的对象时,条目的生成号应增加1,最大生成号为65535;当交叉引用条目达到此值时,它将永远不会被重用。

连续的交叉引用表

下面显示了一个交叉引用表,该表由一个包含6个条目的小节组成:4个正在使用(对象编号1、2、4和5)和2个空闲(对象编号0和3)。 对象编号3已被删除,使用该对象编号创建的下一个对象的生成编号为7。

xref
0 6
0000000003 65535 f 
0000000017 00000 n 
0000000081 00000 n 
0000000000 00007 f 
0000000331 00000 n 
0000000409 00000 n

非连续的交叉引用表

下面显示了具有4个子节的交叉引用表,总共包含5个条目。

第1个小节包含1个条目,对象编号为0,标记是f(free),默认的。

第2个小节包含1个条目,对象编号为3,正在使用(n)。

第3小节包含2个条目,对象编号为23、24,正在使用(n)。从对象编号23的生成编号为2可以看出,它已被重用(n)。

第4小节包含1个条目,对象编号30,正在使用中(n)。

xref
0 1
0000000000 65535 f 
3 1
0000025325 00000 n 
23 2
0000025518 00002 n 
0000025635 00000 n 
30 1
0000025777 00000 n 

2.4、File Trailer(文件尾)

PDF文件的trailer文件尾使得应用程序可以快速找到交叉引用表和某些特殊对象。应用程序从文件末尾读取PDF文件。

文件的最后一行应仅包含文件结尾标记%%EOF。

倒数往前两行应每行依次包含关键字startxref和解码后的流中从文件起始位置到最后一个交叉引用节中xref关键字开头的字节偏移量。

startxref行之前必须是Trailer字典,该字典由关键字Trailer组成,后跟一系列用双尖括号(<< ... >>)括起来的键/值对。 总体结构如下:

trailer
<< key1 value1 key2 value2
...
keyn valuen
>>
startxref
Byte_offset_of_last_cross-reference_section
%%EOF

 Trailer字典类型

Key  Type Value
Size 数字型 所有间接对象的个数。一个PDF文件,如果被更新过,则会有多个对象集合、交叉引用表、trailer,最后一个trailer的这个字段记录了之前所有对象的个数。这个值必须是直接对象。
Prev 数字型 

当文件有多个对象集合、交叉引用表和trailer时,才会有这个键,它表示前一个相对于文件头的偏移位置。这个值必须是直接对象。

Root 字典 Catalog字典(文件的逻辑入口点)的对象号。必须是间接对象。
Encrypt 字典 文档被保护时,会有这个字段,加密字典的对象号。
info 字典 存放文档信息的字典,必须是间接对象。
ID 数组 文件的ID

  

一个未增量更新过的PDF原始文件的trailer文件尾如下格式,标志是没有Prev这个Key

trailer
    << /Size 22
       /Root 20R /Info 10R
       /ID [ <81b14aafa313db63dbd6f981e49f94f4>
             <81b14aafa313db63dbd6f981e49f94f4>
           ]
    >>
startxref
18799
%%EOF

 

2.5、Incremental Updates(增量更新)

PDF文件内容可以增量更新而无需重写整个文件。更新变化数据需要附加到文件尾段,而其原始内容可以保持不变。

PDF支持增量更新的优点:

  • 可以快速保存对大型文档的较小更改。
  • 在某些情况下,例如通过HTTP连接编辑文档或使用OLE嵌入(Windows特定技术)时,符合条件的编写器无法覆盖原始文件的内容时,增量更新可用于保存对文档的更改。

增量更新后的文件结构示例:

增量更新时新增的交叉引用表部分仅包含那些已经被修改,替换,或删掉的对象。删除的对象原封不动的留在文件中,需要通过交叉引用表把对应的交叉引用表项标记为已删除(f)。新增的trailer文件尾包括所有的选项包括之前的trailer文件尾部分,字典中的Prev项标记之前交叉引用部分的位置。被更新过多次的PDF文件通常包含了多个trailer文件尾;每个trailer文件尾都有自己的结束标识(%%EOF)。

由于更新的部分被添加到文件中,一个文件可能有一个相同对象的多个副本,而保持相同的对象标识(对象编号和生成编号)。可能出现以下情况,例如如果一个文本标注被修改多次并且文件保存了多次的修改。因为文本标注对象没删除,它仍保持着之前相同的对象号和生成号。但一个被修改过的对象副本会被包含在更新部分添加到文件中。更新的交叉引用表部分包含这个新的对象的字节偏移值,覆盖原先交叉引用表中旧的字节偏移值。当一个用户应用程序读取文件时,它必需用这种方法构建它自己的交叉引用表信息,即文件中每个对象的最新副本是被访问的那一个。

PDF 1.4之后的版本,版本号Version是支持在增量更新中修改。

posted @ 2021-05-06 20:22  JeromePowell  阅读(5077)  评论(0编辑  收藏  举报