随笔-11  评论-42  文章-0  trackbacks-0

现在让我简要介绍一下PDF的文件格式,PDF的文件格式说明,最权威的就是Adobe官方网上的PDFReference,纯英文版的,一千多页,个人认为对于国内的开发者做PDF的生成的时候,最大的困难就在这里了,一个是没有充足的时间去看,二个一看满篇的英文基本上就头大。我只看了三分之一左右,看了整体描述和有针对性地看了一些,必竟HTML转PDF的时候,有不少的东西是用不着的。现在我介绍一下PDF格式的一些要点:
一、PDF文件是一种文本和二进制混排的格式,但是Adobe更愿意让人把它当成二进制的文件,所以在里面建议当文件里面的文本太多的时候,可以加一些二进制的注释,好让现有的一些编译器把它当成二进制文件。里面的文本主要是对文件结构的一种描述,二进制的内容来自于三个方面:1、图片;2、字体;3、压缩后的Post Script。
二、文件结构可以分为三方面:
1、首部。用文本编辑器打开的时候就可以看到:%PDF-1.4 这样的字眼,其中最后一位就是PDF文件格式版本号,软件的版本号总要比文件格式的版本号高1,比如说Read 5能打开的内容就是4。
2、文件体。里面有若干个的obj,以及xref来组成,OBJ这种形式:
30979 0 obj
<<
/Linearized 1
/O 30982
/H [ 15061 25084 ]
/L 9379963
/E 166967
/N 978
/T 8760262
>>
endobj 
第一个数字就是这个OBJ的顺序号,是为了便于在xref中查找,后面的0是为了区分不同的OBJ,现在都是0(个人感觉是为了以后扩展用的)后面就是关键字obj.下面的各行就是属性,/关键字 值 的形式。
xref是obj的索引表,用来索引各个obj在文档中的起始位置,它的形式是:
xref
0 211
0000000000 65535 f
0000000009 00000 n
……
0000087999 00000 n

trailer
<<
/Size 211
/Root 2 0 R
/Info 1 0 R
/ID [<B29FBB52459C4623DB1A90CBFC28381E><B29FBB52459C4623DB1A90CBFC28381E>]
>>
其中0,211分别代表这个xref的obj的起始和终止序号。其中0这个是估计是为了程序中好处理所以加了这个(个人英文水平不行,有些地方看不明白),可以不加入这个。下面的各行就代表各个obj在这个文档的起始位置,其中第一串字符(10个)代表起始位置,中间的五个字符也是为了区分用的,现在基本上全为0, 后面的字母有两种f代表删除的,n代表要使用的。后面的trailer是对整个xref的摘要,说明里面有多少个OBJ,读的时候从哪个OBJ开始解析,信息节点等,ID是为了让一些文件检索工具能够唯一区分文件。
3、文件尾。
startxref
88019
%%EOF
因为一个文档中可以有多个xref,所以这里要指明要从哪个xref开始进行解析这个文件。
从上面的分析来看:PDF文件内部校验是很复杂的,只要里面有一位错位了,就会导致整个文档读取错误。而且它时硕会有不少的二进制内容,所以一般来说在内存里面存储的时候,用流对象,而不能用字串,特别是生成的时候,每加入一个obj的时候,去获取一下当前流的长度就可以得到每个obj的起始位置,同时把获取的这些位置存到ArrayList里面,这样就可以很方便地得到和内容相一致的xref了。
三、PDF里面对象的组成形式,可以说是用树形结构来相互关联的,驵下面挂页集合,页集合下面挂页,页里挂图片,链接,内容等
四、PDF里面的obj的类型主要有以下几种:
1、文件描述对象,用来描述这个文件的标题,作者,时间等
2、组对象,也就是文档内容的起始结点。Type 为Catalog
3、页集合,里面聚合了大量的页对象。  Type 为pages
4、页对象,里面指明了当前页里面用到的字体,内容,活动对象,图片等。Type 为page
5、活动对象,有链接,文字,声音,电影等,Type 为Annots
6、图片对象, Type 为 XObject
7、字体对象,Type 为 Font 。PDF可以内置字体,所以即使目标机器上没有,只要它内置了,也可以正常地显示,不受影响(内置字体,这个我还没有研究清楚,希望知道的人可以告诉我一下,这里先谢了)
8、流对象。所有的二进制内容都是存在这个对象里面,文件流的常见的压缩方式是:图片的一些压缩算法,FlateDecode,ASCIIHexDecode,ASCII85Decode等等,FlateDecode事实上就是ZIP的压缩算法(关这个,我就花了好长的时间去研究)。流对象的长度是关连到一个长度对象上的/Length  188 0 R这种形式。188就是存这个长度的OBJ的顺序号。
9、数字对象。
188 0 obj
2538
endobj
里面只有一个数字,经常用来表示长度,为什么要把长度还要再用对象来表示,这个到现在我也想不太明白。
以上就是我对PDF文件格式的理解的摘要。也许有些地方可能理解得不正确,希望得到大家的指正。

