PDF學(xué)習(xí)(二) 收藏
要解析一個(gè)PDF文件,首先要掌握PDF的物理結(jié)構(gòu),這是第一步。但是這個(gè)僅僅只是基礎(chǔ),更重要的是對PDF邏輯結(jié)構(gòu)的解析。PDF的邏輯大體上是一個(gè)樹狀結(jié)構(gòu),根節(jié)點(diǎn)是catalog字典,通過這里去解析頁、目錄、鏈接信息等等,在這里按照PDF的樹形結(jié)構(gòu),詳細(xì)討論一下整個(gè)文件的邏輯框架。
一、catalog根節(jié)點(diǎn)
catalog是整個(gè)PDF邏輯結(jié)構(gòu)的根節(jié)點(diǎn),這個(gè)可以通過trailer的Root字段定位,雖然簡單,但是相當(dāng)重要,因?yàn)檫@里是PDF文件物理結(jié)構(gòu)和邏輯結(jié)構(gòu)的連接點(diǎn)。Catalog字典包含的信息非常多,這里僅就最主要的幾個(gè)字段做個(gè)說明。
(1)Pages字段
這是個(gè)必須字段,是PDF里面所有頁面的描述集合。Pages字段本身是個(gè)字典,它里面又包含了一下幾個(gè)主要字段:
字段
類型
值
Type
name
(必須)只能為Pages 。
Parent
dictionary
(如果不是catalog里面指定的跟節(jié)點(diǎn),則必須有,并且必須是間接對象) 當(dāng)前節(jié)點(diǎn)的直接父節(jié)點(diǎn)。
Kids
array
(必須)一個(gè)間接對象組成的數(shù)組,節(jié)點(diǎn)可能是page或page tree。
Count
integer
(必須) page tree里面所包含葉子節(jié)點(diǎn)(page 對象)的個(gè)數(shù)。
從以上字段可以看出,Pages最主要的功能就是組織所有的page對象。Page對象描述了一個(gè)PDF頁面的屬性、資源等信息。Page對象是一個(gè)字典,它主要包含一下幾個(gè)重要的屬性:
字段
類型
值
Type
name
(必須)必須是Page。
Parent
dictionary
(必須;并且只能是間接對象)當(dāng)前page節(jié)點(diǎn)的直接父節(jié)點(diǎn)page tree 。
LastModified
date
(如果存在PieceInfo字段,就必須有,否則可選)記錄當(dāng)前頁面被最后一次修改的日期和時(shí)間。
Resources
dictionary
(必須; 可繼承)記錄了當(dāng)前page用到的所有資源。如果當(dāng)前頁不用任何資源,則這是個(gè)空字典。忽略所有字段則表示繼承父節(jié)點(diǎn)的資源。
MediaBox
rectangle
(必須; 可繼承)定義了要顯示或打印頁面的物理媒介的區(qū)域(default user space units)
CropBox
rectangle
(可選; 可繼承)定義了一個(gè)可視區(qū)域,當(dāng)前頁被顯示或打印的時(shí)候,它的內(nèi)容會被這個(gè)區(qū)域裁剪。默認(rèn)值就是 MediaBox。
BleedBox
rectangle
(可選) 定義了一個(gè)區(qū)域,當(dāng)輸出設(shè)備是個(gè)生產(chǎn)環(huán)境( production environment)的時(shí)候,頁面顯示的內(nèi)容會被裁剪。默認(rèn)值是 CropBox.
Contents
stream or array
(可選) 描述頁面內(nèi)容的流。如果這個(gè)字段缺省,則頁面上什么也不會顯示。
這個(gè)值可以是一個(gè)流,也可以是由幾個(gè)流組成的一個(gè)數(shù)組。如果是數(shù)組,實(shí)際效果相當(dāng)于所有的流是按順序連在一起的一個(gè)流,這就允許PDF生成的時(shí)候可以隨時(shí)插入圖片或其他資源。流之間的分割只是詞匯上的一個(gè)分割,并不是邏輯上或者組織形式的切割。
Rotate
integer
(可選; 可繼承) 順時(shí)鐘旋轉(zhuǎn)的角度數(shù),這個(gè)必須是90的整數(shù)倍,默認(rèn)是0。
Thumb
stream
(可選)定義當(dāng)前頁的縮略圖。
Annots
array
(可選) 和當(dāng)前頁面關(guān)聯(lián)的注釋。
Metadata
stream
(可選) 當(dāng)前頁包含的元數(shù)據(jù)。
一個(gè)簡單例子:
3 0 obj
<< /Type /Page
/Parent 4 0 R
/MediaBox [ 0 0 612 792 ]
/Resources <</Font<<
/F3 7 0 R /F5 9 0 R /F7 11 0 R
>>
/ProcSet [ /PDF ]
>>
/Contents 12 0 R
/Thumb 14 0 R
/Annots [ 23 0 R 24 0 R]
>>
endobj
(2)Outlines字段
Outline是PDF里面為了方便用戶從PDF的一部分跳轉(zhuǎn)到另外一部分而設(shè)計(jì)的,有時(shí)候也叫書簽(Bookmark),它是一個(gè)樹狀結(jié)構(gòu),可以直觀的把PDF文件結(jié)構(gòu)展現(xiàn)給用戶。用戶可以通過鼠標(biāo)點(diǎn)擊來打開或者關(guān)閉某個(gè)outline項(xiàng)來實(shí)現(xiàn)交互,當(dāng)打開一個(gè)outline時(shí),用戶可以看到它的所有子節(jié)點(diǎn),關(guān)閉一個(gè)outline的時(shí)候,這個(gè)outline的所有子節(jié)點(diǎn)會自動隱藏。并且,在點(diǎn)擊的時(shí)候,閱讀器會自動跳轉(zhuǎn)到outline對應(yīng)的頁面位置。Outlines包含一下幾個(gè)字段:
KEY
TYPE
VALUE
Type
name
(可選)如果這個(gè)字段有值,則必須是Outlines。
First
dictionary
(必須;必須是間接對象) 第一個(gè)頂層Outline item。
Last
dictionary
(必須;必須是間接對象)最后一個(gè)頂層outline item。
Count
integer
(必須)outline的所有層次的item的總數(shù)。
Outline是一個(gè)管理outline item的頂層對象,我們看到的,其實(shí)是outline item,這個(gè)里面才包含了文字、行為、目標(biāo)區(qū)域等等。一個(gè)outline item主要有一下幾個(gè)字段:
Title
text string
(必須)當(dāng)前item要顯示的標(biāo)題。
Parent
dictionary
(必須;必須是間接對象) outline層級中,當(dāng)前item的父對象。如果item本身是頂級item,則父對象就是它本身。
Prev
dictionary
(除了每層的第一個(gè)item外,其他item必須有這個(gè)字段;必須是間接對象)當(dāng)前層級中,此item的前一個(gè)item。
Next
dictionary
(除了每層的最后一個(gè)item外,其他item必須有這個(gè)字段;必須是間接對象)當(dāng)前層級中,此item的后一個(gè)item。
First
dictionary
(如果當(dāng)前item有任何子節(jié)點(diǎn),則這個(gè)字段是必須的;必須是間接對象) 當(dāng)前item的第一個(gè)直接子節(jié)點(diǎn)。
Last
dictionary
(如果當(dāng)前item有任何子節(jié)點(diǎn),則這個(gè)字段是必須的;必須是間接對象) 當(dāng)前item的最后一個(gè)直接子節(jié)點(diǎn)。
Dest
name,
byte string, or array
(可選; 如果A字段存在,則這個(gè)不能被會略)當(dāng)前的outline item被激活的時(shí)候,要顯示的區(qū)域。
A
dictionary
(可選; 如果Dest 字段存在,則這個(gè)不能被忽略)當(dāng)前的outline item被激活的時(shí)候,要執(zhí)行的動作。
(3)URI字段
URI(uniform resource identifier),定義了文檔級別的統(tǒng)一資源標(biāo)識符和相關(guān)鏈接信息。目錄和文檔中的鏈接就是通過這個(gè)字段來處理的。
(4)Metadata字段
文檔的一些附帶信息,用xml表示,符合adobe的xmp規(guī)范。這個(gè)可以方便程序不用解析整個(gè)文件就能獲得文件的大致信息。
(5)其他
Catalog字典中,常用的字段一般有以下一些:
字段
類型
值
Type
name
(必須)必須為Catalog。
Version
name
(可選)PDF文件所遵循的版本號(如果比文件頭指定的版本號高的話)。如果這個(gè)字段缺省或者文件頭指定的版本比這里的高,那就以文件頭為準(zhǔn)。一個(gè)PDF生成程序可以通過更新這個(gè)字段的值來修改PDF文件版本號。
Pages
dictionary
(必須并且必須為間接對象)當(dāng)前文檔的頁面集合入口。
PageLabels
number tree
(可選) number tree,定義了頁面和頁面label對應(yīng)關(guān)系。
Names
dictionary
(可選)文檔的name字典。
Dests
dictionary
(可選;必須是間接對象)name和相應(yīng)目標(biāo)對應(yīng)關(guān)系字典。
ViewerPreferences
dictionary
(可選)閱讀參數(shù)配置字典,定義了文檔被打開時(shí)候的行為。如果缺省,則使用閱讀器自己的配置。
PageLayout
name
(可選) 指定文檔被打開的時(shí)候頁面的布局方式。SinglePageDisplay 單頁
OneColumnDisplay 單列
TwoColumnLeftDisplay 雙列,奇數(shù)頁在左
TwoColumnRightDisplay 雙列,奇數(shù)頁在右
TwoPageLeft 雙頁,奇數(shù)頁在左
TwoPageRight 雙頁,奇數(shù)頁在右
缺省值: SinglePage.
PageMode
name
(可選) 當(dāng)文檔被打開時(shí),指定文檔怎么顯示
UseNone 目錄和縮略圖都不顯示
UseOutlines 顯示目錄
UseThumbs 顯示縮略圖
FullScreen 全屏模式,沒有菜單,任何其他窗口
UseOC 顯示Optional content group 面板
UseAttachments顯示附件面板
缺省值: UseNone.
Outlines
dictionary
(可選;必須為間接對象)文檔的目錄字典
Threads
array
(可選;必須為間接對象)文章線索字典組成的數(shù)組。
OpenAction
array or dictionary
(可選) 指定一個(gè)區(qū)域或一個(gè)action,在文檔打開的時(shí)候顯示(區(qū)域)或者執(zhí)行(action)。如果缺省,則會用默認(rèn)縮放率顯示第一頁的頂部。
AA
dictionary
(可選)一個(gè)附加的動作字典,在全局范圍內(nèi)定義了響應(yīng)各種事件的action。
URI
dictionary
(可選)一個(gè)URI字典包含了文檔級別的URI action信息。
AcroForm
dictionary
(可選)文檔的交互式form (AcroForm)字典。
Metadata
stream
(可選;必須是間接對象)文檔包含的元數(shù)據(jù)流。