作者:馬健
郵箱:stronghorse_mj@hotmail.com
發布:2012.06.11
一、背景
目前對於掃描電子文檔,網上比較流行的格式是PDF和DjVu。為了便於對掃描文檔進行文字檢索、復制,這兩種格式均允許在掃描圖像層之外,再加一層隱藏文字層,成為通常所說的“雙層PDF”和“雙層DjVu”。
對於雙層PDF和DjVu來說,閱讀者所直接看到的都是原汁原味的掃描頁面,保留了原始書籍頁面的全部內容和版式,但當閱讀者用鼠標在頁面上拖拽選擇時,又能選中、復制人眼看不到的隱藏文字。同時閱讀者使用文本搜索功能,也能對隱藏文字進行檢索。因此可以說雙層PDF和DjVu既保留了掃描文檔的原始風味,又兼得文字版的便利。
目前雙層PDF和DjVu的隱藏文字均通過OCR技術獲得,而在目前的OCR技術條件下,准確率不太可能是100%。就算達到99%的准確率,三千字的短文也有 三十字的錯誤,因此如果直接去讀OCR的內容,估計很多人會讀不下去,這也是要把文字隱藏起來,仍然去讀圖的原因。
換句話說,雙層PDF和DjVu人讀是沒有問題,如果掃描圖像的質量、分辨率足夠的話,復制、檢索問題也不大,但完全相信其中的文本則不太現實,也就是參考吧 ,除非人工對文字內容進行校對,校對過程可參見我寫的《校對雙層PDF中的隱藏文本》。
從使用層面來說,PDF和DjVu中的隱藏文本如上所述,差別不大。但在技術層面上,我感覺二者還是有差異的,下面結合我在開發DjVuToy的相關功能中的一些體會加以說明。
二、DjVu中的隱藏文本
在DjVu中,文本的表示相對簡單:
- 每頁有一個TXTz或TXTa段,二者內容是一樣的,只不過一個經過壓縮,另一個沒有壓縮。
- 段頭包含版本信息、字符串、字符串長度。這個字符串就是該頁中全部文本的集合,說白了就是把該頁中的全部文字拼起來就是這個字符串,采用utf-8編碼。
- 段頭后面是一個列表,具體說明每個文字在頁面上的顯示位置、尺寸、內容,稱為zone。
zone包含下列內容:
- ZoneType:可以是Page、Colume、Region、Paragraph、Line、Word和Character
- x、y:zone的左上角在頁面上的坐標位置(像素)
- width、height:zone的寬度、高度(像素)
- offText:zone所含內容在頁面字符串中的起始位置
- lenText:zone所含字符串的長度。offText、lenText合起來決定了zone的文字內容
- nChildren:下級zone的數量,如一個Word下面含幾個Character
從DjVu對文字的定義看,DjVu中的隱藏文本在技術上有幾個特點:
1、是真正的“隱藏文本”,沒法直接顯示
DjVu中的文字有utf-8編碼,有文字的顯示位置、顯示尺寸,但是沒有字體信息,因此如果想顯示出來,還需要指定字體信息。
正是因為文字根本就沒打算顯示,所以在DjVu瀏覽器中文字與圖像完全不會互相干擾,雙層DjVu也就沒有雙層PDF所需考慮的究竟是“圖壓字”還是“字壓圖”的問題。另外也不需要考慮文本究竟是橫排還是豎排的問題:反正你也看不見,你 管它是橫排還是豎排? 可能是受DjVu文字的影響太深刻,DjVu官方軟件Caminova DocumentExpress Enterprise 7.5(簡稱deent75)在將DjVu轉為PDF時,雖然支持隱藏文字的轉換,也支持橫排的亞洲語言,但就是不支持豎排的亞洲語言。
除豎排的問題外,DjVu中簡單的文字表示也造成校對的問題:沒辦法直接把文字顯示出來進行校對,只能把文字導出成XML,校對后再導入DjVu。
DjVuToy的一個德國用戶向我介紹過一個校對DjVu中隱藏文本的方法:對同一個DjVu文件,用MODI和ABBYY各OCR一遍,導出純文本,然后用文本比較工具進行比較,能夠較快地發現OCR的錯誤。按他的說法,至少對於德語來說,MODI和ABBYY各有千秋,所以他用這個方法屢試不爽。有興趣的不妨也試試。
2、文本信息比較簡單,節省存儲空間,也容易復制、導出
從定義就可以知道了,沒有PDF那么多花狸狐哨的東西,相對比較簡潔,有利於減小文件長度。而且DjVu中的文本統一采用utf-8編碼,這個是有標准的,做不了什么手腳,轉換成Unicode也比較容易,因此理論上說從DjVu復制或導出的文字不可能是亂碼,而PDF則不一定。
3、沒有平台、語言的問題
utf-8是一種已經標准化的編碼,與Unicode完全通用,因此在所有支持Unicode的平台上,都可以檢索、復制。而由於沒有字體等限制,因此也不存在平台兼容性問題。
4、對文本位置定義比較細致,以便用鼠標選擇
從ZoneType的定義就可以看出,對Page、Colume、Region、Paragraph、Line、Word和Character分得比較細,鼠標選擇的時候,可以從Character選到Word,再選到Line、Paragragh等。
其實“細致”是比較好聽的遮羞說法,在我看來,這種“細致”完全是迫不得已:由於沒有字體信息,根本就不知道字符的寬度究竟是多少,因此鼠標拖動的時候,沒有辦法准確計算用戶究竟選中了字符串的哪個部分,因此只能“細致”一點,從Character開始定義了。
換句話說,如果某個DjVu文件的文字定義粒度到Character,那么用戶選擇的精度就到字母;如果定義粒度到Word,就只能一次選一個詞;如果粒度到Line,就只能一次選一行。原因很簡單:在沒有字體信息的情況下,實在算不出來一個Word或Line中的一部分在屏幕上的寬度究竟是多少,除非知道每個Character的寬度。
這種“細致”不僅會平白增加一些數據量,而且給文本校對帶來了麻煩:DjVu的文本校對都是把隱藏文字導出成XML,校對后再導入回去。如果文字粒度到Character,校對時會非常吃力;如果粒度到Line,校對會很省力,但鼠標選擇的時候就只能選整行了。這個問題我至今沒找到什么解決辦法。
三、PDF中的隱藏文本
PDF中的文本定義比較復雜,在《PDF Reference sixth edition》中用整整一個第5章進行描述,共90頁,翻譯過來也夠出一本書了。這么長的內容我不想寫,各位也未必想看,還是直接說其技術特點吧。
1、隱藏文本可以顯示出來
按《PDF Reference sixth edition》的規定,PDF中的隱藏文本只不過是普通文本的一個特例:在頁面內容流中,如果Tr參數是3則文本不顯示出來,成為隱藏文本,否則就顯示出來。
這種情況對校對比較有利:可以通過修改Tr參數把隱藏文字顯示出來,則文字位置、內容是否准確一目了然,發現有問題用Foxit Phantom、Foxit PDF Editor修改起來也很方便。
PDF中隱藏文本的這個特性是靠下面這個特點保證的:
2、文本定義比較完備
PDF中的文本除了編碼、顯示矩陣(位置、比例)外,還有字體、字號等。
在PDF中,一個字的“編碼”與“顯示”是分離的,中間連接的橋梁就是“字體”。簡單點說,編碼是一個字的內部表示方法,但這個字顯示出來究竟是這么樣子,要看你用的是什么字體。比如說我的姓是“馬”,這個字的GB碼是C2ED,Unicode碼是9A6C,用宋體顯示出來的就是宋體的“馬”,用 篆體顯示出來的就是篆體的“馬”,但要用韓文的字體顯示呢?根本就顯示不出來,因為沒有這個字。
這種分離與連接,就產生了下一個特點:
3、文本能不能被復制、檢索、保存,由制作者決定
如前所述,一個字“看起來”是什么樣子,是由文字編碼與字體共同決定的:PDF瀏覽器顯示文字時,根據編碼從字體文件中查找到這個字的字形輪廓,然后按照輪廓定義一筆、一筆把這個字“畫”出來。
而在復制、檢索、保存的時候,是針對文字的編碼來的:按照PDF標准的規定,PDF文件中的字體說明部分有義務提供將文字編碼轉換成Unicode的轉換表,所有復制、檢索、保存均針對Unicode。
但是“有義務”不等於“一定要”,何況還可以故意提供一個假的轉換表。不論是不提供轉換表還是提供假的轉換表,最終的結果就是閱讀者在看的時候是看到正確的“文字”(其實是畫出來的字形),但是復制、存盤出來的卻是一堆亂碼,檢索也檢索不到什么。這種手腳在采用內嵌字體的時候更容易做,因為內嵌字體的編碼本來一般就不會用標准編碼。
4、存在平台兼容性問題
PDF中的字體可以是外部字體,也可以是內嵌字體。外部字體即在PDF中只存放字體名稱,但不存放字體文件,顯示的時候PDF瀏覽器根據字體名稱,從外部字體文件讀取字形。內嵌字體則是將所有需要的字形組合成一個字體文件,嵌入到PDF文件中。
毫無疑問,采用外掛字體的PDF的文件長度要比采用內嵌字體的PDF要小,因為不需要存儲字形。但是外掛字體存在平台兼容性問題:你怎么保證閱讀者在閱讀PDF的時候,所處的環境正好就有所需的字體文件?
內嵌字體沒有平台兼容性問題,因為所有需要的東西都已經嵌入PDF里了,不必再從外部讀取,付出的代價就是文件長度增加。對於字母文字來說,這種代價不算沉重,畢竟字母是有限的。號稱有5千年歷史的中文則不一樣,不同的字太多了。
一個折中的辦法是:使用PDF規定的標准外掛字體。雖然花樣少了點,但省地方,兼容性也有標准規范做保證。當然PDF瀏覽器的開發者非要不遵守規范你也沒辦法。另外標准外掛字體支持的語言是有數的,好在常用的Latin 1(西歐各國)、中文簡體、中文繁體、日文、韓文都沒有問題,別的就管不了這么多了。
外掛字體除了節省PDF文件長度外,還有一個好處是文字編輯容易:所有的字形都在外掛字體文件里,PDF中加幾個字都無所謂。內嵌字體通常是用到的字才嵌入,如果想加入新的字就比較麻煩了。就是考慮到校對的問題,所以在DjVuToy、FreePic2Pdf、Pdg2Pic生成的雙層PDF中,才清一色采用外掛字體——沒辦法,目前的技術條件下OCR准確率100%只能是夢想。
5、鼠標選擇文字時,單位精確、細致
由於有字體信息,PDF瀏覽器可以精確計算一個字符串中的某個部分在屏幕上的顯示尺寸,因此即使把整行單詞拼成一個長串,用鼠標選擇時也可以從字母選到詞,再選到行。
這種情況更適合用所見即所得的方式對文件進行編輯,因此帶來了校對的便利。
另外對中、日、韓字體,還有橫排、豎排的區別。在橫排情況下,鼠標光標是豎線;在豎排情況下,鼠標光標是橫線。原因是在不同的排版方式下文字的選擇方式不同,這個區別找兩個文件比划一下就知道了。
6、字壓圖 or 圖壓字?This is a question
其實就是說在雙層PDF中,究竟是文字層在圖像層之上(字壓圖),還是圖像層在文字層之上(圖壓字)。
理論上說,這兩種情況都是允許的,也都有商業實踐者:Acrobat生成雙層PDF時用的是字壓圖,而deent75用的是圖壓字。
我個人更喜歡字壓圖:對於字壓圖來說,只要把Tr參數從3改成其他,即可將文字顯示出來,便於檢查、校對。而對於圖壓字來說,只改Tr則字會被圖蓋住,顯示不出來,除非 再把圖整個隱藏掉。所以在DjVuToy、FreePic2Pdf、Pdg2Pic生成的雙層PDF中,全部是“字壓圖”。