posted on 2006-01-05 13:06 铁匠 阅读(2971) 评论(4)  编辑 收藏

评论:
#1楼  2006-01-11 23:45 | flyingxu [未注册用户]
期待后续文章。。
  回复  引用    
#2楼  2006-02-09 16:17 | 投影 [未注册用户]
我刚开始看PFD,看英文的文档看得头都晕了。这篇文章很有用,谢谢。
  回复  引用    
#3楼  2006-03-15 11:26 | Camel [未注册用户]
2、文件体。里面有若干个的obj,以及xref来组成,OBJ这种形式:
30979 0 obj
<<
/Linearized 1
/O 30982
/H [ 15061 25084 ]
/L 9379963
/E 166967
/N 978
/T 8760262
>>
endobj
第一个数字就是这个OBJ的顺序号,是为了便于在xref中查找,后面的0是为了区分不同的OBJ,现在都是0(个人感觉是为了以后扩展用的)
不是以后扩展用的,后面的0是obj的版本号。实际上很多PDF文件中都会存在例如1 1 obj这样的形式,在交叉索引表中的表示页会发生变化
0000000009 00000 表示在文件中第九byte开始的obj,它的版本号是0,如果是1
就要改成0000000009 00001了
另外 30979 0 obj所表示的obj是线性化的PDF,对于线性化的PDF要求所有的obj版本号必须为0。线形化的具体内容可以参考PDFReference 附录F

  回复  引用    
#4楼  2006-12-15 15:10 | Robert[匿名] [未注册用户]
下面给出了我认为是必要的信息,从中可以得出Tm, MediaBox的大小。实际的第一个字符串(XXX CONFIDENTIAL)被打印在了横向页面的右上角。此前没有位置指定,估计是默认值,弄了半天没弄出来,万望高手指点。
1 0 obj
<<
/Type /Page
/Parent 6 0 R
/Resources 3 0 R
/Contents 2 0 R
/Rotate -90
>>
endobj
2 0 obj
<< /Length 373 /Filter /FlateDecode >>
stream
BT
/F2 1 Tf
0 -9 9 0 565.6 184.084 Tm
0 g
/GS1 gs
0 Tc
0 Tw
(XXX CONFIDENTIAL)Tj
-64.197 -1.1 TD
( )Tj
64.197 -1.1 TD
(Date: 01/07/2005 19:15:13)Tj
-34.199 0 TD
(Report)Tj
-29.999 0 TD
(Title:)Tj
64.197 -1.1 TD
(Page: 2)Tj
ET
endstream
6 0 obj
<<
/Type /Pages
/Kids [ 1 0 R 7 0 R 10 0 R 13 0 R 16 0 R 19 0 R ]
/Count 6
/MediaBox [ 0 0 612 792 ]
>>
endobj
  回复  引用    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      


相关链接: