4.PDF文档的逻辑结构
作为一种结构化的文件格式,一个PDF文档是由一些称为“对象”的模块组成的。并且每个对象都有数字标号,这样的话可以这些对象就可以北其他的对象所引用。这些对象不需要按照顺序出现在PDF文档里面,出现的顺序可以是任意的,比如一个PDF文件有3页,第3页可以出现在第一页以前,对象按照顺序出现唯一的好处就是能够增加文件的可读性,如果你不会用文本编辑器来阅读PDF结构,那么大可不必关心。正是因为页与页之间的不相关性,就可以对PDF文件的页码进行随机的访问。
文件尾(Trail),说明根对象的对象号,并且说明交叉引用表的位置,通过对交叉引用表的查询可以目录对象(Catalog)。这个目录对象是该PDF文档的根对象,包含PDF文档的大纲(outline)和页面组对象(pages)引用。大纲对象是指PDF文件的书签树;页面组对象(pages)包含该文件的页面数,各个页面对象(page)的对象号。
一个PDF文档有下图所示的层次关系:
页面(page)对象作为PDF中最重要的对象,包含如何显示该页面的信息,例如使用的字体,包含的内容(文字,图片等),页面的大小。当然里面的子项也可以是其他对象的引用。页面中包含的信息是包含在一个称为流(stream)的对象里,这个流的长度(字节数)必须直接给出或指向另外一个对象。如下图:
5. PDF的基本语法:
文件的第一行是文件头,指明了该文件所遵从的PDF规范的版本号,它出现在PDF文件的第一行。
一个对象的第一行一般有两个数字和关键字“obj”。例如:
3 0 obj
<<
/Type /Pages
/Count 1
/Kids [4 0 R]
>>
endobj
第一个数字称为对象号,来唯一标识一个对象的,第二个是产生号,是来表明它在被创建后的第几次修改,所有新创建的PDF文件的对象号应该都是0,即第一次被创建以后没有被修改过。上面的例子就说明该对象的对象号是3,而且创建后没有被修改过。
对象的内容应该是包含在<< 和>>之间的,最后以关键字endobj结束.
6. 文件Hello World的文件分析:
6.1.文件的具体分析
%PDF-1.0
文件头,说明符合PDF1.0规范
1 0 obj
<<
/Type /Catalog
/Pages 3 0 R
/Outlines 2 0 R
>>
endobj
Catalog对象(根对象)
2 0 obj
<<
/Type /Outlines
/Count 0
>>
endobj
outline对象(此处它的计数为0,说明没有书签)
3 0 obj
<<
/Type /Pages
/Count 1
/Kids [4 0 R]
>>
endobj
pages对象(页面组对象),/Type /Pages 说明自身的属性,对象的类型为页码,/Count 1说明页码数量为1,/Kids [4 0 R]说明页的对象为4, 这里要说明的是如果有多个页面,就多个页面直接连续下去,比如说/Kids [4 0 R 10 0 R], 就说明该PDF的第一页的对象号是4,第二页的对象号是10。
4 0 obj
<<
/Type /Page
/Parent 3 0 R
/Resources << /Font << /F1 7 0 R >> /ProcSet 6 0 R >>
/MediaBox [0 0 612 792]
/Contents 5 0 R
>>
endobj
页对象,/Parent 3 0 R说明其父对象的对象号为3,/Resources << /Font << /F1 7 0 R >> /ProcSet 6 0 R >>说明该页所要包含的资源,包括字体和内容的类型,/MediaBox [0 0 612 792]说明页面的显示大小(以象素为单位),/Contents 5 0 R说明页面内容对象的对象号为5。
5 0 obj
<< /Length 44 >>
stream
BT
/F1 24 Tf
100 100 Td (Hello World) Tj
ET
endstream
endobj
<< /Length 44 >>说明stream对象为字节数,从BT开始,ET结束,包括中间的行结束符。
Stream说明一个流对象的开始。
BT说明一个文字对象的开始。
/F1 24 Tf,Tf说明True font对象,字体明为F1, 大小为24个象素。
100 150 Td (Hello World) Tj,100 100 说明这一行文字放置的位置,对于Td, 我们可以这样理解,我们的当前X,Y坐标分别加上100和150就是文本的位置,因为在该例子中只有一个对象,那么它的位置就是(100,150), 如果下个对象位置信息为100, 50 Td, 那么它的位置应该就是(100+100, 150+50)也就是(200,200)。(Hello World) Tj说明文本的内容,当然,如果这里是文本的内容可以写成16进制,用<>包含。
ET说明文字对象的结束
endstream流对象的结束
6 0 obj
[/PDF /Text]
Endobj
[/PDF /Text]说明PDF的内容类型仅仅为文本,如果有图片则为[/PDF /Image]
7 0 obj
<<
/Type /Font
/Subtype /Type1
/Name /F1
/BaseFont /Helvetica
>>
endobj
Object six defines the
字体对象,不再多作解释。
所有的对象之后是下面的交叉引用表:
xref
0 8
0000000000 65535 f
0000000009 00000 n
0000000074 00000 n
0000000120 00000 n
0000000179 00000 n
0000000322 00000 n
0000000415 00000 n
0000000445 00000 n
xref说明一个交叉引用表的开始,交叉引用表的第一行0 8 说明下面各行所描述的对象号是从0开始,并且有8个对象。
0000000000 65535 f,一般每个PDF文件都是以这一行开始交叉应用表的,说明对象0的起始地址为0000000000,产生号(generation number)为65535,也是最大产生号,不可以再进行更改,而且最后对象的表示是f,表明该对象为free, 这里,大家可以看到,其实这个对象可以看作是文件头。
0000000009 00000 n就是表示对象1,也就是catalog对象了,0000000009是其偏移地址,00000为5位产生号(最大为65535),0表明该对象未被修改过, n表示该对象在使用,区别与自由对象,不可以更改。
下面的几行相信大家就可以告诉我含义了。
Trailer
<<
/Size 8
/Root 1 0 R
>>
startxref
553
%%EOF
trailer
说明文件尾trailer对象的开始。
/Size 8说明该PDF文件的对象数目。
/Root 1 0 R说明根对象的对象号为1。
Startxref
553说明交叉引用表的偏移地址,从而可以找到PDF文档中所有的对象的相对地址,进而访问对象。
%%EOF为文件结束标志。
6.2.PDF解析过程
7.结束语:
到这里,我们对一个最简单的PDF文件的介绍就结束了,我想大家对PDF文件的格式和特定应该已经有所了解了。
当然,我这里介绍的是不完整的,完整的信息,请访问adobe的网站下载:
http://partners.adobe.com/public/developer/pdf/index_reference.html