⼀个简单PDF⽂件的结构分析
⼀个简单的PDF⽂件结构的分析
Adobe的PDF参考告诉我们⼀个PDF⽂件可以通过下⾯4个⽅⾯来理解:
1.对象,⼀个PDF⽂档是由⼀组基本数据类型组成的数据结构。
2.⽂件(物理结构),决定对象是如何存放在⼀个PDF⽂件中的,它们是如何被访问的,如何被更新的。这个结构是独⽴于对象的语
义的。
3.⽂档结构,说明⼀些基本的对象类型是如何来表现PDF⽂档的成分的:例如页,图⽚,字体,批注等。
4.内容流,⼀个PDF⽂件内容流包含⼀系列的指令,描述页⾯的外观或其他图形实体的外观和⽂件内容。
但是当时对我来说要看懂这⼏⾏字是有很⼤的困难的,需要了解确切含义,必须看完后⾯的⼏⼗页上百页的内容并且要分析⼀个实际的
PDF⽂件才能完全领会它的意思。
后来经过长时间的⽂档阅读,相关开发,并且具体地分析PDF⽂件后才把PDF⽂件的语法,⽂件的解析搞清楚。虽然说学习是痛并快乐
着,但是对于当时的我来说真得希望有⼀个⼈能够告诉我⼀个简单的例⼦,通过⼀个简单的例⼦来描述PDF的基本组成,它的解析原理和过
程。从我的切⾝体验来说,从⼀个初学者的⾓度出发,最好的⽅式应该是⼀个简单的例⼦。因此我主要将以⼀个简单的例⼦并且加以图例来
说明PDF的主要特性并给出⼀个简单的PDF⽂件的全景。
在继续阅读该⽂章前,先问⾃⼰下⾯的两个问题:
1.你了解⾄少⼀种⽂件格式吗?(例如HTML)
2.为什么要学习PDF的相关知识?
如果你对第⼀个问题的答案为“是”,并且第⼆个问题你能给出⼀个⾮常明确的答案,那么这篇短⽂就是为你准备的。否则,如果对任何⼀
种格式都不了解,建议你先了解⼀下HTML,或XML,你可以从这两种语⾔⾥得到很多启发,对学习PDF的构成或研究学习其他格式⽂件
有很⼤的好处;如果你不清楚你要学习是为了什么,那么我就认为你学习没有⽬的性和动⼒,说不定你今天学了以后明天就忘得⼀⼲⼆净,
因此也不建议你继续看下去,等到你想清楚了欢迎你来看这则短⽂。
1.PDF格式和HTML,XML格式:
⼀个PDF⽂档从根本上来说是⼀个8字节序列。其实PDF格式和我们已经熟知的HTML,XML等结构化的⽂件格式⼀样,包含有关键字,
分隔符,数据等等。
不同的是PDF⽂件是按照⼆进制流的⽅式保存的,⽽html⽂件则是可读的⽂本⽅式保存的,你可以⽤⽂本编辑器分别打开⼀个html⽂件和
PDF⽂件⽐较⼀下就知道了。XML⽂件⼀般只包含数据本⾝,并没有把如何显⽰的信息放在其中,因此要显⽰⼀个XML⽂件还需要⼀个
Schema⽂件才能显⽰,否则看到的将是所有的字节流,包括所有的标志;HTML包含了数据的同时也包含了⼀些关于如何显⽰的信息,但
是HTML是按照是不经过压缩的⽂本存放的,是可读的,你打开⼀个HTML⽂件就能知道所有将显⽰在浏览器⾥的⽂字。另外就是HTML
不能包含⼆进制流,它对图像⽂件的引⽤都是通过引⽤外部⽂件的⽅式来实现的。
2.PDF规范的发展
PDF规范从1993年到现在,已经有过7个版本,六次版本升级,从最初的pdf1.0版本到现在的PDF1.6,每次的版本升级都会加⼊⼀些新的
特性,PDF参考说明书也是从最初的100多页到现在的1000多页,但是PDF⽂件格式的主要特性还是没有改变,可以这么理解,PDF1.6
是PDF1.0的扩展集,学习了PDF1.0以后也能基本上理解PDF1.6的内容,⽽PDF1.0规范是相对简单的,因此说我选择⼀个符合PDF1.0
规范的最简单的⼀个PDF⽂件来进⾏分析。
PDF规范的6次升级:
1.11995加⼊了⽂档加密(40字节),线索树,名字树,链接,设备独⽴⾊彩资源。
1.21996表单,半⾊调屏幕,和其他的⼀些⾼级⾊彩特性,对中⽂,⽇⽂和韩⽂的⽀持
1.32000数字签名,逻辑结构,JavaScript,嵌⼊式⽂件,MaskedImages,平滑阴影,⽀持CID字体的附加⾊彩。
1.42001⽂件加密(128字节),标签式PDF,访问控制,透明,元数据流
1.52003⽂档加密(公钥),JPEG2000压缩,可选的内容组,附加的注解类型
1.62005⽂档加密(AES),增加最⼤⽂件⽀持,加⼊3D⽀持,额外的注解类型
3.PDF⽂件的基本组成:
⼀个PDF⽂件从⼤的⽅⾯来说可以分4个部分:
⽂件头,指明了该⽂件所遵从的PDF规范的版本号,它出现在PDF⽂件的第⼀⾏。
⽂件体,PDF⽂件的主要部分,由⼀系列对象组成。
交叉引⽤表,为了能对间接对象进⾏随机存取⽽设⽴的⼀个间接对象的地址索引表。
⽂件尾,声明了交叉引⽤表的地址,即指明了⽂件体的根对象(Catalog),从⽽能够找到PDF⽂件中各个对象体的位置,达到随机访问。
另外还保存了PDF⽂件的加密等安全信息(以后详细讨论)。
如下图:
图1
4.PDF⽂档的逻辑结构
作为⼀种结构化的⽂件格式,⼀个PDF⽂档是由⼀些称为“对象”的模块组成的。并且每个对象都有数字标号,这样的话可以这些对象
就可以被其他的对象所引⽤。这些对象不需要按照顺序出现在PDF⽂档⾥⾯,出现的顺序可以是任意的,⽐如⼀个PDF⽂件有3页,第3页
可以出现在第1页以前,对象按照顺序出现唯⼀的好处就是能够增加⽂件的可读性,如果你不会⽤⽂本编辑器来阅读PDF结构,那么⼤可不
必关⼼该顺序。正是因为页与页之间的不相关性,就能够对PDF⽂件的页⾯进⾏随机的访问。
⽂件尾(Trail),说明根对象的对象号,并且说明交叉引⽤表的位置,通过对交叉引⽤表的查询可以找到⽬录对象(Catalog)。这个⽬
录对象是该PDF⽂档的根对象,包含PDF⽂档的⼤纲(outline)和页⾯组对象(pages)引⽤。⼤纲对象是指PDF⽂件的书签树;页⾯组对象
(pages)包含该⽂件的页⾯数,各个页⾯对象(page)的对象号。
下图是PDF⽂档的层次关系:
图2
页⾯(page)对象作为PDF中最重要的对象,包含如何显⽰该页⾯的信息,例如使⽤的字体,包含的内容(⽂字,图⽚等),页⾯的⼤
⼩。⾥⾯的信息可以直接给出,当然⾥⾯的⼦项更多的是对其他对象的引⽤,真正的信息存放在其他对象⾥⾯。页⾯中包含的信息是包含在
⼀个称为流(stream)的对象⾥,这个流的长度(字节数)必须直接给出或指向另外⼀个对象(包含⼀个整数值,表明这个流的长度)。
如下图:
图3
5.PDF的基本语法:
⽂件的第⼀⾏是⽂件头,指明了该⽂件所遵从的PDF规范的版本号,它出现在PDF⽂件的第⼀⾏。
⼀个对象的第⼀⾏⼀般有两个数字和关键字“obj”。例如:
1.30obj
2.<<
3./Type/Pages
4./Count1
5./Kids[40R]
6.>>
第⼀个数字称为对象号,来唯⼀标识⼀个对象的,第⼆个是产⽣号,是⽤来表明它在被创建后的第⼏次修改,所有新创建的PDF⽂件的对象
号应该都是0,即第⼀次被创建以后没有被修改过。上⾯的例⼦就说明该对象的对象号是3,⽽且创建后没有被修改过。
对象的内容应该是包含在<<和>>之间的,最后以关键字endobj结束.
6.⽂件HelloWorld的⽂件分析:
6.1.⽂件的具体分析
%PDF-1.0
⽂件头,说明符合PDF1.0规范
1.10obj
2.<<
3./Type/Catalog
4./Pages30R
5./Outlines20R
6.>>
Catalog对象(根对象)
/Type/Catalog说明该对象的类型为/Catalog,/Pages30R,这⾥/Pages指的是这个根对象包含的/Pages的⽬标是对象号为3的对
象,30R的意思是对对象3的引⽤。
1.20obj
2.<<
3./Type/Outlines
4./Count0
5.>>
outline对象(此处它的计数为0,说明没有书签)
1.30obj
2.<<
3./Type/Pages
4./Count1
5./Kids[40R]
6.>>
pages对象(页⾯组对象),/Type/Pages说明⾃⾝的属性,对象的类型为页码,/Count1说明页码数量为1,/Kids[40R]说明它的
孩⼦、页的对象号为4,如果有多个页⾯,就有多个页⾯对象的引⽤,例如/Kids[40R100R],就说明该PDF的第⼀页的对象号是4,第⼆
页的对象号是10。
1.40obj
2.<<
3./Type/Page
4./Parent30R
5./Resources<>/ProcSet60R>>
6./MediaBox[00612792]
7./Contents50R
8.>>
页对象,/Parent30R说明其⽗对象的对象号为3,及Pages对象,/Resources<>/ProcSet60R>>说明该
页所要包含的资源,包括字体和内容的类型,/MediaBox[00612792]说明页⾯的显⽰⼤⼩(以象素为单位),/Contents50R说明
页⾯内容对象的对象号为5。
1.50obj
2.<>
5./F124Tf
6.100100Td(HelloWorld)Tj
eam
<>说明stream对象为字节数,从BT开始,ET结束,包括中间的⾏结束符。
Stream说明⼀个流对象的开始。
BT说明⼀个⽂字对象的开始。
/F124Tf,Tf说明Truefont对象,字体明为F1,⼤⼩为24个象素。
100150Td(HelloWorld)Tj,100100说明这⼀⾏⽂字放置的位置,对于Td,我们可以这样理解,我们的当前X,Y坐标分别加上100
和150就是⽂本的位置,因为在该例⼦中只有⼀个对象,那么它的位置就是(100,150),如果下个对象位置信息为100,50Td,那么它的位
置应该就是(100+100,150+50)也就是(200,200)。(HelloWorld)Tj说明⽂本的内容,当然,如果这⾥是⽂本的内容写成16
进制,则⽤<>包含。
ET说明⽂字对象的结束标志。
Endstream为流对象的结束标志
60obj
[/PDF/Text]
Endobj
[/PDF/Text]说明PDF的内容类型仅仅为⽂本,如果有图⽚则为[/PDF/Image]
1.70obj
2.<<
3./Type/Font
4./Subtype/Type1
5./Name/F1
6./BaFont/Helvetica
7.>>
字体对象,不再多作解释。
所有的对象之后是下⾯的交叉引⽤表:
2.08
3.535f
4.000n
5.000n
6.000n
7.000n
8.000n
9.000n
0.000n
xref说明⼀个交叉引⽤表的开始,交叉引⽤表的第⼀⾏08说明下⾯各⾏所描述的对象号是从0开始,并且有8个对象。
535f,⼀般每个PDF⽂件都是以这⼀⾏开始交叉应⽤表的,说明对象0的起始地址为,产⽣号
(generationnumber)为65535,也是最⼤产⽣号,不可以再进⾏更改,⽽且最后对象的表⽰是f,表明该对象为free,这⾥,⼤家可以
看到,其实这个对象可以看作是⽂件头。
000n就是表⽰对象1,也就是catalog对象了,是其偏移地址,00000为5位产⽣号(最⼤为
65535),0表明该对象未被修改过,n表⽰该对象在使⽤,区别与⾃由对象,可以更改。
下⾯的⼏⾏相信⼤家就可以告诉我含义了。
r
2.<<
3./Size8
4./Root10R
5.>>
ref
7.553
8.%%EOF
Trailer说明⽂件尾trailer对象的开始。
/Size8说明该PDF⽂件的对象数⽬。
/Root10R说明根对象的对象号为1。
Startxref553说明交叉引⽤表的偏移地址,从⽽可以找到PDF⽂档中所有的对象的相对地址,进⽽访问对象。
%%EOF为⽂件结束标志。
6.2.PDF解析过程
回顾上⾯的详细解释,我们可以将这个简单的PDF解析过程简化为如下图例:
图4
7.结束语:
到这⾥,对⼀个最简单的PDF⽂件的介绍就结束了,⼤家对PDF⽂件的格式和特定也应该已经有所了解了。
当然,我这⾥介绍的是不完整的,完整的信息,请访问adobe的⽹站下载最新的PDFREFERENCE1.6:
下次介绍PDF的加密过程及原理。
本文发布于:2022-12-27 04:23:59,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/38086.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |