為了要擷取出內嵌在 PDF 檔中的影像, 稍微研究了一下 PDF 的規格, 一開始的目的是要解出其中的 TIFF 檔, 看起來好像挺簡單的, 因為從 PDF 中可以很容易的就把 TIFF 的 stream 取出來 (找到 /Filter /CCITTFaxDecode 的區段, 後續出現被包在 stream.....endstream 中的就是了), 但是結果當然並不是把那段 stream 存檔這麼簡單就行了, 因為 TIFF 本身還有一些檔頭和檔尾資訊必須處理, 所以又得再花精神去研究 TIFF 的規格(TIFF 6.0 Specification).....然後依據 pdf object 的描述自行寫入相關的檔頭和檔尾就可以了(看起來還滿簡單的吧)!
檔頭的部分很簡單, 因為只有 8 個 bytes, 很容易理解, 麻煩的是後面檔尾部分的 IFD (Image File Directory), 那是和 TIFF 內容相關的一些描述, 必須正確的寫入才能看到完整的 TIFF 呈現出來, 細節說來話長, 就先跳過吧, 附上一張簡單的示意圖(擷取自 TIFF 6.0 Specification)!
第一個需求完成之後, 很快的就產生了第二個需求, 因為在 PDF 中除了有 TIFF 之外, 還有 JPG 格式的影像在裡面, 擷取 PDF 影像的功能算只完成了一半, 已經不能回頭了, 只能再繼續前進! 這次遇到的 /Filter 是 [ /ASCII85Decode /DCTDecode ], 這表示該 stream 要經由兩次解碼才能得到原來的影像, 分別是 ASCII85Decode 和 DCTDecode.
什麼是 ASCII85 咧? Wikipedia 上有很詳細的解釋(示意圖如下), 而且還有附上 C# Souce code 的網址, 所以很簡單就完成了第一部分的解碼任務, 至於第二個 /DCTDecode, 其實就是 JPG 的編碼方式, 所以可以直接把第一次解碼後的 stream 直接存成 jpg 檔之後就可以得到原來的影像了!
目前還沒有看到第三種格式的影像檔出現在要處理的 PDF 中, 所以就先研究到這兒!
keywords: pdf, tiff, jpg, ascii85 decode, dctdecode