PDF文件格式(一):交叉引用流

在PDF-1.5版本之前,对象的交叉引用信息是存储在交叉引用表(cross-reference table)中的。在PDF-1.5版本之后,引进了交叉引用流(cross-reference stream)对象,可以用它来存储对象的交叉引用信息,就像交叉引用表的功能一样。

采用交叉引用流对象有以下几点好处:

  1. 存储的信息更紧凑,并且可以引入压缩算法进行压缩

  2. 提供了访问存储于对象流(ObjectStreams)中的被压缩的对象的功能

  3. 提供了将来的可扩展的交叉引用流的表项类型,以便存储更多不同信息

PDF交叉引用表是PDF的重要组成部分,本文介绍的是交叉引用流(cross-reference stream)对象,这种引用表的格式是PDF的obj格式,内容是被压缩存放在obj下的stream中,因此比常规的引用表格式复杂。下面就开始介绍这种交叉引用表的格式和解析的方法:

1 定位最初始位置:

交叉引用表方法一样,需要到文件尾部找到"startxref"后面的数字,就是第一个交叉引用表的位置(PDF交叉引用表是倒序的,应该说是最后一个)。

2 解析交叉引用表obj内容:

取出obj内DecodeParms,W, Index,size,Prev ,stream内容

DecodeParms是解压缩参数,针对当前Obj有stream内容的情形,解压缩stream内容使用(解压缩部分后续再说)

W的值是数组,数组里面有三个数字,表示的是交叉引用表三个元素(type,file offset,generation)信息在stream内容需要读取的长度;

Index的值也是数组,数量是偶数个,两两一组,表示交叉引用对应obj的起始obj号和范围;

Prev的值是下一个交叉引用表的位置(准确的说应该叫上一个,因为PDF交叉引用表是倒序的,为了描述方便);

stream的内容是交叉引用表的实际内容,交叉引用相关信息被处理,再被压缩

3 多个交叉引用表

当文档内有多个交叉引用表时,当前引用表obj的prev内容保存的是下一个交叉引用表的位置,如果当前引用表时最后一个,那么当前obj找不到Prev。

在解析多个交叉引用表时,需要不断查找当前obj下是否存在prev,如果不存在,则停止查找,说明交叉引用表到此是最后一个,在交叉引用表尾都会部有startxrf字段,后面的数字就是当前交叉引用表位置。因此,在最开头去文件尾部查找startxrf,也是在查找第一个交叉引用表尾部的startxrf。

这里第一个引用表的Prev是541882,找到541882(0x844ba)位置如下:

105 0 obj仍然是交叉引用表obj,里面还有Prev,在endobj后面跟着startxrf(当前交叉引用表位置)。

注意:有时候startxrf记录的不是当前obj的位置,准确的方式是使用引用表obj内的Prev判断。

下面结合实例,看一下交叉引用表时如何被解析出来的:

这是一段PDF文档内容:

可以看到,在PDF尾部的startxrf的是572618,对应的位置是8bcca,正好是116 0 obj,这里的Index是[1 1 4 1 12 1 106 11],表示这段交叉引用表保存的是1号obj,4号obj,12号obj,106号至117(106+11)号obj(106,107,108,109....117);W是[1 3 0];接下来是stream内容,下面是一段解压之后的stream内容:

第一个字节是type内容,0表示f,1表示n,2表示o;2到4字节是offset值,二进制存储,得到结果是542265,最后由于W数组最后一个是0,所以不读取stream数据,generation值为0;从stream起始位置对应Index的顺序(两两一组)最后得出交叉引用表的信息:1号obj,type是n,位置在542265,generation是0,;好了现在找到了交叉引用表的1号obj,我们到542265位置看一下:

可以看到,0x84639对应的位置正是1 0 obj,这样一个完整的交叉引用表流程解析完毕。

相关推荐
ufo200626 分钟前
fastreport导出PDF后style bold粗体斜体等字体风格不显示的原因
pdf·delphi·fastreport
belldeep9 小时前
python:reportlab 将多个图片合并成一个PDF文件
python·pdf·reportlab
墨染辉14 小时前
pdf处理2
pdf
墨染辉1 天前
10.2 如何解决从复杂 PDF 文件中提取数据的问题?
pdf
shandianchengzi1 天前
【记录】Excel|Excel 打印成 PDF 页数太多怎么办
pdf·excel
bianshaopeng2 天前
android 原生加载pdf
android·pdf
卢卡斯2332 天前
在线PDF怎么转换成JPG图片?分享14种转换操作!
pdf
J不A秃V头A2 天前
iTextPDF中,要实现表格中的内容在数据长度超过边框时自动换行
java·pdf
嘻嘻仙人3 天前
【杂谈一之概率论】CDF、PDF、PMF和PPF概念解释与分析
pdf·概率论·pmf·cdf
资深前端之路3 天前
vue2 将页面生成pdf下载
前端·vue.js·pdf