作者:马健
邮箱: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中,全部是“字压图”。

转载于:https://www.cnblogs.com/stronghorse/p/4913444.html

DjVu、PDF中的隐藏文本相关推荐

  1. 通过XPDF抽取PDF中的中文文本

    通过XPDF抽取PDF中的中文文本 1.下载XPDF,下载地址: ftp://ftp.foolabs.com/pub/xpdf/xpdf-3.02pl4-win32.zip 2.下载字体Gbsn00l ...

  2. 如何(以及为什么)在Word文档中使用隐藏文本

    Word lets you hide text so you can read or print your document as if the text isn't there. This migh ...

  3. 【CSS】文字溢出问题 ( 强制文本在一行中显示 | 隐藏文本的超出部分 | 使用省略号代替文本超出部分 )

    文章目录 一.文字溢出问题 二.文字溢出处理方案 三.代码示例 一.文字溢出问题 在元素对象内部显示文字 , 如果文本过长 , 则会出现文本溢出的问题 ; 下面的示例中 , 在 150x25 像素的盒 ...

  4. java给文件添加水印_Java在PDF中添加水印(文本/图片水印)

    水印是一种十分常用的防伪手段,常用于各种文档.资料等.常见的水印,包括文字类型的水印.图片或logo类型的水印.以下Java示例,将分别使用insertTextWatermark(PdfPageBas ...

  5. pdf中如何编辑文本框

    在word中插入文本框对于经常接触文档的人来说可谓是信手拈来,但是在pdf文档中要进行这个操作该怎么办呢?方法也很简单! 第一步,先到网上下载一个捷速pdf编辑器: 下载好之后将编辑器打开,并单击左上 ...

  6. java pdf 水印_Java在PDF中添加水印(文本/图片水印)

    水印是一种十分常用的防伪手段,常用于各种文档.资料等.常见的水印,包括文字类型的水印.图片或logo类型的水印.以下Java示例,将分别使用insertTextWatermark(PdfPageBas ...

  7. java pdf 水印_Java在PDF中添加水印(文本/图片水印)效果

    水印是一种十分常用的防伪手段,常用于各种文档.资料等.常见的水印,包括文字类型的水印.图片或logo类型的水印.以下Java示例,将分别使用insertTextWatermark(PdfPageBas ...

  8. Java在PDF中添加水印(文本/图片水印)效果import com.spire.pdf.*; import com.spire.pdf.graphics.*; import java.awt.*;

    水印是一种十分常用的防伪手段,常用于各种文档.资料等.常见的水印,包括文字类型的水印.图片或logo类型的水印.以下Java示例,将分别使用insertTextWatermark(PdfPageBas ...

  9. XPDF3.04抽取PDF中的中文文本

    2019独角兽企业重金招聘Python工程师标准>>> 开发环境:Windows8.0 X64位          eclipse3.2 版本号:xpdfbin-win-3.04   ...

  10. linux中将文本中的单词换掉的指令_为什么说从PDF中提取文本是一件困难的事?...

    PDF文档处理工作中,总是绕不开对文本提取的需求.很多用户觉得我们PDFlux好用,所以对其中的底层技术也非常感兴趣.也有人为认为,从PDF里抽取文本段落和表格,应该非常简单! 近期,我们会对PDF文 ...

最新文章

  1. eclipse java luna,java-如何在Eclipse Luna中配置Lombok
  2. 计算机网络的组成相关,计算机网络的组成
  3. 再议《反驳 吕震宇的“小议数据库主键选取策略(原创)” 》
  4. LeetCode LCS 02. 完成一半题目(计数+排序)
  5. Linux中实现远程登录Xshell和Xftp
  6. 消息称iPhone 14、14 Max仍采用A15处理器
  7. 乌班图系统修改服务器时间的命令,ubuntu 修改系统时间无效
  8. SPOJ Can you answer the Queries系列
  9. 【转】WPF 窗体淡入淡出动画
  10. PHP工程师学习计划
  11. node.js 处理 http 请求
  12. linux服务网卡速率查看,linux 下查看网卡工作速率
  13. 信息系统项目管理师考试相关介绍
  14. 绝地求生缺少xinput1_3.dll怎么办?
  15. 供应链金融的三种业务模式
  16. JAVA广度优先搜索---寻找从A点到B点最短路径
  17. 最小生成树——克鲁斯卡尔(Kruskal)算法
  18. 怒江java培训班_Graal VM:微服务时代的Java
  19. python画一个爱心
  20. 番茄花园 Ghost XP SP3 2012 06 电脑城极速装机版

热门文章

  1. 暴风激活工具,劫持Chrome浏览器主页
  2. 阅读圣经丨筛选上下文与行上下文
  3. C++调用C#创建的COM组件
  4. VSCode摸鱼插件,让工作更轻松
  5. cread(creade吹风机)
  6. 简历制作器App隐私政策
  7. redis可视化工具desktop manager
  8. Dotween常用方法详解
  9. DGIOT国内首家轻量级物联网开源平台——真实电表接入实战教程
  10. C++ 回调函数简单示例