PDF格式分析(二十七)Linearized PDF 线性化 - 文档结构

线性化PDF文档结构

线性化PDF文件文件中的所有间接对象应分为两组:

  • 第一组应包含文档目录,其他文档级对象以及属于文档第一页的所有对象。 这些对象应按顺序编号,从第二组最后一个编号后的第一个对象编号开始。 (包含hint表的流,称为hint流,可以不按顺序编号)。
  • 第二组应包含文档中的所有剩余对象,包括第一页之后的所有页面,所有共享对象(从多个页面引用的对象,不计算从第一页引用的对象),等等。 这些对象应从1开始按顺序编号。

这些对象组应由两个交叉引用表编制索引。 线性化PDF按顺序由11个部分组成, 所有对象的版本号均为0。

从PDF 1.5开始,PDF文件可以包含对象流(object streams )。 在包含对象流的线性化文件中,需要符合以下条件:

  • 一些附加对象可能不包含在对象流中:如线性化字典,文档目录和页面对象。
  • 存储在对象流中的对象编号,应在主要和第一页交叉引用部分中使用最高范围的对象编号。
  • 对于包含对象流的文件,hint 数据可以仅指定对象流的位置和大小(或未压缩的对象),而不是单个压缩对象。 类似地,共享对象引用应该对包含压缩对象的对象流进行,而不是对压缩对象本身进行。
  • 使用交叉引用流代替传统的交叉引用表。

Part 1: Header
线性化PDF文件应以标准的PDF文件头开头。 线性化与PDF版本号无关,可以应用于1.1或更高版本的任何PDF文件。第二行百分号(25h)后面的二进制字符是代码为128或更大的字符。

%PDF-1.1 
% …Binary characters…

Part 2: Linearization parameter dictionary
在标题之后,文件正文中的第一个对象应该是线性化参数字典, 此词典中的所有值都应为直接对象。 在文件的任何地方都不得引用该词典; 但是,第一页交叉引用表应包含正常的条目。

线性化参数字典应完全包含在PDF文件的前1024个字节中。 这是判断文件是否线性化之前,必须读取的数据量,所以,如果超出这个范围,会判断该文件不是线性化文件。

Linearized:整数,(必需)线性化格式的版本号。
L:整数,(必需)整个文件的长度(以字节为单位)。 它应该完全等于PDF文件的实际长度。
H:数组,(必需)包含两个或四个整数的数组,[offset1 length1] 或 [offset1 length1 offset2 length2]。 offset1 应该是主要 hint 流对象在文件的偏移量。length1 应该是此流对象的长度。如果主 hint 流字典的 Length 条目的值是间接引用,则它引用的对象应紧跟流对象,length1 还应包括间接长度对象的长度。 如果存在溢出 hint 流,则 offset2 和 length2 应指定其偏移量和长度。
O:整数,(必需)第一页的页面对象的对象编号。
E:整数,(必需)第一页末尾相对于文件开头的偏移量。
N:整数,(必需)文档页数。
T:整数,(必需)在使用标准主交叉引用表的文档中,此条目应表示空白字符相对于文件的开头的偏移量,该空白字符位于主交叉引用表(包含对象号0的条目)的第一个条目之前的字符。 请注意,这与第一页trailer中的Prev条目不同,后者提供了在交叉引用表之前的 xref 的位置。 (PDF 1.5)对于仅使用交叉引用流的文档,此条目应表示主交叉引用流对象的偏移量。
P:整数,(可选)第一页的页码。 默认值:0。

43 0 obj
<< /Linearized 1.0            % Version
/L 54567                      % File length
/H [475 598]                  % Primary hint stream offset and length (part 5)
/O 45                         % Object number of first page’s page object (part 6)
/E 5437                       % Offset of end of first page
/N 11                         % Number of pages in document
/T 52786                      % Offset of first entry in main cross-reference table (part 11)
>>
endobj

Part 3: First-page cross-reference table and trailer
第3部分应包含属于第一页的对象的交叉引用表,以及文档目录和文档级别,该部分出现在第一页之前的对象。 此外,此交叉引用表应包含线性化参数字典(在开头)和主要hint流(在结尾)的条目。 该表应是有效交叉引用表,它应由一个没有空闲条目的交叉引用子部分组成。

