文件头(Header):指明了该文件所遵从PDF规范的版本号
文件体(Body):由一系列的PDF间接对象组成。这些间接对象构成了PDF文件的具体内容如字体、页面、图像等
交叉引用表(Cross-reference Table):是为了能对间接对象进行随机存取而设立的一个间接对象地址索引表。
文件尾(Trailer):声明了交叉引用表的地址,指明文件体的根对象(Catalog),还保存了加密等安全信息。根据文件尾提供的信息,PDF的应用程序可以找到交叉引用表和整个PDF文件的根对象,从而控制整个PDF文件,如下示意图
PDF的文档结构是一种树型结构,反映了文件体中间接对象之间的等级层次关系。
树的根节点就是PDF文件的目录对象(Catalog),是PDF文档的根对象,包含PDF文档的大纲(Outlines)和页面组对象(Pages)。
根节点下有四个子树:页面树(Pages Tree)、书签树(Outline Tree)、线索树(Article Threads)、名字树(Named Destination)。
PDF文件的基本元素是PDF对象(PDF Object),包括直接对象(Direct Object)和间接对象(Indirect Object)。
直接对象如下几种基本类型:
2.数值型(Number):包括整形和实型,不支持非十进制数字,不支持指数形式的数字.
3.字符串型(String):由一系列0-255之间的字节组成,一个string总长度不能超过65535.string有以下两种方式
1)由()包含起来的一个字串,中间可以使用转义符”/”:
(abc) 表示abc
(a//) 表示a/
2)由<>包含起来的一个16进制串,两位表示一个字符,不足两位用0补齐:
<Aabb> 表示AA和BB两个字符
<AAB> 表示AA和B0两个字符
和string不同的是,name是不可分割的和唯一的.
不可分割就是说一个name对象就是一个原子,比如/name,不能说n就是这个name的一个元素;
唯一就是指两个相同的name一定代表同一个对象.
从pdf1.2开始,除了ascii的0,别的都可以用一个#加两个十六进制的数字表示.
/name *#表示name*
/name#20is *#表示name is*
/name#200 *#表示name 0*
虽然pdf只支持一维array,但可以通过array的嵌套实现任意维数的array(但是一个array的元素不能超过8191)
例:
[549 3.14 false (Ralph) /SomeName]
例:
<< /IntegerItem 12
/StringItem (a string)
/Subdictionary << /Item1 0.4
/Item2 true
/LastItem (not!)
/VeryLastItem (OK)
>>
>>
内容和string很相似,但有区别:
stream可以分几次读取,分开使用不同的部分,string必须作为一个整体一次全部读取使用;
string有长度限制,但stream却没有这个限制.一般较大的数据都用stream表示.
如果一个key的值为null,则这个key可以被忽略;如果引用一个不存在的object则等价于引用一个空对象.
间接对象是一种标识了的PDF对象,这个标识叫作间接对象的ID。标识的目的是为了让别的PDF对象引用。任何PDF对象标识后都变成了间接对象。
PDF共有60个页面描述指令。
这60个页面描述指令描述了页面上的一系列图形对象。这些图形对象可分为四类:
路径对象(Path Object)
文本对象(Text Object)
图像对象(Image Object)
外部对象(XObject)
PDF文件中的内容(如文字、图形、图像)都保存在页面对象的Contents关键字对应的流对象(Stream)中。
内容流(Content Stream)中用到了很多基本对象如数字、字符串,这些都是用直接对象(Direct Object)表示的。
但还有其他一些对象如字体(Font),本身就是用字典对象(Dictionary)或流对象(Stream)来表示的,无法用直接对象表示,
而内容流中又不能出现任何间接对象,于是就将这些对象命名,并在内容流中用相应的名字来表示它们。
这些用名字来表示的对象就称作命名资源(Named Resources)。
在页面对象中有一个资源项(Resources Key),该项列出了内容流中用到的所有资源,并建立了一个资源名字与资源对象本身的映射表。
PDF中的命名资源有:
指令集(ProcSet)
字体(Font)
色彩空间(Color space)
外部对象(XObject)
扩展的图形状态(Extended graphics state)
底纹(Pattern)
用户扩展标记列表(Property list)。
非命名资源有(非命名资源都是被隐含引用的,因此没有命名的需要):
Encoding
Font descriptor
Halftone
Function
CMap
%PDF-1.4 *#header格式:%PDF-1.5*
%My company (CodePage = 932)
1 0 obj *#对象格式:序号 版本号 obj <<...>>endobj*
<<
/Producer(My company)
/Creator(MyPDF.DLL (Ver.03-04-12.A00))
/CreationDate(D:20160511134447+08'00')
/ModDate(D:20160511134447+08'00')
>>
endobj *#Object结束关键字*
7 0 obj
<<
/Type /XObject
/Subtype /Image
/Filter /DCTDecode
/BitsPerComponent 8 *#颜色位数*
/ColorSpace /DeviceRGB
/Width 507 *#image的宽度*
/Height 317 *#image的高度*
/Length 38682
>>
stream
... ...
endstream
endobj
4 0 obj
<<
/Type /Page
/Parent 3 0 R *#其父对象号为3,即Pages对象*
/MediaBox[0.00 0.00 595.28 841.89] *#页面显示大小,以像素为单位*
/Resources 5 0 R *#该页包含的资源*
/Contents 6 0 R *#页面内容对象的对象号为6*
/ColorSpace <2 0 R>> >> *#色彩空间*
>>
endobj
5 0 obj
<<
/ProcSet[/PDF /Text /ImageB /ImageC /ImageI]
/XObject << /Im1 7 0 R >> *#外部对象*
>>
endobj
6 0 obj
<<
/Filter /FlateDecode *#流对象的压缩方式为zip的压缩算法*
/Length 155 *#流对象的长度*
>>
stream *#流对象*
... ...
endstream *#流对象结束标志*
endobj
2 0 obj
<<
/Type/Catalog
/Pages 3 0 R
>>
endobj
3 0 obj
<<
/Type /Pages
/Kids [ 4 0 R ] *#kids对象说明它的子页对象为4*
/Count 1 *#页面数量为1*
>>
endobj
xref *#交叉引用表开始标志*
0 8 *#表示从对象号为0的开始,连续有8个对象(0,1,...,7),分别用8行来表示*
0000000000 65535 f *#每行的前10个数字代表这个这个对象相对文件头的偏移地址*
0000000056 00000 n *#后面5个数字只有当这个对象被删除的时候才有用,表示这个对象被删除后又被重新生成后的对象号*
0000039567 00000 n *#最后一位f或n表示对象是否被使用(n表示使用,f表示被删除或没有用)*
0000039623 00000 n
0000039103 00000 n
0000039229 00000 n
0000039329 00000 n
0000000235 00000 n
trailer *#整个pdf文件分析的入口点*
<<
/Root 2 0 R *#这个pdf文件的catalog对象的对象号,这是pdf中最顶层的对象*
/Info 1 0 R
/Size 8 *#这个pdf中总共使用了多少个对象*
>>
startxref *#cross reference table的开始位置*
39692
%%EOF *#文件结束符*
如果这个pdf是加密的,那么在trailer里会有一个/Encrypt的name。
它的值一般形式是n 0 R,表示这个pdf文件的加密信息在n 0这个obj里面记录.
找到这个obj,其下有一个/P的name,它的值是一个数字(32位)其中第三位代表是否有打印权限。
http://www.cnblogs.com/bile/p/3480096.html