DjVu、PDF中的隐藏文本

作者:马健
邮箱:stronghorse_mj@hotmail.com
发布:2012.06.11

目录
一、背景
二、DjVu中的隐藏文本
三、PDF中的隐藏文本

一、背景

目前对于扫描电子文档,网上比较流行的格式是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中,全部是“字压图”。

posted @ 2015-10-27 10:28  strnghrs  阅读(4545)  评论(1编辑  收藏  举报