2013年11月25日 星期一

Android pdf renderer lib (將pdf out 到android 的views上)

2015/08/25
更新
Android API 21就釋放出可以直接處理pdf的資訊了

https://developer.android.com/reference/android/graphics/pdf/PdfRenderer.html


Android pdf renderer lib
2013/11/25

因為剛做完一個段落,紀錄一下

-----------------------------------------------------------------------------------------------
如果你只是要在Android程式上打開PDF檔的話(可以接受使用其他的軟體的話),
那並不是本文章所想講的內容,Google上有許多簡單call Intent外部資源的資料。
-----------------------------------------------------------------------------------------------

Renderer的翻譯是渲染,
一開始我並不知道這個單字的意思,
但是這個單字在資訊上的意思應該是將文件輸出至銀幕上顯示的意思,
也就是將文件渲染至銀幕上,
所以在此解釋一下,
幫助未來一些像我這樣不太懂的人了解。

這篇是記錄 "我如何解決PDF解析並且renderer到Android的行動裝置銀幕上" 的文章。

一開始我去Stack flow 上找了許多人介紹的 PDF library 包括
 iText ,    http://itextpdf.com/
PDFViewer (jblough的) , https://github.com/jblough/Android-Pdf-Viewer-Library
GHOST 4J , http://www.ghost4j.org/
9PDF , (現在不知道去哪找了...)
Jpedal , http://sourceforge.net/projects/jpedal/
pdf box, http://pdfbox.apache.org/
ApachePOI, http://poi.apache.org/ (也有其延伸的 Tika http://tika.apache.org/)
等等的

甚至還去找了PDF的格式
(因為我忘記在哪找到的了,所以我上傳我保留的到雲端)
https://docs.google.com/file/d/0B4ygFvrB4o3VTUh5allqNVFFMHc/edit
這好像是某一年Adobe公布的標準,詳細情況請在自行Google

其中我有實作出來並可以run的demo檔是 PDF Viewer,
不過做出來的顯示畫面並不是很好,
會有顏色跑掉或是模糊的情況。

(應該是在這行造成的
Code:
page.compress( Bitmap.CompressFormat.PNG, 100, stream);

可以使用 PNG或 JPEG的格式,但輸出的效果我認為都不好。)

其他的函式庫大多會遇到一個我認為蠻大的問題,
就是他們都引用了JAVA 的 awt或 swing函式庫,
這兩個函式庫都是Android上所沒有支援的畫圖函式庫,
也因此這些函式庫大多可以完整的解析PDF檔案,
但是無法 renderer到Android的銀幕上。

(Android本身是使用Google 公布的 Graphics2D 函式庫,幾近完全拋棄JAVA的原生函式庫,雖然有人試圖編譯awt to Graphics2D....但...自行Google...)

未來如果這幾個解析器都發展完整Android相關的函式庫出來的話,
我個人認為GHOST 4J這個解析器應該是最簡單且人性化的函式。

(可能半個月內、半年內、或者一兩年內突然就有完整的解決方案了。)
(當然也可能早有人寫出來免費的PDF render且有公布在網路上,
但我這個接觸JAVA Android 不到一個月的人沒找到的資源也說不定。)

-------------------------------------我如何解決這個問題------------------------------------
我本來要使用的是
muPDF 這個函式庫,這也是網路上最多人推薦的 PDF renderer (http://mupdf.com/docs/)
不過
1.他並沒有提供很簡易的使用方式,
2.他是利用JAVA去調用Linux實做底層的C語言程式去實做PDF轉換及java image格式接口,我們的程式如果包含如此多的額外資源的話,可能會造成後續的延伸問題。

因此,我在與公司討論後(因為我的工作與韌體有點關係)
就將PDF to image 這個步驟切到韌體上面去執行,

我使用的是Fedora 系統 ,切成fedora系統以後轉換pdf to image這個步驟就簡單了許多,使用的library是 他的Imagemagick 函式

程式碼也相當的簡單
$ convert  INPUT.PDF out.png
如此而已

有不同需求的人也可以去找一找pdftoppm 這個函式
(我是沒有實作出來,但似乎也是一種解決方案)

嚴格說起來,我並沒有使用Android上的程式去解決PDF renderer的問題,
但有短時間內要解決此問題的需求的話,
可以參考看看我解決的策略。

而有中長期解決這個問題的需求的人,可以考慮研究mupdf這個函式庫,
或者自行參與某個open source去實作出來這部分。

-----------------------------------------抱怨---------------------------------------------
我在研究不同lib的時候發現每個lib對於renderer的解釋似乎並不一樣
這樣其實很不好,
有些renderer是被定義成輸出給影印機影印,
而有一些則是被定義成輸出成xtml,
甚至有一些lib打開renderer source後發現裡面空空如也....

另外PDF FILE ,Document這些關鍵字的定義都很不好,
很難讓使用者在網路上搜尋到,
我每次打iText Document的相關搜尋的時候,
第一個跳出來的文章總是他的API 函式Document ,
而實際的Document使用就很難找到,
更不要說某些散布在網路上不同的函式庫對於同一個關鍵字的標準不同了。
(簡單來說就是資訊標準並沒有被定義好。)
對於查資料而且根本不熟的人怎麼會知道

"喔!!!原來 PdFfile 跟 PDFFILE 跟pDfFile 是不的lib 裡的關鍵字,
而且其定義資料格式完全不同而且還不能互通!!!"

也因此可以看到網路上有人拿了A lib的 sample code 去問B lib 為何不能執行?
使用B lib的人則非常困擾 怎麼可能不能run???

有些lib好像處理好了如何renderer 的問題,
但是並沒有完整解析pdf格式的lib,
而有些則相反,但又因為彼此定義資料格式不同的關係,
最後也是無法直觀使用的函式庫,
真的很讓人沮喪。

--------------------------如果你的公司可以接受付費函式庫的話-------------------
網路上有蠻多這類的函式庫的
例如:
ASPOSE(http://www.aspose.com/),
OliveDoc(http://www.olivephone.com/m_page.php),
QPDF ( 我一度以為這個函式庫是免費的,直到他在Demo程式上出現了浮水印...   http://sourceforge.net/projects/qpdf/)

如果有人願意指點迷津給小弟一個在Android上的完整解決函式或demo code的話,
小弟也會虛心接受的,感謝有仔細觀看這篇文章的人,
歡迎回應。

---------------------------------補充----------------------------------------------------
我突然在想是不是有人會將ImageMagick寫到android上?
找了一下,發現仍然有call awt的問題,
不過也有高手寫出了fake awt 解決部分的lib function
https://github.com/subicura/android-lib-magick
不過只有jpg轉png...