在PDF 1.5及更高版本中,交叉引用流可用于线性化文件中。 这里描述的逻辑对于交叉引用流的情况,仍然适用。

该交叉引用表下方应为第一页trailer。trailer的Prev条目的值是,在文件末尾附近的主交叉参考表的偏移量。

第一页 trailer 应包含有效的 Size 和 Root 条目,以及显示文档所需的任何其他条目。 Size值应为文档间接对象的总数。

注:第一页 trailer 可以选择以startxref,整数和%% EOF为了结尾,不过,该信息应被忽略。

xref
43 14
0000000052 00000 n
0000000392 00000 n
0000001073 00000 n
…Cross-reference entries for remaining objects in the first page…
0000000475 00000 n
trailer
<< /Size 57                 % Total number of cross-reference table entries in document
/Prev 52776                 % Offset of main cross-reference table (part 11)
/Root 44 0 R                % Indirect reference to catalogue (part 4)
…Any other entries, such as Info and Encrypt… % (part 9)
>>
                            % Dummy cross-reference table offset
startxref
0%
%EOF

Part 4: Document catalogue and other required document-level objects
在第一页交叉引用表和 trailer 之后是Catalog字典和打开文档时所需的其他对象。 Catalog中如果存在以下这些条目,它们的值必须是间接对象:

  • Preferences条目
  • PageMode条目。 注意,如果PageMode的值是UseOutlines,则大纲层次结构应位于第6部分; 否则,大纲层次结构(如果有的话)应位于第9部分。
  • “Threads”条目及其引用的所有Thread词典。 这不包括Threads的信息字典或属于Threads的各个bead字典。
  • OpenAction条目。
  • AcroForm条目。 只应存在顶级交互式表单字典,而不是它所引用的对象。
  • 第一页trailer词典中的 Encrypt 条目。 Encrypt字典中的所有内容也应该放在此处。

除了上面提到的所有对象不得位于此处,而应位于文件的末尾,也就是第9部分。 这包括诸如页面树节点,文档信息字典和命名目标等对象。

注:位于此处的对象由第一页交叉引用表索引,即使它们在逻辑上不是第一页的一部分。

44 0 obj
<< /Type /Catalog
/Pages 42 0 R
>>
endobj
…Other objects…

Part 5: Primary hint stream (may precede or follow part 6)
线性化信息的核心应存储在称为 hint 表的data结构中,其格式在下面的“ hint 表”中描述。 它们应提供索引信息,使浏览器能够为了显示文档的任何页面或有效检索其他信息所需的所有对象,构造单个请求。 hint 表可能包含其他信息,使得符合特定的应用程序进行数据的优化访问。

通常,所有 hint 表应该包含在一个流中,称为主 hint 流。也可能存在包含更多 hint 的额外流,称为溢出hint流。两个hint流的内容应该被连接处理,就好像它们是一个连续的流。

第5部分表示的主提示流(Primary hint stream )。这部分和第一页部分(如第6部分所示)的顺序可以颠倒。溢出提示流(Overflow hint stream,第10部分)是可选的。主提示流的位置和长度,以及如果存在溢出提示流的位置和长度,应在文件开头的线性化参数字典中给出。

提示流应该被分配到第一页的最后一个对象的对象编号之后。它们的交叉参考表条目应在第一页交叉引用表的末尾。

提示流字典中的所有条目的值应该是直接对象,除了流字典的 Length 条目。

除了标准流属性之外,主提示流的字典应给出流中每个提示表的开头位置的条目。 这些位置应以字节为单位计算,相对于流数据的开头(解码后,如果有的话),并且与溢出提示流连接(如果存在)。 溢出提示流的字典不应包含主提示流中这些条目。 注意,页面偏移提示表必须是流中的第一个表,并且应从偏移量0开始。

S :(必需)共享对象提示表
T :(缩略图图像存在时出现)缩略图提示表
O :(文档大纲存在时出现)大纲提示表
A:(文章线程存在时出现)线程信息提示表
E :(命名目标存在时显示)命名目标提示表
V :(交互式表单字典存在时出现)交互式表单提示表
I:(文档信息词典存在时显示)信息字典提示表
C :(逻辑结构层次结构存在时出现; PDF 1.3)逻辑结构提示表
L:(PDF 1.3)页面标签提示表
R:(Renditions名称树存在时出现; PDF 1.5)Renditions名称树提示表
B:(嵌入文件流存在时出现; PDF 1.5)嵌入式文件流提示表

