一個簡單PDF文件的結構分析

一個簡單的PDF文件結構的分析

AdobePDF參考告訴我們一個PDF文件可以通過下面4個方面來理解:

1.         對象, 一個PDF文檔是由一組基本數據類型組成的數據結構。

2.         文件(物理結構, 決定對象是如何存放在一個PDF文件中的, 它們是如何被訪問的,如何被更新的。這個結構是獨立於對象的語義的。

3.         文檔結構, 說明一些基本的對象類型是如何來表現PDF文檔的成分的:例如頁,圖片,字體,批註等。

4.         內容流,一個PDF文件內容流包含一系列的指令,描述頁面的外觀或其他圖形實體的外觀和文件內容。

   但是當時對我來說要看懂這幾行字是有很大的困難的,需要了解確切含義,必須看完後面的幾十頁上百頁的內容並且要分析一個實際的PDF文件才能完全領會它的意思。

   後來經過長時間的文檔閱讀,相關開發,並且具體地分析PDF文件後才把PDF文件的語法,文件的解析搞清楚。雖然說學習是痛並快樂着,但是對於當時的我來說真得希望有一個人能夠告訴我一個簡單的例子,通過一個簡單的例子來描述PDF的基本組成,它的解析原理和過程。從我的切身體驗來說,從一個初學者的角度出發,最好的方式應該是一個簡單的例子。因此我主要將以一個簡單的例子並且加以圖例來說明PDF的主要特性並給出一個簡單的PDF文件的全景。

       在繼續閱讀該文章前,先問自己下面的兩個問題:

l         你瞭解至少一種文件格式嗎?(例如HTML

l         爲什麼要學習PDF的相關知識?

如果你對第一個問題的答案爲“是”, 並且第二個問題你能給出一個非常明確的答案,那麼這篇短文就是爲你準備的。否則,如果對任何一種格式都不瞭解,建議你先了解一下HTML,或XML,你可以從這兩種語言裏得到很多啓發,對學習PDF的構成或研究學習其他格式文件有很大的好處;如果你不清楚你要學習是爲了什麼,那麼我就認爲你學習沒有目的性和動力,說不定你今天學了以後明天就忘得一乾二淨,因此也不建議你繼續看下去,等到你想清楚了歡迎你來看這則短文。

1PDF格式和HTML,XML格式:

一個PDF文檔從根本上來說是一個8字節序列。 其實PDF格式和我們已經熟知的HTMLXML等結構化的文件格式一樣,包含有關鍵字,分隔符,數據等等。

不同的是PDF文件是按照二進制流的方式保存的,而html文件則是可讀的文本方式保存的,你可以用文本編輯器分別打開一個html文件和PDF文件比較一下就知道了。XML文件一般只包含數據本身,並沒有把如何顯示的信息放在其中,因此要顯示一個XML文件還需要一個Schema文件才能顯示,否則看到的將是所有的字節流,包括所有的標誌;HTML包含了數據的同時也包含了一些關於如何顯示的信息,但是HTML是按照是不經過壓縮的文本存放的,是可讀的,你打開一個HTML文件就能知道所有將顯示在瀏覽器裏的文字。 另外就是HTML不能包含二進制流,它對圖像文件的引用都是通過引用外部文件的方式來實現的。

2PDF規範的發展

PDF規範從1993年到現在,已經有過7個版本,六次版本升級,從最初的pdf1.0版本到現在的PDF1.6, 每次的版本升級都會加入一些新的特性,PDF參考說明書也是從最初的100多頁到現在的1000多頁,但是PDF文件格式的主要特性還是沒有改變,可以這麼理解,PDF1.6PDF1.0的擴展集,學習了PDF1.0以後也能基本上理解PDF1.6的內容, 而PDF1.0規範是相對簡單的,因此說我選擇一個符合PDF1.0規範的最簡單的一個PDF文件來進行分析。

PDF規範的6次升級:

1.1 1995 加入了文檔加密(40字節),線索樹,名字樹,鏈接,設備獨立色彩資源。

1.2 1996 表單, 半色調屏幕,和其他的一些高級色彩特性, 對中文,日文和韓文的支持

1.3 2000 數字簽名, 邏輯結構, JavaScript, 嵌入式文件,Masked Images, 平滑陰影, 支持 CID字體的附加色彩。

1.4 2001 文件加密 (128 字節), 標籤式 PDF, 訪問控制,透明,元數據流

1.5 2003 文檔加密 (公鑰), JPEG 2000 壓縮, 可選的內容組,附加的註解類型

1.6 2005 文檔加密 (AES),增加最大文件支持,加入3D支持,額外的註解類型

 

 

 

3PDF文件的基本組成:

   一個PDF文件從大的方面來說可以分4個部分:

l         文件頭,指明瞭該文件所遵從的PDF規範的版本號,它出現在PDF文件的第一行。

l         文件體,PDF文件的主要部分,由一系列對象組成。

l         交叉引用表,爲了能對間接對象進行隨機存取而設立的一個間接對象的地址索引表。

l         文件尾,聲明瞭交叉引用表的地址,即指明瞭文件體的根對象(Catalog),從而能夠找到PDF文件中各個對象體的位置,達到隨機訪問。另外還保存了PDF文件的加密等安全信息(以後詳細討論)。

如下圖:

1

4PDF文檔的邏輯結構

   作爲一種結構化的文件格式,一個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”。例如:

3 0 obj

<<

/Type /Pages

/Count 1

/Kids [4 0 R]

>>

endobj

第一個數字稱爲對象號,來唯一標識一個對象的,第二個是產生號,是用來表明它在被創建後的第幾次修改,所有新創建的PDF文件的對象號應該都是0,即第一次被創建以後沒有被修改過。上面的例子就說明該對象的對象號是3,而且創建後沒有被修改過。

對象的內容應該是包含在<< >>之間的,最後以關鍵字endobj結束.

 

 

 

6.     文件Hello World的文件分析:

61.文件的具體分析

%PDF-1.0        

文件頭,說明符合PDF1.0規範

 

 

 

1 0 obj

<<

/Type /Catalog

/Pages 3 0 R

/Outlines 2 0 R

>>

endobj

Catalog對象(根對象)

/Type /Catalog說明該對象的類型爲/Catalog/Pages 3 0 R,這裏/Pages指的是這個根對象包含的/Pages的目標是對象號爲3的對象,3 0 R的意思是對對象3的引用。

 

 

 

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,及Pages對象,/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 TfTf說明True font對象,字體明爲F1, 大小爲24個象素。

100 150 Td (Hello World) Tj100 100 說明這一行文字放置的位置,對於Td, 我們可以這樣理解,我們的當前X,Y座標分別加上100150就是文本的位置,因爲在該例子中只有一個對象,那麼它的位置就是(100,150), 如果下個對象位置信息爲100, 50 Td, 那麼它的位置應該就是(100+100, 150+50)也就是(200200)。(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

字體對象,不再多作解釋。

所有的對象之後是下面的交叉引用表:

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是其偏移地址,000005位產生號(最大爲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爲文件結束標誌。

 

 

 

62PDF解析過程

回顧上面的詳細解釋,我們可以將這個簡單的PDF解析過程簡化爲如下圖例:

4

 

 

 

7.結束語:

到這裏,對一個最簡單的PDF文件的介紹就結束了,大家對PDF文件的格式和特定也應該已經有所瞭解了。

當然,我這裏介紹的是不完整的,完整的信息,請訪問adobe的網站下載最新的PDF REFERENCE1.6

http://partners.adobe.com/public/developer/pdf/index_reference.html

下次介紹PDF的加密過程及原理。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章