PDFImageViewer v1.0 免费的PDF查看图像和无损导出工具,兼谈PDF内嵌图像。
提起PDF内嵌图像,大部分人都知道PDF可以内嵌JPG、PNG、Tif、JBig2等图像格式。其实这种观点都是外行看热闹,盲人摸象,摸到啥就以为是啥。实际上,如果认真写过一个PDF内嵌图像导出软件的话,自然就知道PDF规范里面根本就没有所谓图像格式的说法,只有编码和色彩空间的概念。
今天,我给大家讲一讲PDF图像是如何存储和导出的。
大部分人可能都听说过PDF补丁丁软件,如果你用它导出PDF图像,用得多了,就会发现有的图像无法导出,有的图像全黑,有的图像全是斜线,还有的偏色,与PDF查看器渲染出来的图像不一样。这是什么原因呢?为什么明明用PDF Reader、福昕、PDF-XChange那些商业软件可以清楚看到的图像,却无法用补丁丁导出。
我测试过很多免费工具,国外比较常用免费工具的是XPDF里面的pdfimages 和 MuPDF中的mutool,这两个软件比PDF补丁丁要好很多,但是依然存在某些内嵌图像无法识别或者无法导出的问题。如果把全部的内嵌图像当作100的话,PDF补丁丁大约可以正确导出40%的图像(新版补丁丁打算更换MuPDF内核,可以改善导出图像的问题,大家可以拭目以待。),pdfimages 可以正确导出70%的图像,mutool可以正确导出95%的图像。
为什么不同的工具,实现一个图像导出的功能差距如此之大呢?难道PDF内嵌图像导出是一个很困难的事情吗?
确实如此,处理PDF图像比想象中的要复杂得多。
在谈到PDF图像导出之前,要先明白两个概念,一个是编码Encode、一个是色彩空间ColorSpace。PDF图像基本就是围绕着这两个概念进行存储和还原的。
首先,为了避免大家理解困难,我按照外行的说法给大家讲一下什么是编码。 如果你去问AI,PDF内嵌编码有哪些,AI会告诉你一大堆,什么Flate、LZW、CCITT Fax、JBIG2、Run Length、DCT、JPX、ASCII85、ASCIIHex ,这么多编码看着头就晕了。这里,有个简单的鉴别方法,如果你看到编码是DCT,那么就是JPG图像的编码;如果你看到JPX,那就是Jpeg2000图像的编码;如果你看到JBig2,就是Jbig2图像的编码;其它的都属于Png。只是这里有个小问题,某些软件把CCITT Fax和LZW编码的图像数据导出为Tif,这是为了方便输出,并不是说这些编码是Tif图像。 好了,现在你是不是知道PDF图像导出的时候,为什么有的是Jpg,有的是Png,有的是Tif了吧(目前PDF补丁丁就是这么做的)。但是,很不幸,这种导出是错误的。采用这种简易导出图像方式的软件,只能应付40%的图像类型。
那么,问题出在哪里?
这就要说PDF内嵌图像的另一个重要概念,色彩空间ColorSpace。PDF能够成为印刷业的标准文档储存方式,完全是因为它支持丰富多彩的色彩空间。 同样,如果你去问AI,PDF内嵌图像的色彩空间有哪些,AI也会告诉你一大堆概念,例如设备色彩空间(RGB、Gray、CMYK),CIE 的色彩空间(CalGray、CalRGB、Lab 和 ICCBased),特殊色彩空间(Pattern、Indexed、Separation 和 DeviceN、NChannel)。如果你想深入了解PDF纷繁复杂的色彩空间概念,可以看这个链接:PDF的色彩空间
好了,就像老师给学霸上课一样,我现在说:恭喜大家,你们已经掌握了PDF内嵌图像导出的两个重要概念,学会了编码,掌握了色彩空间,现在可以导出图像了。 

PDF导出图像的顺序是这样的:在读取页面对象,找到Image资源之后,要进行三步。1、解码资源,2、按照色彩空间还原图像像素,3、保存图像像素。这就像把大象装进冰箱里一样,拢共分三步,但是你会卡在第二步。 第一步,解码资源,这个简单,PDF开源库已经准备好了解码函数,调用就可以了。第三步,保存图像,也是人人都会。但是第二步,按照色彩空间还原图像像素,所有人都卡在这一步。 在写PDFImageViewer软件之前,我也是和大家一样,以为把大象塞进冰箱是个很容易的事情,然后大象不乐意了...
外行没有人知道PDF图像导出会卡在色彩空间解码这里,我也是上个月才知道的,毕竟之前我也不是专业搞PDF的(纯外行)。实际上,我在2019年就写过PDF图像导出的软件,那时候从来不关心色彩空间是什么,反正大部分需要导出图像的pdf都很简单,不是jpg就是png,不是jpx就是jbig2,总之,导出图像非常简单,总共就两步,解码、导出。中间那个把大象塞进冰箱的步骤跳过去了。
所以,当我写PDFImageViewer软件,想查看PDF内嵌的全部图像的时候,问题就来了。至少有一半的测试图像完全不可查看,不是偏色就是极暗,不是全黑就是全白。
图像偏色的示例(Separation色彩空间),右侧为偏色图像。

图像偏色的示例(Lab色彩空间),右侧为偏色图像。

为了解决这些问题,我深入学习了PDF色彩空间的概念。
真正的PDF图像导出步骤是这样的:
1、读取页面对象,找到Image资源。
2、根据色彩空间决定如何解码资源数据。可能是灰度数据、可能是RGB数据、可能是CMYK数据、也可能是分色数据。解码算法可能是Flate、DCT、JPX、CCITT或者ASCII之类的什么。这里有个问题,前面不是说遇到DCT就当成Jpg图像,遇到Jpx就当成Jpeg2000图像吗?所以,简易图像导出的错误就在这里。PDF图像数据存储是经过编码的,解码之后,需要根据色彩空间判断下一步工作,而不是仅仅根据存储的压缩算法直接导出成图像。这就是为什么PDF补丁丁只能处理40%图像的其中一个原因。
3、资源数据解码之后,要进行Decode映射,这一步是个鸡肋,不处理的话,图像就会黑白颠倒或者偏色,处理就会影响图像导出速度(全是浮点运算,大图像极其耗时)。所以,我们经常用简易处理以提升速度。
4、经过映射还原的数据,还可能需要经过索引还原或者色调还原(最难的,这里不介绍)。索引还原就是把8位的数据通过索引表(也叫调色板)转成RGB、CMYK、LAB或者其它色彩空间的数据 ---- 这种索引的目的本质是是为了节省存储空间。这样才是初步的图像数据。为什么说是初步,因为这个数据不能直接导出成图像,可能还需要色彩校正。
5、色彩校正在很多开源的PDF库都没有这一步,包括目前的PDF补丁丁,所以导出图像偏色就无法解决。CMYK的色彩校正,简单的说就是ICC校正,有专门的图像库处理。而CalRGB等其它色彩空间的校正就需要自己计算了。
6、经过色彩还原之后的数据就是普通的像素数据了。要注意,在PDF图像中没有透明的概念,所以导出的图像数据要么是黑白两色,要么是Gray 8pp灰度,要么就是RGB彩色。我们要根据色彩空间的具体情况来保存或者显示图像数据。
7、当然,事情并没有我说的这么简单,很多时候上述步骤大概率是互相嵌套的,例如Index色彩空间可能与Separation色彩空间、ICCBase色彩空间嵌套在一起,这就进一步造成图像提取的困难和增加耗时。而如果涉及到复杂的色调还原函数,更增加了十倍的提取耗时。
所以,PDF图像导出为什么难?难就难在色彩还原牵扯的东西太多了,每个色彩空间都有自己的还原方式,你需要处理设备色彩空间(RGB、Gray、CMYK),CIE 的色彩空间(CalGray、CalRGB、Lab 和 ICCBased),特殊色彩空间(Pattern、Indexed、Separation 和 DeviceN、NChannel)这么多的方式,有些时候编码算法和色彩空间互相嵌套,处理繁杂。还有某些色彩空间是纯粹给印刷机器用的,在Windows上完全无法支持,更不要说解码和准确还原以及查看了。
PDFImageViewer 是一个神奇的软件,她能支持前面提到的大部分色彩空间。除了某些Windows无法支持的格式和内联图像(我不关注这个),这个软件解决了多年以来免费工具无法精确查看和导出PDF内嵌图像的痛点问题。
预计软件在一两个月内会提供下载,请大家耐心等候。

浙公网安备 33010602011771号