PDF文件中交叉引用流對象(cross-reference stream)的解析方法

 

PDF文件中交叉引用流對象(cross-reference stream)的解析方法

 

1 介紹

在PDF-1.5版本[1]之前,對象的交叉引用信息是存儲在交叉引用表(cross-reference table)中的。在PDF-1.5版本之後,引進了交叉引用流(cross-reference stream)對象,可以用它來存儲對象的交叉引用信息,就像交叉引用表的功能一樣。

採用交叉引用流對象存儲對象的交叉引用信息至少有以下幾點好處:

1) 存儲的信息更緊湊,並且可以引入壓縮算法進行壓縮

2) 提供了訪問存儲於對象流(ObjectStreams)中的被壓縮的對象的功能

3) 提供了將來的可擴展的交叉引用流的表項類型,以便存儲更多不同信息

交叉引用流對象在PDF文件中的偏移位置,由關鍵字startxref 指出;而相應的交叉引用表則由關鍵字xref指出。交叉引用流對象的類型爲XRef, 也即其對象類型具有如下形式:”/Type /XRef

下述的片段就是一個交叉引用流對象例子:

41 0 obj

<</Type /XRef/W[1 4 2]/Index[0 42]/Size 42/Filter/FlateDecode/DecodeParms<</Columns 7/Predictor 12>>/Length111/Root 1 0 R /Info 11 0 R /ID[<88009A03A92CE346AF48303D7897A1B6><F5D995A232C33D29EC686AB9E1F5B2B0>]>>stream

x渃b ??仈 ##?g``??恇?褸?孡`?@


?>0?4
壷?髆哤 ?Ue?蟘x        瓈?伱緂P>L??#?‑凐?濽?

endstream

endobj

可以看到此對象需要進行”FlateDecode”解碼,並且之後還要進行PNG的過濾器再解碼(由DecodeParms參數指出),才能得到最終的數據。

 

2 解析

交叉引用流對象通常在存儲之前都會進行壓縮,而爲了提高壓縮率,會進行數據的預處理,這個預處理就稱爲過濾(filter)。讀取時再進行反向的處理,如下圖所示:



2.1 壓縮/解壓縮

對於壓縮/解壓縮的處理,可以採用開源的zlib[2]進行處理,其中的壓縮算法稱爲”deflate”, 解壓縮算法稱爲” inflate”,這裏不再詳細說明。

2.2 Filter處理

當PDF文件中的對象(Object)指示採用LZWDecode或者FlateDecode進行解壓縮時,在解碼參數中的Predictor指示瞭解壓縮完成後,再對數據進行的filter過濾器處理算法。常用的過濾器算法有TIFF和PNG兩大類。在文檔《PDF Reference, Sixth Edition, version 1.7》中的3.3.3節的”TABLE 3.8Predictor values“中,說明了不同的Predictor值對應的filter類型及算法。如下圖:


圖3 Predictor值對應的filter

2.3 PNG Filter

PNG filter過濾器算法可以在W3C網頁[3]查到。這裏以”Predictor12”也即PNG Up的過濾器算法爲例簡單介紹如下:

由於PNG Filter是針對圖片進行處理的,因此輸入的數據也必須指定爲”行x列”的形式。從網頁介紹可知,PNGfilter有5種,即:0-None, 1-Sub, 2-Up, 3-Average, 4-Paeth。過濾器是作用在輸入數據的每一行的每個字節(byte)上的,並且每一行可以獨立的指定不同的過濾器。爲了做到這點,在過濾時會在每一行數據的最前面插入一個字節表明採用的過濾器類型;在數據解碼時則需要將此字節去除。

換言之,如果原始數據爲rows 行,columns列,那麼經過過濾器之後的數據爲rows行,columns+1列,並且第一列的字節指示了此行採用的過濾器算法。


圖4 PNG filter 執行結果

這裏以讀取第一節的數據(/Filter/FlateDecode/DecodeParms<</Columns 7/Predictor 12>>)爲例進行舉例說明:

/Filter/FlateDecode說明對steam和endstream之間的數據用zlib的inflate解壓縮。

/DecodeParms<</Columns 7/Predictor 12>>:解壓縮後的數據還需要進行PNG Filter Up算法的反向處理(因爲是讀取)

Zlib的inflate算法是現成的,這裏不介紹。PNG filter算法比較簡單,我們自己來實現它。

“/Columns 7”說明圖像寬度爲7像素(當然這裏不是圖像,只是借用而已)。

“/Colors x” 參數未出現,默認值爲1,代表每個像素一種顏色。

“/BitsPerComponent”參數未出現,默認值爲8,代表每種顏色8比特表示。

“/Predictor 12”表面數據經過了PNG的Up filter算法處理。

於是每一行的字節數爲:Columns x Colors x BitsPerComponent /8bit = 7x1x8/8 = 7字節。也即圖像寬度爲7字節。經過zlib解壓縮後的數據行寬度爲7+1=8字節。

下圖爲up filter的反向處理源代碼示例:


其它的PNG Filter算法可以同樣的完成。

3 結論

PDF-1.5之後可以採用交叉引用流對象來替代交叉引用表,使得存儲PDF和更高效,但是也帶來了解析上的複雜性。通過本文例子可以很方便的進行交叉引用流對象進行解析。

 

參考文獻

[1] PDF Reference, Sixth Edition, version1.7[EB/OL].https://wwwimages2.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/pdf_reference_1-7.pdf.

[2] zlib[EB/OL]. http://www.zlib.net/.

[3] Filter Algorithms[EB/OL].https://www.w3.org/TR/PNG-Filters.html.

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