每个提示表都是流的一部分,相应流属性指示在流中的开始位置。 此外,符合标准的编写器应包括页面偏移提示表,该表应是流中的第一个表,并且应从偏移0开始。如果存在溢出提示流,则其内容应无缝地附加到主提示流。

详细描述在后面章节展示。

56 0 obj
<< /Length 457
…Possibly other stream attributes, such as Filter…
/S 221                                      % Position of shared object hint table
…Possibly entries for other hint tables…
>>
stream
…Page offset hint table…
…Shared object hint table…
…Possibly other hint tables…
endstream
endobj

Part 6: First-page section (may precede or follow part 5)
该部分是显示文档第一页所需的所有对象。 通常,第一页是页面0,即页面树中最左边的叶页节点。 但是,如果文档目录中包含OpenAction条目,该条目可以指定打开第0页以外的其他页面,这时,被打开的页面被视为第一页,此页的页码在线性化参数字典的P条目中给出。

如前所述,包含属于文档第一页的对象的部分放在主提示流之前或之后。起始文件偏移量和该段的长度可以从提示表中确定。此外,线性化参数字典中的E条目指定第一页的末尾(从文件开头的偏移),O条目给出第一页的页对象的对象号。

以下对象应包含在第一页的部分中,且输出顺序如下:

  1. 第一页的页面对象。 该对象放在该部分的最前面。 其对象编号在线性化参数字典中给出。 该页面对象应明确指定所有必需的属性,例如:Resources和MediaBox,这些属性不得从祖先页面树节点继承。
  2. 整个大纲层次结构,如果目录中的PageMode条目的值为UseOutlines。但如果PageMode条目被省略或是其他值,且文档具有大纲层次结构,则大纲层次结构应出现在第9部分中; 请参见“第9部分”。
  3. 页面对象引用的所有对象(任意深度),除页面树节点或其他页面对象。包括Contents,Resources,Annots和B条目引用的对象,但不包括Thumb条目。

从页面对象按照以下顺序进行输出:
a)Annots数组和所有注释字典,其深度足以激活那些注释。绘制注释所需的信息可以放在稍后输出。
b)此页面的B(beads)数组和所有bead词典(如果有的话)。如果此页面存在任何bead,则B数组应存在于页面字典中。另外,线程中的每个bead(不仅仅是第一个bead)应包含一个引用相关线程字典的T条目。
c)资源字典,但不包含该字典中包含的资源对象。
d)资源对象,按照它们首先从contents流中直接或间接引用的顺序进行排序。如果contents对象内容为流数组,则资源对象应位于首次引用它的流之前。请注意,此处应包含Font,FontDescriptor和Encoding资源,但不包括从字体描述符引用的可替换字体文件(即FontFile)。
e)页面内容(Contents)。 如果内容流很大,则应将其表示为对内容流的间接引用数组,而内容流又应与它们所需的资源交错。 如果很小,则整个Contents应该是资源之前的单个内容流。
f)图像XObjects,按照它们首次被引用的顺序进行排序。
g)FontFile流,该类型对象包含了嵌入字体的实际定义。

45 0 obj
<< /Type /Page
…
>>
endobj
…Outline hierarchy (if the PageMode value in the document catalog is UseOutlines)…
…Objects for first page, including both shared and nonshared objects…

Part 7: Remaining pages

线性化PDF文件的第7部分应包含文件所有剩余页面的页面对象和非共享对象,每个页面的对象组合在一起输出。 页面应是连续的,并按页码排序。 如果文件的第一页不是第0页,则此部分应从第0页开始。

对于每个页面,显示该页面所需的对象应组合在一起,但资源和与其他页面共享的其他对象除外。 共享对象应位于共享对象部分(第8部分)。 可以从提示表中查看到每个页面的起始偏移量和长度。

页面中对象的推荐顺序与第一页中的基本相同。 特别是,页面对象应该是每个部分中的第一个对象。

在大多数情况下,与第一页不同,将内容与资源交织不会带来什么好处,因为除图像字体之外的大多数资源在多个页面之间共享,因此驻留在共享对象部分中。图像XObjects通常不被共享,但是它们应该出现在文件的页面部分的末尾,因为图像的呈现被推迟了。

1 0 obj
<< /Type /Page
…Other page attributes, such as MediaBox, Parent, and Contents…
>>
endobj
…Nonshared objects for this page…
…Each successive page followed by its nonshared objects…
…Last page followed by its nonshared objects…

Part 8: Shared objects for all pages except the first
第8部分包含从多个页面引用,但未被第一页(直接或间接)引用的对象(主要是命名资源)。 提示表包含这些对象的索引。

这些对象的顺序可以是任意的。 但是,只要资源由多级结构组成,结构的所有组件都应组合在一起输出。如果仅从组外部引用顶级对象,则可以通过共享对象提示表中的单个条目来描述整个组。 这有助于最小化共享对象提示表的大小以及页面偏移提示表中条目的单个引用数。

Shared objects…

Part 9: Objects not associated with pages, if any
该部分是与显示页面所需无关的其他任何对象。 这些对象应分为功能进行分类,每个类别中的对象应该组合输出; 类别的相对顺序并不重要。

  1. 页面树(page tree)。 此对象可以位于此部分中,因为符合标准的读者从不需要查阅它。 请注意,页面对象的所有Resources属性和其他可继承属性都应在每个叶页对象中下推并复制(但它们可能包含对共享对象的间接引用)。
  2. 缩略图图片(Thumbnail images)。 这些对象只需按页码排序(第0页的缩略图图像应该是实际上第一页的,即使文档的第一页是0以外的某个页面)。每个缩略图图像由一个或多个对象组成,这些对象可以引用缩略图共享对象部分中的对象(请参阅 下一个项目)。
  3. 缩略图共享对象(Thumbnail shared objects)。 这些是在一些或所有缩略图图像之间共享的对象,不得从任何其他对象引用。
  4. 大纲层次结构(outline hierarchy,如果不在第6部分中)。对象的顺序应与阅读器显示的顺序相同。 这是大纲树的前序遍历顺序,跳过任何已关闭的子树(即,其父级的Count值为负)。 接下来应该是跳过的子树,按照它们全部打开时出现的顺序。
  5. 线程信息(Thread information)字典,从线程字典的 I 条目引用。 请注意,注意,线程字典本身应该与文档目录一起定位,而珠子(bead)字典应该与其坐在的单个页面一起定位。
  6. 命名目的地(Named destinations)。 这些对象包括文档目录中的Dests或Names条目的值以及它引用的所有目标对象。
  7. 文档信息字典及其中包含的对象。
  8. 交互式表单字段层次结构(interactive form field hierarchy)。 该组对象不应包括与文档目录一起定位的顶级交互式表单字典。
  9. 文档目录中未从任何页面引用的其他条目。
  10. (PDF 1.3)逻辑结构层次结构(logical structure hierarchy)。
  11. (PDF 1.5)播放名称树层次结构(renditions name tree hierarchy)。
  12. (PDF 1.5)嵌入式文件流(Embedded file streams)。
…Other objects…

Part 10: Overflow hint stream (optional)

参见第5部分。

Overflow hint stream…

Part 11: Main cross-reference table and trailer
第11部分是PDF文件中所有对象的交叉引用表,除了第一页交叉引用表(第3部分)中列出的对象外。 如前所述,此交叉引用表应扮演文件的原始交叉引用表的角色(在附加任何更新之前),并应符合以下规则:

  • 它由一个交叉引用子部分组成,从对象编号0开始。
  • 第一个条目(对象号为0)应为free。
  • 其余条目用于正在使用的对象,这些对象应从1开始连续编号。

startxref 行应给出第一页交叉引用表的偏移量。 第一页 trailer 的Prev条目应给出主交叉参考表(Main cross-reference table)的偏移量。 主 trailer 没有Prev条目,不得包含Size以外的任何条目。

在PDF 1.5及更高版本中,交叉引用流(cross-reference streams )可用于线性化文件中。 本子条款中描述的逻辑对于交叉引用流同样适用。

xref
0 43
0000000000 65535 f
…Cross-reference entries for all except first page’s objects…
trailer
<< /Size 43 >>        % Trailer need not contain other entries; in particular,
                      % it should not have a Prev entry
                      % Offset of first-page cross-reference table (part 3)
startxref
257
%%EOF

猜你喜欢

转载自blog.csdn.net/steve_cui/article/details/82466188