关于 VMware Workstation 虚拟机 vmx86驱动版本不匹配的解决办法

  本人习惯在虚拟机里做开发,因为一直想把生活和工作分开。二是方便数据恢复,由于前几天自己在电脑里跑单机版的传奇sf,由于服务端病毒太多导致电脑整个瘫痪,所有数据都丢失,还好自己花了1天时间把所有的数据都恢复过来了。由于之前用到的虚拟机版本太老就想体验下最新版本的虚拟机,于是在网上下了个7的绿色版本。后来死活装不上。没办法又咋网上找到了6.5的,也装不上,想了想可能是原先的注册表项没删掉,就把注册表删除了,删除后可以安装了,紧接着就出现了虚拟机驱动版本不正确的问题。在网上有幸查到了这篇文章,最后解决了。

原文如下:

==========================================================================================

相信很多玩vmware的童鞋遇到过这样的问题

 

与vmx86 驱动版本不匹配: 期待xxo.o,当前ooo.x 你的驱动程序vmx86.sys 版本不正确。请重新安装VMware Workstation。未能初始化监视器设备。

一般是以前安装过旧版本的没卸载,或是所谓绿色虚拟机造成的,,

本人很久很久前也遇到过,也曾疯狂谷歌过,无果,无果,看样子这问题对专业玩家来说,可能是比较低级的错误吧。。

哎,在网吧里什么风吹雨打怪兽妖魔猥哥媚娘没见过,特别是07年那会经过劲舞团反外挂平台那什么”EagleNT”的赤.裸.洗. 脑,也能解决些“驱动级”的问题了。

 

于是套用了一下,得到出这个挺通用的解决方案

1 在虚拟机目录下找vmx86.sys (ctrl+f),, 7系列一般在安装后的main目录下,6系统或更早系统可能躲在某个iso或rar里,但一定要是在虚拟机目录!

2 把找到的vmx86.sys轻轻地放到C:\windows\system32\drivers 目录下

3 开始,运行,cmd

4.在cmd黑漆漆的窗口里输入 net stop vmx86

回车

5.在cmd黑漆漆的窗口里输入 net start vmx86

回车

 

 

启动虚拟机,一切ok!

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

按照高手的指点,解决了,不知道是否适合遇到此问题的朋友,本人强烈鄙视,动不动就说是操作系统的问题,显卡驱动的问题,网上回答的多数纯属扯蛋,不懂装懂,害人害己。

此办法经本人测试,可行。

如果本人给出的解决办法不可行,请另寻他法。咱人是不能在一个搜索引擎里吊死的,要在多个搜素引擎里吊死。

CDT+MinGW32+wxWidgets环境配置

看了网上一些配置,比较难正确配好

CDT:

Version: Juno Service Release 1
Build id: 20120920-0800

 

MinGW32:nuwen.net版本
http://nuwen.net/files/mingw/mingw-9.6.exe

编译wxWidgets:自己下载wxWidgets最新版本,解压后编译:
1.cmd
2.进入D:\MinGW\wxWidgets-2.9.4\build\msw
3.set path=D:\MinGW\bin;%path%
4.修改config.gcc
SHARED ?= 0
UNICODE ?= 1
BUILD ?= debug
MONOLITHIC ?= 1 #编译为1个lib文件
USE_GUI ?= 1
GCC_VERSION ?= 3
5.make -f config.gcc
6.BUILD ?= release,再编译一次
好了,现在D:\MinGW\wxWidgets-2.9.4\lib\gcc_lib就有编译好的版本了
设置CDT:1.windows->Preferences  => C/C++ / Build / Environment,加入:
CPLUS_INCLUDE_PATH
D:\MinGW\include;D:\MinGW\wxWidgets-2.9.4\include;D:\MinGW\wxWidgets-2.9.4\lib\gcc_lib\mswu

C_INCLUDE_PATH
D:\MinGW\include

LIBRARY_PATH
D:\MinGW\lib;D:\MinGW\wxWidgets-2.9.4\lib\gcc_lib

PATH
D:\MinGW\bin

 

 

项目属性设置:

右击project –> properties =>
C/C++ Build -> Tool Chain Editor
Debug、Release都选择MinGW GCC 和Gnu Make Builder

C/C++ Build -> Setting

GCC C++ Compiler:Preprocessor加入Defined symbols
__WXMSW__
_UNICODE
wxUSE_GUI
MinGW C++ Linker
Command line pattern: ${COMMAND} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} ${FLAGS} ,也就是把FLAGS移到最后

Libraries加入wxmsw29u(DEBUG版本则对应加入wxmsw29ud)
Miscellaneous加入Linker flags:-luuid -lcomdlg32 -lcomctl32 -lgdi32 -lole32 -loleaut32 -lWinspool -lpng -lz,这里要非常注意顺序,否则会link出错

 

这样基本上可以了

[V972四核版] 解决卡开机画面故障[特别针对卡V972四核版,卡1989看别处]

volume+:http://huqingyu.com/code/volume1.9.apk

特此申明:
“卡V972四核版”说明已经进入系统,但进不了桌面
“卡Since1989″说明无法进入系统

本帖更换启动器办法是解决“卡V972四核版”问题
“卡Since1989″由其他原因所致,更换启动器还是有一定可能会遇到,解决方法参见在下的另一个帖子http://www.ondabbs.cn/thread-220322-1-1.html
此外,如果你更换启动器后做了双清,是看不到系统桌面的,此时可以连接电脑360助手,重新安装启动器,桌面会出现,不需要线刷ROM,本文仅针对有一定动手动脑能力的朋友,请谨慎使用。

  1. <font color=”Blue”>提升:以下内容仅针对”卡V972四核版”故障,”卡Since 1989″或其他界面的故障因在下没有此类故障机,所以不做探讨,如有昂友遇此故障而且对解决问题感兴趣的,可以加在下QQ1462465671共同研究。以下正文</font>

复制代码

在下的972四核版购于2012岁末,拿到手时觉得非常超值,装了一堆东西,第一次重启动,卡在”V972四核版”的界面死活进不去,进Recovery双清,刷了官方新出的v1.32固件,玩了一会又出现故障,真恨不得把它砸了。
后来想想,民族工业,起步晚必然落后,需要我等之支持才有赶超的机会。于是打定主意自己研究一下。

  1. 一、将未双清,卡在”V972四核版”界面的故障机器连接电脑,360软件助手成功连接上,正确读出了机器内各应用,而且能够升级/卸载机器上的程序。

复制代码

这说明机器的内核和服务基本上已经正常启动运行,只是一个无响应的程序卡住了执行过程,恩,有戏!

  1. 二、此时机器上的360软件助手已经打开,但是按Home键(和电源键对称那个)仍然是”V972四核版”界面,

复制代码

Home键应该是调用启动器程序,看来问题可能出在启动器上。

  1. 三、用adb从电脑连接机器,执行以下命令
  2. adb shell
  3. su
  4. busybox ps -A

复制代码

发现启动器进程确实没有执行,看来问题就出在这里。

所以得出解决方案

本帖隐藏的内容

1)刷1.32固件 (http://www.ondabbs.cn/thread-219402-1-1.html)

1.35.1:http://pan.baidu.com/share/link?shareid=334119&uk=923648228
1.35.2:http://pan.baidu.com/share/link?shareid=339846&uk=923648228
2)系统Root (http://www.ondabbs.cn/thread-219699-1-2.html)
3)安装360软件助手和360安全卫士,给他Root权限(方法很多,比如点<管理>-<更多管理>-<系统瘦身>,就会要求授权,选<允许>),当然你也可以用其他软件更新和系统优化工具,不过在下是用的360.
4)用机器上的360软件助手或者安智市场搜索“Nova启动器”安装,一定要装到手机内存,不要装到SD卡
5)在机器上应用里找”Nova设置”,然后点他的<选择默认启动器>按钮,选中Nova
6)(最重要的一步来了),在360软件助手的<管理><更多管理><系统瘦身>里找到<系统预装>,然后点右上角的目录号,选<显示核心组件,然后找到<启动器>,把它删了,对,你没看错,选中它,点一键卸载,跳出任何警告都点确认(小心不要误选其他的系统应用)
7)关机,重启,恭喜你,不会再遇到卡V972了总而言之一句话,用Nova启动器替换掉系统预装的启动器,当然你不喜欢Nova也可以试试别的,在下只试验了Nova启动器,版本2.0.1beta4,目前已经成功使用一周多,装了各种乱七八糟应用和游戏,未出现卡机故障。Enjoy,本帖3天后开始收费,自觉顶贴,沉了我就把它删掉。看不懂上述操作的,可以在论坛里短消息询问我,顺便求好友。

顺便附上在下目前的小达的进程列表,可以看到该死的com.android.launcher (昂达修改的启动器)不见了,只有com.teslacoilsw.launcher(Nova启动器),嘿嘿

  1. >adb shell
  2. shell@android:/ $ su
  3. su
  4. shell@android:/ # busybox ps -A
  5. busybox ps -A
  6. PID   USER     TIME   COMMAND
  7.     1 0          0:01 /init
  8.     2 0          0:00 [kthreadd]
  9.     3 0          0:00 [ksoftirqd/0]
  10.     6 0          0:00 [migration/0]
  11.    16 0          0:00 [cpuset]
  12.    17 0          0:00 [khelper]
  13.    18 0          0:00 [kdevtmpfs]
  14.    19 0          0:00 [netns]
  15.    23 0          0:00 [suspend]
  16.    28 0          0:00 [earlysuspend_ho]
  17.   288 0          0:00 [sync_supers]
  18.   290 0          0:00 [bdi-default]
  19.   292 0          0:00 [kblockd]
  20.   308 0          0:00 [khubd]
  21.   313 0          0:00 [cpufreq_uevent]
  22.   391 0          0:00 [cfg80211]
  23.   480 0          0:01 [usb-hardware-sc]
  24.   483 0          0:00 [rpciod]
  25.   490 0          0:00 [kswapd0]
  26.   491 0          0:00 [fsnotify_mark]
  27.   492 0          0:00 [nfsiod]
  28.   496 0          0:00 [crypto]
  29.   628 0          0:00 [f_mtp]
  30.   633 0          0:00 [file-storage]
  31.   694 0          0:00 [fantasys]
  32.   714 0          0:00 [binder]
  33.   762 0          0:00 [krfcommd]
  34.   781 0          0:01 [hdmi proc]
  35.   783 0          0:01 /sbin/ueventd
  36. 1111 0          0:09 [nandd]
  37. 1112 0          0:27 [nfmtd]
  38. 1125 0          0:00 [jbd2/nandd-8]
  39. 1126 0          0:00 [ext4-dio-unwrit]
  40. 1129 0          0:00 [flush-93:0]
  41. 1134 0          0:00 [jbd2/nande-8]
  42. 1135 0          0:00 [ext4-dio-unwrit]
  43. 1140 0          0:00 [jbd2/nandh-8]
  44. 1141 0          0:00 [ext4-dio-unwrit]
  45. 1146 0          0:00 [pvr_timer]
  46. 1175 0          0:00 [gslX680_init]
  47. 1176 0          0:00 [gslX680_resume]
  48. 1177 0          0:00 [kworkqueue_ts]
  49. 1186 0          0:00 [mma8452_init]
  50. 1191 0          0:00 [mma8452_resume]
  51. 1204 0          0:00 /system/bin/sh /dev/ttyS0
  52. 1205 1000       0:00 /system/bin/servicemanager
  53. 1206 0          0:07 /system/bin/vold
  54. 1208 0          0:04 /system/bin/netd
  55. 1209 0          0:00 /system/bin/debuggerd
  56. 1210 1000       1:18 /system/bin/su**ceflinger
  57. 1211 0          0:05 zygote /bin/app_process -Xzygote /system/bin –zygote –s
  58. 1212 1019       0:00 /system/bin/drmserver
  59. 1213 1013       0:06 /system/bin/mediaserver
  60. 1214 1002       0:00 /system/bin/dbus-daemon –system –nofork
  61. 1215 0          0:00 /system/bin/installd
  62. 1216 1017       0:00 /system/bin/keystore /data/misc/keystore
  63. 1217 0          0:00 /system/bin/rild -l libsoftwinner-ril.so — -d /dev/ttyUS
  64. 1218 0          0:01 /system/bin/u3gmonitor
  65. 1219 0          0:02 /system/bin/logcat -r 1000 -n 10 -v time -f /data/local/l
  66. 1397 2000       0:04 /sbin/adbd
  67. 1577 0          0:00 [pvr_workqueue]
  68. 1686 0          0:00 [dc_sunxi]
  69. 1840 1000       1:53 system_server
  70. 1976 10047      0:15 com.android.systemui
  71. 2028 10012      0:12 android.process.media
  72. 2060 10019      0:20 com.android.galaxy4
  73. 2076 10057      0:00 com.google.android.inputmethod.pinyin
  74. 2093 1001       0:01 com.android.phone
  75. 2105 10069      0:46 com.teslacoilsw.launcher
  76. 2117 10020      0:01 com.google.process.gapps
  77. 2185 10054      0:00 com.android.smspush
  78. 2200 10003      0:01 android.process.acore
  79. 2225 10023      0:00 com.google.android.partnersetup
  80. 2431 10008      0:00 com.android.providers.calendar
  81. 2545 0          0:00 [loop0]
  82. 2591 0          0:00 [kdmflush]
  83. 2603 0          0:00 [kcryptd_io]
  84. 2604 0          0:00 [kcryptd]
  85. 2607 0          0:00 [ext4-dio-unwrit]
  86. 2649 0          0:00 [loop1]
  87. 2707 0          0:00 [kdmflush]
  88. 2708 0          0:00 [kcryptd_io]
  89. 2709 0          0:00 [kcryptd]
  90. 2712 0          0:00 [ext4-dio-unwrit]
  91. 2765 0          0:00 [loop2]
  92. 2770 0          0:00 [kdmflush]
  93. 2771 0          0:00 [kcryptd_io]
  94. 2773 0          0:00 [kcryptd]
  95. 2776 0          0:00 [ext4-dio-unwrit]
  96. 2841 10041      0:00 com.android.vending
  97. 2857 0          0:00 [loop3]
  98. 2861 0          0:00 [kdmflush]
  99. 2862 0          0:00 [kcryptd_io]
  100. 2863 0          0:00 [kcryptd]
  101. 2867 0          0:00 [ext4-dio-unwrit]
  102. 2902 0          0:00 [loop4]
  103. 2906 0          0:00 [kdmflush]
  104. 2907 0          0:00 [kcryptd_io]
  105. 2908 0          0:00 [kcryptd]
  106. 2913 0          0:00 [ext4-dio-unwrit]
  107. 3001 0          0:00 [loop5]
  108. 3042 0          0:00 [kdmflush]
  109. 3043 0          0:00 [kcryptd_io]
  110. 3044 0          0:00 [kcryptd]
  111. 3046 0          0:00 [ext4-dio-unwrit]
  112. 3062 0          0:00 [loop6]
  113. 3065 0          0:00 [kdmflush]
  114. 3066 0          0:00 [kcryptd_io]
  115. 3067 0          0:00 [kcryptd]
  116. 3069 0          0:00 [ext4-dio-unwrit]
  117. 3082 10064      0:01 com.kingroot.kinguser
  118. 3100 0          0:00 [loop7]
  119. 3141 0          0:00 [kdmflush]
  120. 3142 0          0:00 [kcryptd_io]
  121. 3143 0          0:00 [kcryptd]
  122. 3146 0          0:00 [ext4-dio-unwrit]
  123. 3155 10065      0:58 com.qihoo.appstore
  124. 3180 0          0:00 [loop8]
  125. 3184 0          0:00 [kdmflush]
  126. 3185 0          0:00 [kcryptd_io]
  127. 3186 0          0:00 [kcryptd]
  128. 3188 0          0:00 [ext4-dio-unwrit]
  129. 3218 0          0:00 [loop9]
  130. 3222 0          0:00 [kdmflush]
  131. 3224 0          0:00 [kcryptd_io]
  132. 3225 0          0:00 [kcryptd]
  133. 3228 0          0:00 [ext4-dio-unwrit]
  134. 3232 10007      0:00 com.android.calendar
  135. 3290 0          0:00 [loop10]
  136. 3293 0          0:00 [kdmflush]
  137. 3294 0          0:00 [kcryptd_io]
  138. 3295 0          0:00 [kcryptd]
  139. 3298 0          0:00 [ext4-dio-unwrit]
  140. 3326 0          0:00 [loop11]
  141. 3329 0          0:00 [kdmflush]
  142. 3330 0          0:00 [kcryptd_io]
  143. 3331 0          0:00 [kcryptd]
  144. 3333 0          0:00 [ext4-dio-unwrit]
  145. 3357 0          0:00 [loop12]
  146. 3490 0          0:00 [kdmflush]
  147. 3491 0          0:00 [kcryptd_io]
  148. 3492 0          0:00 [kcryptd]
  149. 3494 0          0:00 [ext4-dio-unwrit]
  150. 3499 0          0:00 sh
  151. 3607 0          0:00 [loop13]
  152. 3611 0          0:00 [kdmflush]
  153. 3612 0          0:00 [kcryptd_io]
  154. 3613 0          0:00 [kcryptd]
  155. 3616 0          0:00 [ext4-dio-unwrit]
  156. 3646 0          0:00 [loop14]
  157. 3650 0          0:00 [kdmflush]
  158. 3651 0          0:00 [kcryptd_io]
  159. 3652 0          0:00 [kcryptd]
  160. 3654 0          0:00 [ext4-dio-unwrit]
  161. 4252 0          0:00 [loop15]
  162. 4291 0          0:00 [kdmflush]
  163. 4292 0          0:00 [kcryptd_io]
  164. 4293 0          0:00 [kcryptd]
  165. 4296 0          0:00 [ext4-dio-unwrit]
  166. 4326 0          0:00 [loop16]
  167. 4365 0          0:00 [kdmflush]
  168. 4366 0          0:00 [kcryptd_io]
  169. 4367 0          0:00 [kcryptd]
  170. 4370 0          0:00 [ext4-dio-unwrit]
  171. 4395 0          0:00 [loop17]
  172. 4517 0          0:00 [kdmflush]
  173. 4518 0          0:00 [kcryptd_io]
  174. 4519 0          0:00 [kcryptd]
  175. 4564 0          0:00 [ext4-dio-unwrit]
  176. 4788 0          0:00 [loop18]
  177. 4791 0          0:00 [kdmflush]
  178. 4792 0          0:00 [kcryptd_io]
  179. 4793 0          0:00 [kcryptd]
  180. 4796 0          0:00 [ext4-dio-unwrit]
  181. 4815 0          0:00 [loop19]
  182. 4819 0          0:00 [kdmflush]
  183. 4820 0          0:00 [kcryptd_io]
  184. 4821 0          0:00 [kcryptd]
  185. 4823 0          0:00 [ext4-dio-unwrit]
  186. 4843 0          0:00 [loop20]
  187. 4883 0          0:00 [kdmflush]
  188. 4884 0          0:00 [kcryptd_io]
  189. 4885 0          0:00 [kcryptd]
  190. 4930 0          0:00 [ext4-dio-unwrit]
  191. 4944 0          0:00 [loop21]
  192. 4947 0          0:00 [kdmflush]
  193. 4948 0          0:00 [kcryptd_io]
  194. 4949 0          0:00 [kcryptd]
  195. 4952 0          0:00 [ext4-dio-unwrit]
  196. 4973 0          0:00 [loop22]
  197. 4976 0          0:00 [kdmflush]
  198. 4977 0          0:00 [kcryptd_io]
  199. 4978 0          0:00 [kcryptd]
  200. 4981 0          0:00 [ext4-dio-unwrit]
  201. 5002 0          0:00 [loop23]
  202. 5005 0          0:00 [kdmflush]
  203. 5006 0          0:00 [kcryptd_io]
  204. 5007 0          0:00 [kcryptd]
  205. 5010 0          0:00 [ext4-dio-unwrit]
  206. 5029 0          0:00 [loop24]
  207. 5033 0          0:00 [kdmflush]
  208. 5034 0          0:00 [kcryptd_io]
  209. 5035 0          0:00 [kcryptd]
  210. 5037 0          0:00 [ext4-dio-unwrit]
  211. 5054 0          0:00 [loop25]
  212. 5057 0          0:00 [kdmflush]
  213. 5058 0          0:00 [kcryptd_io]
  214. 5059 0          0:00 [kcryptd]
  215. 5062 0          0:00 [ext4-dio-unwrit]
  216. 5081 0          0:00 [loop26]
  217. 5085 0          0:00 [kdmflush]
  218. 5086 0          0:00 [kcryptd_io]
  219. 5087 0          0:00 [kcryptd]
  220. 5089 0          0:00 [ext4-dio-unwrit]
  221. 5111 0          0:00 [loop27]
  222. 5115 0          0:00 [kdmflush]
  223. 5116 0          0:00 [kcryptd_io]
  224. 5117 0          0:00 [kcryptd]
  225. 5119 0          0:00 [ext4-dio-unwrit]
  226. 5137 0          0:00 [loop28]
  227. 5140 0          0:00 [kdmflush]
  228. 5141 0          0:00 [kcryptd_io]
  229. 5142 0          0:00 [kcryptd]
  230. 5145 0          0:00 [ext4-dio-unwrit]
  231. 5215 0          0:00 [loop29]
  232. 5218 0          0:00 [kdmflush]
  233. 5219 0          0:00 [kcryptd_io]
  234. 5220 0          0:00 [kcryptd]
  235. 5222 0          0:00 [ext4-dio-unwrit]
  236. 5259 0          0:00 [loop30]
  237. 5263 0          0:00 [kdmflush]
  238. 5264 0          0:00 [kcryptd_io]
  239. 5265 0          0:00 [kcryptd]
  240. 5268 0          0:00 [ext4-dio-unwrit]
  241. 5307 0          0:00 [loop31]
  242. 5311 0          0:00 [kdmflush]
  243. 5313 0          0:00 [kcryptd_io]
  244. 5314 0          0:00 [kcryptd]
  245. 5317 0          0:00 [ext4-dio-unwrit]
  246. 5348 0          0:00 [loop32]
  247. 5351 0          0:00 [kdmflush]
  248. 5352 0          0:00 [kcryptd_io]
  249. 5353 0          0:00 [kcryptd]
  250. 5356 0          0:00 [ext4-dio-unwrit]
  251. 5361 10050      0:00 com.google.android.googlequicksearchbox
  252. 5378 10067      0:55 com.qihoo360.mobilesafe.opti.powerctl
  253. 5433 0          0:00 rt_server_pctl
  254. 6022 1000       0:03 com.android.settings
  255. 6465 10033      0:00 com.google.android.apps.uploader
  256. 7639 2000       0:00 [screencap]
  257. 7762 10010      0:00 com.android.defcontainer
  258. 8005 2000       0:00 [screencap]
  259. 9615 0          0:00 [kworker/0:0]
  260. 9624 0          0:00 [kworker/0:2]
  261. 9629 2000       0:00 /system/bin/sh –
  262. 9634 0          0:00 sh
  263. 9646 0          0:00 [kworker/u:0]
  264. 9653 0          0:00 [kworker/u:1]
  265. 10156 0          0:00 [kworker/0:3]
  266. 10182 0          0:00 busybox ps -A
  267. 11417 0          0:03 [kworker/u:2]
  268. 15745 0          0:04 [kworker/u:3]
  269. 26712 10077      0:28 com.qihoo360.mobilesafe
  270. 26737 10001      0:00 com.android.gallery3d
  271. 26773 10077      0:00 rpc_server
  272. 26779 10035      0:00 com.android.musicfx
  273. 28954 0          0:00 rt_server                                       -server c
  274. 29461 0          0:03 [kworker/0:1]
  275. shell@android:/ #

复制代码

图像转PDF的问题、方法及题外话

作者:马健

邮箱:stronghorse@tom.com

主页:http://stronghorse.yeah.net

http://blog.sina.com.cn/s/blog_5c3dea8d0100qpfw.html

发布:2006.04.05 更新:2006.11.21

测试用例:用例1(一组各种格式的图片),用例2libtiff 3.7.1所带测试图片)

 

友情提示:虽然我已经尽量简化,但是这篇文章感觉还是有点绕,我自己都没有自信一遍就能看懂。如果您的时间很宝贵,建议不要随便浪费,还是去做该做的事吧,这里讨论的不过是些鸡毛蒜皮的小问题。

目录

一、需要解决的问题    

1、图像数据流重新压缩造成的问题   

2、阅读的顺畅性问题   

3、对特殊图像格式的支持问题 二、预备知识    

1、PDF支持的图像格式     2、图像在PDF中的物理表示  

  3、图像在PDF中的逻辑表示

三、问题的解决办法

四、小结

五、题外话一:PDF转图像 六、题外话二:除了PDF,还有什么?  

  1、多页TIFF     2、JBIG2     3、DjVu     4、双层PDF

 

一、需要解决的问题

图像转PDF似乎正在成为一个热门话题:对企业或组织来说,随着信息化的深入,需要将大量纸质档案电子化,实现在线查询、共享;对个人来说,随着家用数码相机等的普及,越来越多的人希望将电子图像信息转换成方便浏览、共享的格式。由于PDF文件本身的标准化、方便性,目前在企业和家庭应用越来越多,由此也带动了诸多图像转PDF软件的诞生。当然“树林子大了,什么样的鸟都有”,至于鸟叫得怎么样,只能实际比较一下再说。

正好由于工作需要,我近期参与了某金融企业的无纸化办公平台建设项目,其中一个重要内容就是将该企业遍布全国的三十余个分支机构积存的巨额(最先开始扫描的一个分支机构就有近三百万页)纸质档案扫描成电子文档。作为项目负责人,我代表客户与国内数家扫描外包公司进行了接触、考察,并对能够搜集到的图像转PDF工具进行了测试、比较,在这个过程中我发现目前图像转PDF软件大致可以分为两类:

  • 基于虚拟打印原理。最著名的大概要算Adobe Acrobat ProfessionalPDF Factory。基于虚拟打印原理的软件开发门槛稍高一些(需要提供打印驱动程序),所以多为收费软件,通用性较好,除图像文件外还能将Word等所有可打印格式转换成PDF。
  • 直接将图像嵌入PDF文件。如ACD Systems出品的ACDSEE中的Create PDF Wizzard、verypdf出品的Image2Pdf等。直接将图像嵌入PDF文件的软件实现相对简单,所以收费、免费的都有。

从测试的结果看,我认为这两类工具普遍存在一些共性问题,包括图像数据流重新压缩造成的问题生成的PDF文件的阅读顺畅性问题对特殊图像格式的支持问题等。本文将对这些问题的成因、解决方法加以探讨。

1、图像数据流重新压缩造成的问题

对基于虚拟打印原理实现的转换软件来说,其工作过程为:

  • 转换工具提供一个虚拟打印机。如Acrobat提供的打印机名为Adobe PDF。
  • 图像浏览软件打开图像文件,在收到打印命令后,象在真实打印机上打印一样,将图像逐象素描绘到虚拟“纸”上,形成发送给虚拟打印机的数据流。
  • 虚拟打印机收到数据流后,根据图像的色彩空间等信息,选择“合适”的压缩算法,对数据流再次进行压缩以减小文件长度,然后将压缩后的数据流存入PDF。

为了测试虚拟打印机对图像的处理,我选择了一组图像(用例1),在ACDSEE 8.0 Build 39中打开,选中所有图像,然后选择“File->Print”,打印到Acrobat 7.07提供的PDF虚拟打印机(ACDSEE和PDF打印机的所有参数均为默认值),然后比较原始图像数据和PDF中的图像数据,结果见表1.1表1.1中各种“解码器”的解释见本文后续的“PDF支持的图像格式”部分,“PDF中的图像数据”各栏中的数据来自开源的PdfView。如果您有兴趣查看PDF文件内部细节,建议用UltraEdit-32,仅看PDF文件结构 用PdfView足矣。

表1.1 从ACDSEE打印图像到Acrobat PDF虚拟打印的结果

原始图像 PDF中的图像数据
序号 说明 宽×长 (象素) 图像解码器 文件长度 (字节) PDF解码器 BitsPerComponent /ColorSpace 数据流长度 (字节)
01 黑白TIFF 1728×1103 CCITT G3 50,401 CCITT G4 1/ICCBased 54,329
02 黑白TIFF 3315×2334 CCITT G4 35,518 CCITT G4 1/ICCBased 36,110
03 彩色JPEG格式TIFF 512×384 DCTDecode 24,428 DCTDecode 8/ICCBased 21,753
04 灰度JPG 445×600 DCTDecode 34,167 FlateDecode 8/Indexed 200,404
05 彩色JPG 1024×768 DCTDecode 102,776 DCTDecode 8/ICCBased 71,540
06 16级灰度GIF 800×1199 LZWDecode 124,738 FlateDecode 4/Indexed 128,925
07 256色GIF 130×129 LZWDecode 8,408 FlateDecode 8/Indexed 6,990
08 黑白PNG 32×32 FlateDecode 164 CCITT G4 1/ICCBased 41
09 2色彩色PNG 32×32 FlateDecode 112 FlateDecode 1/ICCBased 21
10 256级灰度PNG 600×905 FlateDecode 289,059 FlateDecode 8/Indexed 286,947
11 16级灰度PNG 720×1053 FlateDecode 74,322 FlateDecode 4/Indexed 74,943
12 24位色PNG 350×560 FlateDecode 72,107 FlateDecode 8/ICCBased 79,351
13 15位色BMP 260×235 未压缩 122,266 DCTDecode 8/ICCBased 5,783
14 16色BMP 940×20 RLE  8,134 FlateDecode 4/Indexed 2,868
图像文件总长度(字节)

946,600

PDF文件总长度(字节) 989,431

注1. 图像01.tif经ACDSEE转成PDF后,图像物理表示的高度变成2206,原因后面会加以解释。 注2. 对于索引色(Indexed)图像,“数据流长度”仅包含图像数据流长度,不包含索引(调色板)数据流长度。严格说来这会造成一些误差,但影响不大。以下各表与此相同,不再特殊说明。

表1.1可以看出,对于ACDSEE发送过来的数据流,Acrobat PDF虚拟打印机进行如下处理:

  • 黑白图像重新压缩为CCITT G4数据流。
  • 灰度、索引色(调色板)图像压缩为Flate(ZIP)数据流,色深(BitsPerComponent)不变。
  • 非索引色(如15位色、24位色)图像压缩为DCT(JPG)或Flate数据流。似乎Acrobat PDF虚拟打印机能自动识别压缩为哪种数据流更有利,但压缩成JPG数据流时似乎质量系数很低:文件更小,质量更差。
  • 考虑跨平台特性,所有色彩均表示为ICCBased,并给出对照表。

这种处理带来的问题是:

  • 对于有损压缩的灰度JPG,转换后就成了无损压缩的数据流,必然导致文件长度的膨胀。
  • 对于原来无损压缩的彩色图像(PNG、BMP),转换后可能成为有损压缩的JPG数据流,造成图像质量下降(从转换后的数据流长度看,重新压缩的JPG质量系数不会太高)。对于原来就是有损压缩的彩色JPG图像来说,由于是解码后再压缩,图像质量将会逐次衰减。

为了确认是否所有软件在使用虚拟打印机转换PDF时,均会对JPG图像进行再压缩,我进行了第二个试验:在Word 2003中插入用例1中的13张图像(Word 2003不支持03.tif),每张图像前面再插入一点文字(图像编号),然后打印到Acrobat PDF虚拟打印。限于篇幅,这里不列举具体结果(用例1是公开的,Word 2003、Acrobat也不难找,想要较真的人可以自己动手试一下),仅说明结果:

  • 对01、02两个TIFF文件,Word转换成CCITT G4压缩,而且01.tif物理表示的高度未变,这比ACDSEE强。但是这两个图像均被分解成了多个对象(01.tif分成2个,02.tif分成8个),相当于将原始图像切割成多个水平横条,每个对象代表一条。
  • 对04、05两个JPG图像,Word将原始文件完整地嵌入了PDF文件,但在结尾添加了一个\r(0AH)字符。显然,Word并没有对原始JPG文件进行解码、再压缩。
  • 对06、07两个GIF文件,Word打印后均成为ZIP数据流,与ACDSEE相似。
  • 对08、09两个PNG文件,Word打印后成了4位索引色图像(BitsPerComponent=4,Indexed),压缩算法仍然为ZIP。10~12三个PNG文件转换结果与ACDSEE相似。
  • 13、14两个BMP文件转换结果与ACDSEE相似。

从转换结果的对比来看,Word和ACDSEE的打印结果在TIFF、JPG、PNG方面存在较大差距:

  • 对于TIFF图像,Word对图像进行了切割,这个估计与Word对图像的显示方式有关;另外Word没有改变图像的物理表示,这与下面要谈的“直接将图像嵌入PDF文件”的转换软件类似。
  • 对于JPG图像,Word没有再压缩的过程,因此不会造成图像质量的衰减。
  • 对于PNG图像,Word似乎有自己的表示方法,存在解码、重新压缩的过程,并且将BitsPerComponent小于4的PNG转换成BitsPerComponent等于4的图像,这点与CxImage很象。

为了搞清为什么Word不需要对JPG图像进行解压即可直接打印到虚拟打印机,我查了一下微软的MSDN,其中对StretchDIBits函数的解释引起了我的注意:

Windows 98/Windows 2000: This function allows a JPEG or PNG image to be passed as the source image. How each parameter is used remains the same, except :

  • If the biCompression member of BITMAPINFOHEADER is BI_JPEG or BI_PNG, lpBits points to a buffer containing a JPEG or PNG image, respectively. The BITMAPINFOHEADER’s biSizeImage member specifies the size of the buffer. The iUsage parameter must be set to DIB_RGB_COLORS. The dwRop parameter must be set to SRCCOPY.
  • To ensure proper metafile spooling while printing, applications must call the CHECKJPEGFORMAT or CHECKPNGFORMAT escape to verify that the printer recognizes the JPEG or PNG image, respectively, before calling StretchDIBits.

StretchDIBits是在绘制、打印图像时的常用函数,虽然我不可能看到Word的源代码,但我相信Word直接或间接使用了这个函数。为了证实Acrobat虚拟打印机对JPG数据流的支持,我用VC++写了一个小程序,核心打印代码来自MSDN文章“Testing a Printer for JPEG or PNG Support”,最终证实了我的猜测:Acrobat虚拟打印机允许直接将JPG数据流发送给它,但是不支持PNG数据流。

综上所述,对于基于虚拟打印原理实现的图像转PDF工具,可能会存在如下问题:

  • 对于有损压缩的JPG文件,转换成PDF后的质量与发出打印命令的软件密切相关。如象ACDSEE这样先解码再打印,必然会因为图像的再压缩而造成质量衰减或文件膨胀。而象Word这样直接将JPG数据流发送到虚拟打印机,则与软件内部的打印设置有关,设置好了可以直接将数据流完整嵌入PDF而不造成损失或膨胀,设置不好则同样可能造成损失。另外打印机对JPG数据流的支持受平台限制,我猜这就是为什么包括ACDSEE在内的大多数软件宁愿先解码后打印的原因:解码成bitmap再打印可以不受平台限制。
  • 对于无损压缩的图像文件,如GIF、PNG、BMP等,真彩图像往往会被转换成有损压缩的JPG数据流,造成图像质量损失;灰度、索引色图像往往会被解码后再压缩成某种无损压缩数据流,如果虚拟打印机所选压缩算法的压缩效低于原图像压缩算法,则可能造成PDF文件的膨胀。

直接将图像嵌入PDF的转换软件工作原理与基于虚拟打印机的转换软件不同,其工作过程为:

  • 用户在转换软件中选择需要转换的图像文件。
  • 转换工具按照PDF文件规范创建PDF文件,写入文件头信息。
  • 转换工具逐一从图像文件中抽取图像数据,视需要对数据进行转换,然后将数据打包成PDF对象,写入PDF文件。
  • 转换工具写入PDF文件尾,打包结束。

为了测试图像嵌入式转换工具的效果,我将与表1.1相同的图像文件(用例1),用ACDSEE 8.0 (Build 39)的Create PDF Wizzard转换成PDF,结果见表1.2

表1.2 ACDSEE 8 PDF创建插件转换结果

原始图像 PDF中的图像数据
序号 说明 宽×长 (象素) 解码器 文件长度 (字节) 解码器 BitsPerComponent /ColorSpace 数据流长度 (字节)
01 黑白TIFF 1728×1103 CCITT G3 50,401 DCTDecode 8/DeviceGray 905,917
02 黑白TIFF 3315×2334 CCITT G4 35,518 DCTDecode 8/DeviceGray 693,129
03 彩色JPEG格式TIFF 512×384 DCTDecode 24,428 DCTDecode 8/DeviceRGB 34,496
04 灰度JPG 445×600 DCTDecode 34,167 DCTDecode 8/DeviceGray 59,338
05 彩色JPG 1024×768 DCTDecode 102,776 DCTDecode 8/DeviceRGB 129,655
06 16级灰度GIF 800×1199 LZWDecode 124,738 DCTDecode 8/DeviceRGB 319,743
07 256色GIF 130×129 LZWDecode 8,408 DCTDecode 8/DeviceRGB 6,706
08 黑白PNG 32×32 FlateDecode 164 DCTDecode 8/DeviceGray 936
09 2色彩色PNG 32×32 FlateDecode 112 DCTDecode 8/DeviceRGB 896
10 256级灰度PNG 600×905 FlateDecode 289,059 DCTDecode 8/DeviceGray 185,845
11 16级灰度PNG 720×1053 FlateDecode 74,322 DCTDecode 8/DeviceGray 206,121
12 24位色PNG 350×560 FlateDecode 72,107 DCTDecode 8/DeviceRGB 38,468
13 15位色BMP 260×235 未压缩 122,266 DCTDecode 8/DeviceRGB 8,209
14 16色BMP 940×20 RLE  8,134 DCTDecode 8/DeviceRGB 22,018
图像文件总长度(字节) 946,600 PDF文件总长度(字节) 2,619,592

表1.2中可以看出,ACDSEE 8.0 (Build 39)的Create PDF Wizzard对图像的转换原则是:

  • 灰度图像一律转换成灰度JPG数据流。
  • 彩色图像一律转换成彩色JPG数据流。

看来ACSEE对它的JPG转换引擎还真不是一般地有信心!但从表1.2所列数据看,这种转换也不是没有问题:

  • 对于黑白图像,CCITT G4的压缩比通常比灰度JPG高许多,毕竟它是专为压缩黑白图像而研发的压缩算法。因此将CCITT G3/G4转换成灰度JPG无疑将会造成文件膨胀,而且膨胀得很明显。这点对电子文档来说比较重要:大多数白纸黑字的纸质文档扫描后都是黑白图像。
  • 对于低色深(如16级灰度)图像来说,转换成灰度JPG(256级灰度)同样可能造成文件膨胀。
  • 对于本来就是JPG压缩格式的图像,用ACSEE转换后也会出现文件膨胀的问题,莫非是ACSEE转换插件用的JPG质量系数比较高?
  • 不论原来的图像格式是什么,经过ACSEE的转换插件转换后全部解码再重新压缩成有损的JPG数据流,无疑会对图像质量造成损伤。

ACSEE的转换插件效果很令我失望,为了比较其它嵌入式工具的转换效果,我又用用例1测试了verypdf的Image2Pdf v1.7,转换结果见表1.3

表1.3 Image2Pdf转换结果

原始图像 PDF中的图像数据
序号 说明 宽×长 (象素) 解码器 文件长度 (字节) 解码器 BitsPerComponent /ColorSpace 数据流长度 (字节)
01 黑白TIFF 1728×1103 CCITT G3 50,401 CCITT G4 1/DeviceGray 41,638
02 黑白TIFF 3315×2334 CCITT G4 35,518 CCITT G4 1/DeviceGray 34,981
03 彩色JPEG格式TIFF 512×384 DCTDecode 24,428 DCTDecode 8/DeviceRGB 32,815
04 灰度JPG 445×600 DCTDecode 34,167 DCTDecode 8/DeviceGray 34,167
05 彩色JPG 1024×768 DCTDecode 102,776 DCTDecode 8/DeviceRGB 102,776
06 16级灰度GIF 800×1199 LZWDecode 124,738 RunLengthDecode 4/Indexed/DeviceRGB 206,880
07 256色GIF 130×129 LZWDecode 8,408 RunLengthDecode 8/Indexed/DeviceRGB 13,380
08 黑白PNG 32×32 FlateDecode 164 FlateDecode/PNG 1/DeviceGray 91
09 2色彩色PNG 32×32 FlateDecode 112 FlateDecode/PNG 1/Indexed/DeviceRGB 21
10 256级灰度PNG 600×905 FlateDecode 289,059 FlateDecode/PNG 8/DeviceGray 288,582
11 16级灰度PNG 720×1053 FlateDecode 74,322 FlateDecode/PNG 4/Indexed/DeviceRGB 74,063
12 24位色PNG 350×560 FlateDecode 72,107 FlateDecode/PNG 8/DeviceRGB 71,954
13 15位色BMP 260×235 未压缩 122,266 DCTDecode 8/DeviceRGB 8,707
14 16色BMP 940×20 RLE  8,134 DCTDecode 8/DeviceRGB 20,890
图像文件总长度(字节) 946,600 PDF文件总长度(字节) 942,458

表1.3看,Image2Pdf对图像数据的处理要比ACDSEE的PDF创建插件智能得多:

  • 对于黑白TIFF文件,能够自动压缩成CCITT G4;彩色TIFF解码后压缩成JPG。
  • 对于JPG文件,根本就没有解压、再压缩的过程,直接将原始JPG文件一个字节不改就嵌入PDF文件,从而避免因为再次压缩而造成质量衰减,而且解压、再压缩的时间也省了。
  • 对于GIF文件,解压后压缩为RLE(行程编码)。由于RLE的压缩率远不如GIF本身的LZW算法,因此这种再压缩会造成文件膨胀。估计这种吃力不讨好的做法与传说中LZW压缩算法的版权有关。
  • 对于PNG文件,数据流压缩算法不变(PNG压缩算法在PDF中对应/DecodeParms[<</Predictor 15>>]),但数据流长度会稍小一些,估计是去掉了PNG文件中的无关信息。
  • 对于彩色BMP文件,全部重新压缩成JPG数据流,在色彩数较多、色调过渡自然时能够减小文件长度,否则会增加文件长度。当然不论哪种情况画面质量都会损失。

其它图像转PDF的软件我还试过一些,不过基本与以上几种工具类似,都可能因为对图像数据流重新压缩而产生一些问题,差别只在问题的多与少、严重与不严重:

  • 将无损压缩转换成有损压缩,或对有损压缩解码后再次有损压缩,必然造成图像质量下降。
  • 改变文件数据流的压缩方法,在某些情况下可以减小文件长度,在某些情况下则会造成文件长度膨胀。关键是看数据与压缩方法的搭配是否合适。
  • 对于直接读取图像数据的转换工具,由于可以从原始图像文件中获取丰富的图像信息,包括原始数据压缩算法等,因此可以针对不同的文件格式或不同的图像情况做出选择;基于虚拟打印原理实现的转换工具,如果打印机只能得到解码后的数据流,选择的余地就会小一些:只能从bitmap数据流中获取色深等信息,然后自行选择算法重新压缩数据。

2、阅读的顺畅性问题

这里说的阅读顺畅性问题,是指:

  • 如果PDF纸张选择A4、B5等标准纸张,而原始图像的长宽比例与所选纸张的长宽比例不一致,必然会在上下或左右出现较多空白,影响阅读。
  • 如果PDF纸张随图像大小而变化,则转换出来的页面可能大小不一,在阅读时感觉页面跳来跳去,很是不爽。

对于第一个问题,目前没有什么好的解决方案。对于第二个问题,可能的解决方案包括:

  • 建议用户在阅读时将PDF Reader设置为单页、适合宽度,这样每一页都会自动缩放到Reader的窗口宽度。如果嫌麻烦,也可以在生成PDF时就指定“初始视图”中的“页面布局”为“单页”,“放大率”为“适合宽度”。这种方法的缺点是前后翻页时不如“连续”模式顺畅。
  • 在生成PDF文件时为页面指定一个固定宽度,页面的长度按照原始图像的长宽比自动伸缩。这种方法能保证在以“连续”模式阅读时页面不会跳来跳去,当然打印出来还是会在纸张的上下或左右产生空白。

3、对特殊图像格式的支持问题

这里说的“特殊图像格式”,其实主要就是TIFF格式。在常见的图像格式中,JPG、GIF、PNG、BMP等都有严格的格式规定,可以发挥的余地不多。但是对于TIFF来说,由于标准本身希望能够包容尽可能多的东西,但是对实现细节没有给出具体的规定,所以各家软件生成的TIFF文件五花八门,令人头疼。

以我提供的测试用例2为例,这个其实是支持TIFF文件最权威的开源项目libtiff 3.7.1版所带测试图片,不过去掉了一张caspian.tif(该图片共3通道,单通道采样位数高达64位浮点数,我的32位真彩显示器单通道采样位数只有8位整数,显示不了这么高级的图片)。但仅凭剩下的这些图片,已经可以难倒包括verypdf的Image2Pdf在内的一大批图像转PDF软件,就算是ACDSEE这样“专业”的图像浏览器,5.0.1版在看这些图像时也会出现比例失调(fax2d.tif、g3test.tif)、看不了(quad-tile.tif)、颜色失真(smallliz.tif、zackthecat.tif)等问题;8.0版虽然修正了上述问题,但又出现新的问题:看dscf0013.tif时颜色失真。

其实这些文件还算好,毕竟是libtiff组织提供的,至少它自己的源代码还能解出来。但在我接触到的国内专业扫描外包公司中,大多数公司提供的TIFF文件只要采用了有损压缩,多半就连libtiff也解不开,ACDSEE更是想都不用想。有些甚至连专门显示TIFF文件的Microsoft Office Document Imaging(微软Office 2003所带附件之一)都解不开。

偏偏由于工作需要,我必须和这些怪异TIFF文件打交道。我想到的出路包括:

  • 不要在TIFF文件中使用有损压缩,尤其不要用各品牌专业高速扫描仪所带扫描软件生成有损压缩TIFF文件。由于历史原因,这些软件遵循的多半是古老的TIFF标准,生成的文件大概只有它们自己的阅读软件能打开。如果有必要对图像进行有损压缩,直接存储为标准JPG格式即可,这个很难玩什么花样。
  • libtiff源代码为基础,针对这些图像不规范的地方,逐步修正libtiff代码。这就是为什么前段时间我自己写的ComicEnhancer Pro一直在升级的原因。我甚至怀疑,可能就是因为TIFF格式支持起来太麻烦,所以IE才不支持。

除TIFF外,PNG文件也是一种可能会造成潜在麻烦的格式。但是与TIFF不同,PNG的麻烦不在于文件格式本身或数据压缩算法,而在于它丰富的色彩表示:PNG支持灰度、索引、彩色、Alpha通道彩色图像,并且色深除低端的1、2、4、8位外,还支持16位色深。有兴趣又喜欢较真的人,可以到libpng下载一份libpng源代码,里面的contrib\pngsuite文件夹下就包含了一堆图片,专门用于测试软件对PNG色彩支持的能力。

从我测试的结果看,软件在处理PNG图像时可能出现的问题包括:

  • 将16位色深简化成8位色深。这个在通常24位/32位显示器上看不出问题,因为这些显示器最多只支持8位色深,但是将来高端显示成本降低后可能就会被人看出差异了。PDF文件也是从PDF 1.5版(Acrobat 6.0)开始才支持16位色深。
  • 对于低色深(BitsPerComponent < 4)的PNG图像,转换成BitsPerComponent=4的索引色图像,造成轻微的文件膨胀。

综上所述,目前图像转PDF工具普遍存在一些共性的问题,包括图像数据流重新压缩造成的问题生成的PDF文件的阅读顺畅性问题对特殊图像格式的支持问题等。为了更好地理解这些问题,并找到解决办法,下面先简单介绍一下PDF中与图像相关的基本概念。

二、预备知识

事先声明:本部分所有内容均来自Adobe公司发布的《PDF Reference 5th edition》,说白了就是我看这份文档时做的笔记的一部分,所以看起来可能有点无头无尾,各位看得懂就看,看不懂就去看《PDF Reference 5th edition》原文吧。

1、PDF支持的图像格式

在PDF文件中,图像点阵信息以压缩数据流的形式存在,PDF通过过滤器(filter)对数据流解码。在《PDF Reference 5th edition》中,共介绍了十种过滤器,其中与图像相关的如表2.1所示。

表2.1 PDF文件支持的图像过滤器

过滤器名称 对应压缩算法通称 对应图像格式 压缩类型 说明
LZWDecode LZW GIF、TIFF 无损 通常用于索引色(调色板)图像
FlateDecode ZIP PNG、TIFF 无损 除图像外,也用于文本压缩
RunLengthDecode RLE BMP、TIFF 无损 通常用于单色图像
CCITTFaxDecode G3/G4 TIFF 无损 专为黑白图像研发的高效压缩算法
JBIG2Decode JBIG2 JBG 无损 专为黑白图像研发的高效压缩算法
DCTDecode JPEG JPG、TIFF 有损 用于256级灰度、24位真彩自然图像
JPXDecode JPEG2000 J2K、JP2 有损/无损 JPEG的最新标准,压缩比与质量并重

表2.1看,其实对大多数常见图像格式,都可以将原数据流直接嵌入PDF文件,不需要再重新编码。当然某些数据,如JPG文件中的注释、PNG文件的文件头/文件尾,在PDF文件中没用,可以先剔除再将剩余部分嵌入PDF文件。而对于TIFF文件,需要针对具体压缩算法,将真正图像数据抽取出来再嵌入PDF文件。

直接使用原始数据流而不再重新编码,不仅能够节省图像转换成PDF的时间,而且对于有损压缩,可以避免因为反复压缩而造成图像质量的衰减。但是对于GIF格式的LZW压缩来说,情况有点复杂:由于Unisys公司声称对LZW算法拥有专利权,导致很多软件,包括大名鼎鼎的xpdf在内,放弃对LZW的支持,改用开源的Flate压缩算法。Flate其实是Winzip等软件使用的ZIP压缩算法的另外一个名字。《PDF Reference 5th edition》中对这两种算法的描述如下(黑体效果是我自己加的):

Because of its cascaded adaptive Huffman coding, Flate-encoded output is usually much more compact than LZWencoded output for the same input. Flate and LZW decoding speeds are comparable, but Flate encoding is considerably slower than LZW encoding.

由于上文中黑体部分的描述,及诸多公司、组织卷入与Unisys的专利纠纷,因此在我见到的图像转PDF工具中,没有使用LZW压缩算法的,都宁愿将用LZW压缩的GIF图像解码后再压缩成Flate数据流。这种转换在多数情况下能获得更好的压缩比,但例外总是有的(所以上文用的词是usually,而不是always),如用例1中的06.gif,LZW就比ZIP有效得多,这样的图片我还有几张,不过限于篇幅和空间,就不节外生枝了。

对于LZW和Flate压缩,PDF还支持预报器(Predictor),预报器表示根据图像的某些特征,先对图像进行某些预处理后再对处理结果进行压缩,以获取更高的压缩比。在《PDF Reference 5th edition》中定义的预报器见表2.2。小于10的预报器称TIFF预报器,源自libtiff;10以上的称PNG预报器,源自libpng。因此如果PDF文件中定义图像的物理表示时使用了Predictor属性,多半可以猜到原始图像的格式。在表3.1和表1.3中,为了更好地进行比较,采用PNG预报器的Flate解码器均标注为FlateDecode/PNG。

表2.2 预报器

预报器值 含义
1 No prediction (the default value)
2 TIFF Predictor 2
10 PNG prediction (on encoding, PNG None on all rows)
11 PNG prediction (on encoding, PNG Sub on all rows)
12 PNG prediction (on encoding, PNG Up on all rows)
13 PNG prediction (on encoding, PNG Average on all rows)
14 PNG prediction (on encoding, PNG Paeth on all rows)
15 PNG prediction (on encoding, PNG optimum)

2、图像在PDF中的物理表示

一幅图像在PDF文件中通常用一个XObject对象表示(某些TIFF图像可能要用多个对象表示),这个对象描述图像的原始象素点阵信息,因为这些点阵信息由产生图像的设备本身的物理性质(如扫描仪的DPI、数码相机的有效象素数等)决定,因此在这里称为图像的物理表示,在《PDF Reference 5th edition》中又称为采样表示(Sample Representation)。

要描述图像的物理表示,需要提供下列信息:

  • 图像的宽度(width),以象素为单位。
  • 图像的高度(height),以象素为单位。
  • 每象素的颜色通道数,或色彩空间(The number of color components per sample, ColorSpace)。
  • 每通道的采样位数(The number of bits per color component, BitsPerComponent)。
  • 图像象素点阵数据流(stream)。
  • 解码图像数据流所需的过滤器(Filter)名称,及过滤器采用的预报器(Predictor)。

用例1为例,在ACDSEE 8 PDF创建插件转换的PDF中,用如表2.3所示的XObject定义第二幅图像(数据来自PdfView,右侧双斜杠后面是我自己加的注释):

表2.3 图像对象定义实例

9 0 obj << /Type /XObject /Subtype /Image /Name /Image90 /Width 3315 /Height 2334 /BitsPerComponent 8 /ColorSpace /DeviceGray /Filter [/DCTDecode] /Length 693129 >> stream …… endstream endobj // 对象定义开始,对象ID为9 // 字典(dictionary)定义开始 // 对象类型为XObject // 对象子类型为图像 // 对象名称Image90 // 图像宽度3315象素 // 图像高度2334象素 // 每通道采样位数为8 // 色彩空间为256级灰度 // 解码过滤器为JPG(参见表2.1) // 数据流长度693129字节 // 字典定义结束 // 数据流开始 // 数据流内容,一串16进制数,此处从略 // 数据流结束 // 对象定义结束

PDF中的每个对象均有一个ID(编号),通过对象ID,可以对对象本身进行引用。如一个LOGO图像可能作为背景出现在每一个页面上,在每一页中没有必要都包含这个LOGO图像的实际数据,只要引用这个LOGO图像的ID即可。这样无疑可以提高PDF文件的存储效率。上例中图像的对象ID就是9。

3、图像在PDF中的逻辑表示

前面说的图像的物理表示是用象素点来表示图像,但是如果直接按照象素点对图像进行显示、打印,可能会出现问题。以用例1中的第二幅图像为例,象素点阵为3315×2334,如果在分辨率为96 DPI的显示器上显示,尺寸是34.5英寸×24.3英寸(1英寸=2.54厘米,实际英寸数=象素数÷DPI,如3315÷96=34.5英寸),而在分辨率为300 DPI的打印机上打印,打出来只有11.1英寸×7.8英寸,这显然与PDF要求的“在任何平台上均可获得相同的效果”不符。因此在用物理表示定义出图像的象素点阵后,在实际需要显示图像的地方,不仅要给出图像物理表示的对象ID,还需要给出图像的逻辑表示,包括:

  • 图像的逻辑尺寸。这个尺寸的单位是1/72英寸,因此是一个逻辑概念,即不论在什么样的设备上输出图像,图像的大小都是固定的英寸值,而不会随着输出设备的DPI值而变化。
  • 图像的偏移量,即图像左上角点距离页面左上角点的距离,这同样是一个与设备的物理分辨率无关的逻辑量,单位为1/72英寸。
  • 图像的旋转角度。

这种物理与逻辑表示的分离,可以带来一些好处:

  • 同一份物理数据,可以在不同的地方、用不同的大小、以不同的旋转角度进行显示。
  • 通过将物理表示映射成逻辑表示,可以脱离设备的物理性能限制,在不同的设备上获得相同的效果。

具体到PDF文件格式上,在一个页面上显示一幅图像,除了前面说过的图像的物理表示对象外,还需要定义页面(Page)对象,然后在Page对象中:

  • 用MediaBox属性定义页面的逻辑大小,单位为1/72英寸。
  • 用Resources属性定义页面中包含的资源,即前面说的图像物理表示的对象ID。
  • 用Contents属性定义资源对象(图像)的逻辑表示。

Contents属性通常定义一个六元组,表示为[a, b, c, d, e, f],则从图像物理坐标(x, y)映射为逻辑坐标(x’, y’)的映射关系可以表示为如下矩阵运算:

a b 0
[x’ y’ 1] = [x y 1] × c d 0       式 2.1
e f 0

或表示为如下解析表达式:

x’ = ax + cy + e       式 2.2
y’ = bx + dy + f

从《计算机图形学》知识可知,式2.1式2.2中参数a、d分别为x、y向比例系数,实现从物理尺寸到逻辑尺寸的映射;c、b为旋转系数,表示图像显示时的旋转角度;e、f为平移系数,表示图像到页面左上角的偏移量。

用例1为例,在ACDSEE 8 PDF创建插件转换的PDF中,用如表2.4所示的结构定义第二页。

表2.4 页面对象定义实例

8 0 obj << /Type /Page /Parent 3 0 R /Contents 7 0 R /MediaBox [0 0 3315 2334] /Resources <</ProcSet [/PDF /ImageC] /XObject <</Image90 9 0 R>>>> >> endobj // 对象定义开始 // 字典定义开始 // 对象类型 // 父对象 // 内容在对象7定义 // 页面大小 // 页面包含的图像 // 字典定义结束 // 对象定义结束

内容对象7中定义了图像对象的逻辑表示,如表2.5所示。

表2.5 图像对象的逻辑表示实例

7 0 obj << /Length 38 >> stream q 3315 0 0 2334 0 0 cm /Image90 Do Q endstream endobj // 对象定义开始 // 字典定义开始 // 数据流长度38字节 // 字典定义结束 // 数据流开始 // 保存图像状态(Save graphics state) // 式2.1座标映射所需的六元组(Coordinate transformation Matrix) // 绘制映射后的图像(Paint image) // 恢复图像状态(Restore graphics state) // 数据流结束 // 对象定义结束

表2.5的六元组参数看,ACDSEE 8 PDF创建插件用一种很偷懒的方法构造该六元组:直接用图像的物理象素尺寸作为逻辑尺寸。由于屏幕DPI通常为96 DPI,而PDF为72 DPI,这种偷懒造成的后果就是图像在PDF Reader中按照“实际大小”显示时,看起来会比在ACDSEE中按照“完整大小”显示更大一些。精确一点说,这张图片在PDF中的“实际大小”达到了46.04英寸×32.42英寸。其中46.04=3315÷72,32.42=2334÷72。

对于喜欢较真的人来说,ACDSEE的这种偷懒造成了更深层次的失真:用例1中的第二幅图像是一张扫描形成的TIFF图像,在TIFF文件结构中记载了扫描时扫描仪使用的DPI值——200 DPI。在ACDSEE 8中打开此图像文件,点击“文件->属性”菜单,在显示出来的文件属性中即可看到扫描DPI,及按照扫描DPI换算,这张图片对应原始纸质页面的大小——16.57英寸×11.67英寸。这个尺寸与46.04英寸×32.42英寸相比,实在是差得太远了一点。

而如果用verypdf的Image2Pdf v1.7对同一张图片进行转换,可以看出转换后的PDF页面大小为16.57英寸×11.67英寸,即在PDF Reader中选择按照“实际大小”进行显示,显示出来的图像大小,正好与原始纸质文件的大小一模一样。显然这样的结果更符合文档电子化的要求和习惯。

Image2Pdf的这种“保真”转换过程可以描述如下:

  • 如果图像文件中记录了扫描时扫描仪的DPI设置,则先按照“英寸数=象素数÷扫描DPI”,计算出图像的原始尺寸,以英寸为单位。
  • 按照“PDF尺寸=英寸数×72”,将以英寸为单位的图像原始尺寸转换成PDF中的逻辑尺寸,并据此填写六元组。

三、问题的解决办法

在了解了相关预备知识后,再回顾前面提到的图像转PDF需要面对的问题,其答案自然明了:

  • 图像数据流重新压缩造成的问题:对有损压缩图像数据,应尽量将原始数据流嵌入PDF文件,避免重新压缩造成图像质量衰减;对无损压缩图像数据,可以根据图像特征选择合适的无损压缩算法重新压缩图像数据,以节省存储空间,也可以直接将原始图像数据嵌入PDF,以节省重新压缩所需的时间。
  • 阅读的顺畅性问题:提供灵活多样的页面布局供用户按需选择,包括固定纸张大小、固定纸张宽度、按照图像大小定制页面等。页面大小的不同不应对原始图像数据流(图像的物理表示)造成影响,而是通过定义图像的逻辑表示,由PDF Reader本身来完成必要的图像缩放工作。
  • 特殊图像格式的支持问题:这个问题靠等待很难等到结果,最简单的办法就是自己去面对、解决。

总之,对于象我这样有特殊要求的人来说,在目前的情况下要想得到满意的结果,还是只能贯彻“人要靠自己”的原则。当然也没有必要重新发明轮子,在我看来最理想的情况就是能够在现有开源项目基础上,通过必要的修改和补充,就能达到我的要求。但是google的结果令我稍微有点惊讶:虽然目前最权威的图像codec开源项目都是基于C的,包括JPEG LIBlibpnglibtiff等,但是偏偏在PDF生成领域,JAVA似乎比C多,包括iText等一大批开源项目,而C只有PDFlibClibPDFPanda等有数的几个。

ClibPDF从参考手册上看,在绘图等功能方面很有特色,但是对于图像文件的支持较差,而且要付费,所以我粗看了一下,没有深究。

Panda的功能、接口都非常简洁明了,生成的PDF文件也没多少费话,所以我花时间详细试了一下。结果发现一个小小的小缺点:它的内存漏洞实在是太多了点,补都补不过来,最后只好放弃。

相比之下,PDFlib堪称内容丰富、功能强大,某些高级功能(web优化、权限控制等)虽然要付费才能看到,但就算是免费开源出来的PDFLib Lite,对于各种图像格式的支持也足够一般性使用了,而且基本上没什么明显的内存漏洞。因此我在DACapturer中试用了一把。但是在使用一段时间后就发现一些问题:

  • PDFLib的强大其实是和它代码的复杂程度分不开的,想对这样的代码做更改,实在太麻烦了。
  • PDFLib生成的PDF文件中废话太多,导致文件膨胀。DACapturer对此不是很在乎,但是在需要处理的文件数以万、十万做单位的业务系统中就需要考虑了。
  • PDFLib对JPG、PNG的支持很好,但是对TIFF的支持可以用“令人发指”来形容:不支持JPEG/OJPEG压缩的TIFF还可以弥补(俺在DACapturer中通过在PDFLib Lite之外打补丁的办法解决),但是将TIFF中的每个strip当作一个对象来处理,就有点过分了,甚至发生过这样的事:用PDFLib转换十几页TIFF成为PDF,居然在PDF中创建了几千个obj,后来用iText对这样的PDF文件进行合并操作,甚至活活把iText拖垮了。所以用了没多久,俺就下定决心一定要和PDFLib说再见。

由于问题的根子出在TIFF文件上,所以我的目光很快集中到llibtiff源代码中包含的tiff2pdf.c。这份代码是我见过最简洁的PDF生成代码,而且由于是libtiff自己提供的,马马虎虎算是出身名门、血统纯正,对TIFF文件的支持当然很可观,我就是用它弥补了PDFLib不支持JPEG/OJPEG压缩TIFF文件的问题。当然这份代码也不是一点问题没有:

  • 为了节省内存消耗,生成PDF时采用了一种很少见的顺序,导致在生成过程中难以动态添加新的图像。
  • 对JPEG/OJPEG、CCITT G3/G4、zip压缩的TIFF支持很好,但是对其它格式TIFF的支持有待加强,用用例2测试一下就知道了。

好在这份代码比较简单,结构中规中矩,改起来不是太难。最终我以它为基础实现了新版图像转PDF内核,并结合大名鼎鼎的CxImage,将对图像格式的支持从TIFF扩展到了JPG、PNG、BMP和GIF,成为公开发行的免费软件FreePic2Pdf,能够实现:

  • 对有损压缩的jpg文件及采用JPEG/OJPEG算法压缩的TIFF文件,能直接将原始JPEG数据流嵌入PDF文件,避免因为重新采样而造成图像质量下降。
  • 对于无损压缩的图像文件,黑白图像解码后压缩为G4,其它解码后压缩成ZIP数据流嵌入PDF文件。虽然解码/压缩需要消耗一些时间,但是在多数情况下可以减小PDF文件长度。
  • 可以指定生成的PDF文件的页面大小(除A4、B5等,还支持国内常用的32开、16开、大32开)及页边距,这种指定不会更改图像的物理表示,只影响PDF中对图像的逻辑表示
  • 如果不指定页面的纸张大小,可以指定页面的固定宽度(长度随图像大小伸缩),保证连续阅读时不会因为页面宽度变来变去而影响阅读。
  • libtiff源代码进行了更改,以尽可能支持各种特殊格式的TIFF文件;直接调用libpng对PNG图像进行处理,以支持特殊色深的PNG文件。

用FreePic2Pdf对用例1进行转换,结果见表3.1

表3.1 FreePic2Pdf转换结果

原始图像 PDF中的图像数据
序号 说明 宽×长 (象素) 解码器 文件长度 (字节) 解码器 BitsPerComponent /ColorSpace 数据流 长度 (字节)
01 黑白TIFF 1728×1103 CCITT G3 50,401 CCITT G4 1/DeviceGray 41,638
02 黑白TIFF 3315×2334 CCITT G4 35,518 CCITT G4 1/DeviceGray 34,981
03 彩色JPEG格式TIFF 512×384 DCTDecode 24,428 DCTDecode 8/DeviceRGB 23,169
04 灰度JPG 445×600 DCTDecode 34,167 DCTDecode 8/DeviceGray 34,167
05 彩色JPG 1024×768 DCTDecode 102,776 DCTDecode 8/DeviceRGB 102,776
06 16级灰度GIF 800×1199 LZWDecode 124,738 FlateDecode 4/Indexed/DeviceRGB 126,407
07 256色GIF 130×129 LZWDecode 8,408 FlateDecode 8/Indexed/DeviceRGB 7,031
08 黑白PNG 32×32 FlateDecode 164 CCITT G4 1/DeviceGray 40
09 2色彩色PNG 32×32 FlateDecode 112 FlateDecode 1/Indexed/DeviceRGB 17
10 256级灰度PNG 600×905 FlateDecode 289,059 FlateDecode 8/DeviceGray 278,021
11 16级灰度PNG 720×1053 FlateDecode 74,322 FlateDecode 4/Indexed/DeviceRGB 73,199
12 24位色PNG 350×560 FlateDecode 72,107 FlateDecode/PNG 8/DeviceRGB 71,954
13 15位色BMP 260×235 未压缩 122,266 FlateDecode/PNG 8/DeviceRGB 31,764
14 16色BMP 940×20 RLE  8,134 FlateDecode 4/Indexed/DeviceRGB 2,832
图像文件总长度(字节) 946,600 PDF文件总长度(字节) 838,932

对比表3.1和表1.3,可以看出FreePic2Pdf优先考虑图像质量,其次考虑压缩比、生成速度。

另外用例1第一张图片很有趣,用libtiff带的TiffInfo查看它的信息如下:

TIFF Directory at offset 0xc3c6 Image Width: 1728 Image Length: 1103 Resolution: 204, 98 pixels/inch Bits/Sample: 1 Compression Scheme: CCITT Group 3 Photometric Interpretation: min-is-white FillOrder: lsb-to-msb Orientation: row 0 top, col 0 lhs Samples/Pixel: 1 Rows/Strip: (infinite) Planar Configuration: single image plane Page Number: 1-1 Software: fax2tiff Group 3 Options: (0 = 0x0) Fax Data: clean (0 = 0x0) Bad Fax Lines: 0 Consecutive Bad Fax Lines: 0

这张图片在宽度方向上的扫描DPI约为长度方向的两倍(204/98),如果对这种差异处理不好,会带来意外的结果。以ACDSEE为例,5.0.1版显示该图片时就会变形,页面顶部的圆变成了扁椭圆,到8.0版时显示出了正圆,但是图像的长度从1103变成了2206,而且在ACDSEE 8打印和用PDF创建插件转换成PDF后,在PDF文件的图像物理表示中,这张图片的长度均描述为2206象素。显然,ACDSEE内部对图像数据流进行了更改(沿长度方向放大一倍),以符合原长宽比,这对于图像显示软件来说无可厚非,但是对于PDF转换软件来说就有点多余,会增加最终PDF的文件长度。Image2Pdf没有对这张图片的物理表示进行更改,而是试图通过调整图片的逻辑表示,由PDF Reader在显示时进行长宽比调整。但不幸的是,Image2Pdf v1.7似乎把比例算反了,结果导致最终PDF显示出来后,圆变成了长椭圆。FreePic2Pdf吸取了这些教训,能够通过对图像逻辑表示的正确设置,在不改变物理表示的情况下,以正确的长宽比例显示该图像。

四、小结

  • 由于种种原因,目前图像转PDF工具容易出现图像数据流重新压缩造成的问题阅读的顺畅性问题对特殊图像格式的支持问题等。
  • 解决图像数据流重新压缩造成的问题的建议:对有损压缩的图像数据,应尽量将原始数据流嵌入PDF文件,避免重新压缩造成图像质量衰减;对无损压缩图像数据,可以根据图像特征选择合适的无损压缩算法重新压缩图像数据,以节省存储空间,也可以直接将原始图像数据嵌入PDF,以节省重新压缩所需的时间。
  • 解决阅读的顺畅性问题的建议:制作工具提供灵活多样的页面布局供用户按需选择,包括固定纸张大小、固定纸张宽度、按图像大小调整纸张大小等。页面大小的不同不应对原始图像数据流(图像的物理表示)造成影响,而是通过定义图像的逻辑表示,由PDF Reader本身来完成必要的图像缩放。
  • 对特殊图像格式的支持,需要针对具体情况进行开发。

为了验证我提出的上述问题及其解决方法,我开发了一个免费的图像转PDF工具FreePic2Pdf,有需要的可以到我的网站下载。该软件考虑的优先顺序依次是:图像质量、PDF文件大小、转换速度。

五、题外话一:PDF转图像

前面说了半天图像转PDF,自然会产生一个问题:将PDF转成图像又如何?

我个人认为目前将PDF转成图像也可以分成两种:

  • 将PDF每一页的内容(包括图像和文字)转成一个图像文件,从感觉上类似于对PDF Reader的显示区进行截屏。
  • 从PDF文件里找出原始图像数据流,然后转存成对应的图像文件。

第一种的代表软件包括verypdf公司的PDF2HTML等。PDF2HTML除了将页面转成图像,还能生成包含图像和翻页按钮的HTML页面,方便在没有安装PDF Reader的机器上浏览原PDF文件的内容。不过在这种“眉毛胡子一把抓”的转换结果里要取出某幅图像的内容,大概只能用Photoshop慢慢抠了。

第二种的代表软件包括Adobe Acrobat Professional(菜单项:Advanced->Export All Images)。如果喜欢开源代码,也可以看看Xpdf组织提供的pdfimages。从我使用的结果看,Acrobat略显霸道,不管原来的图像是什么格式,转换出来都成了一种格式。pdfimages稍好一点,JPG数据流可以直接导出成JPG文件,其它无损数据流解码后导出为ppm文件,不过对于某些特殊色彩空间(ColorSpace)的JPG数据流,直接导出会导致偏色,只能解码后导出为ppm文件。其实部分特殊色彩空间可以导出为JPG压缩的TIFF文件,从而避免对数据进行解码、再压缩,pdfimages不知道为什么没有考虑。

六、题外话二:除了PDF,还有什么?

以IT界的眼光来看,电子文档发展到现在历史也不算短了,而且由于巨大市场前景的诱惑,各厂家也都纷纷推出了自己的格式。单纯从以支持扫描图像为主的电子文档来说,格式虽多,但是能够成气候、形成标准的,除了PDF格式外,还有多页TIFF、JBIG2、DjVu等。这些格式的共同点是:

  • 支持多页,能够将整卷档案或整部书存储在一个文件中。
  • 遵循开放的标准,能够吸收最先进的图像压缩技术为己用。

当然这些格式目前的影响力都不如PDF,我认为原因也都差不多:

  • 宣传和市场工作做得不够。PDF在成为ISO标准前有Adobe公司在花大力气推动,现在更有N家公司卷了进来,市场的大饼越做越大,相比之下其它格式就显得技术有余,市场不足。
  • 相应的支持工具和软件不足。PDF虚拟打印机用起来多方便,其它格式的虚拟打印机则少得多。就算是用专用工具辛辛苦苦做出来,想和其它人分享成果的时候,还得问问他的机器上有没有装相应的浏览软件,未免太麻烦。当然浏览的问题和前一个问题相关,几年前也不是所有机器上都装PDF Reader的。

1、多页TIFF

这个应该算比较老的标准了,由于扫描、出版界传统上就习惯用TIFF格式,所以将多页TIFF作为电子文档的一种标准格式,应该是顺理成章的事,国内部分省市先行制定的电子档案管理相关规定也曾要求用多页TIFF作为扫描电子文件的存储格式。

但是从实际情况看,真正用多页TIFF存储的电子文档并不多,在2005年颁布执行的《中华人民共和国行业标准DA/T31—2005 纸质档案数字化技术规范》中,干脆就没多页TIFF什么事:

8图像存储 8·1存储格式 8·1·1采用黑白二值模式扫描的图像文件,一般采用TIFF(G4)格式存储。采用灰度模式和彩色模式扫描的文件,一般采用JPEG格式存储。存储时的压缩率的选择,应以保证扫描的图像清晰可读的前提下,尽量减小存储容量为准则。 8·1·2提供网络查询的扫描图像,也可存储为CEB、PDF或其他格式。

多页TIFF为何会遭到冷落呢?我猜测的原因包括:

  • 缺乏方便的浏览工具。众所周知IE不支持TIFF格式,所以网上浏览TIFF只能借助专门开发的控件。即使只在本地机上浏览,也只有ACDSEE等为数不多的图像浏览软件支持多页TIFF,浏览时想做标注、笔记很困难。
  • 格式不规范,这个恐怕是最为致命的问题。从我接触的情况看,由于历史的、技术的和其它的原因,目前国内众多扫描外包服务公司提供的扫描TIFF文件,黑白图像用G4压缩不会有什么问题,但是灰度、彩色图像在有损压缩时多半都用OJPEG压缩,而且格式多与规范不符,这就造成扫描出来的图像只能用该公司提供的图像浏览软件才能浏览,极大地限制了TIFF文件的传播。俺在实际工作中为了处理客户遍布全国的分支机构委托当地外包商扫描的档案文件,与这些非标准TIFF文件进行了长期的、艰苦卓绝的斗争(看看俺的ComicEnhancer Pro最近的更新记录就知道了), 相信有资格说这句话。我相信在《中华人民共和国行业标准DA/T31—2005 纸质档案数字化技术规范》中规定灰度和彩色图像用JPG存储,也就是为了避免产生这些不规范的有损压缩TIFF文件。

但是对于TIFF格式的生命力,我个人从未表示怀疑:与某些静态图像格式不同,TIFF标准一直在与时俱进,不断将先进的图像压缩技术吸收进来,目前已经支持主流的CCITT、JPEG、LZW、ZIP等技术,新版本的草案中则计划包含对JPEG 2000、JBIG2等先进算法的支持。这些都让我充满期待。

2、JBIG2

这种格式专门针对以文字为主、黑白扫描的图像文件,属无损压缩,据称比G4压缩算法的压缩率高很多,目前已成为ISO标准,PDF从1.4版(Acrobat 5.0)开始允许内嵌JBIG2图像,未来的TIFF标准也打算吸收JBIG2压缩算法。

JBIG2的原理类似OCR:先对图像进行分割、匹配,在识别出子图像(如文字)后,将整幅图像看作子图像及其位置的集合,存储时只存储子图像和子图像出现的位置,其它背景信息全部过滤掉,因此不仅能够提供很高的压缩比,而且能够实现类似文字检索的图像全文检索。

虽然前景诱人,但是我个人认为JBIG2目前还存在下列问题:

  • 压缩率严重依赖于图像本身的内容和压缩引擎的模板表。对于字母文字来说,字母总数毕竟有限,因此重码率很高,自然压缩比也很高,但是对于中文来说,可能就没这么理想了。不过从我试用的情况看,至少不会比CCITT G4的压缩比差。
  • 缺乏必要的代码支持,严重阻碍了该标准的推广普及。与其它图像格式不同,目前还没有一个开源组织提供真正的JBIG2压缩支持:Markus Kuhn提供的JBIG-KIT只支持JBIG1,并已经停止更新;jbig2dec只提供解码代码(俺怀疑PDF的JBIG2解码代码就来自这里),不提供编码代码。

3、DjVu

这个也是针对扫描电子文档的,但是与JBIG2不同,针对的是彩色、图文混排的图像。

DjVu的原理是先对图像进行分析,然后按照内容分层,包括背景层、文字层、图像层等,对不同的层使用不同的压缩算法和参数,以获得最好的图像质量和压缩比。

与JBIG2不同,DjVu不仅有djvuzone组织在维护,而且有开源项目DjVuLibre作为支撑,因此现在不仅有不同平台下的编码、解码器,连查看DjVu文件的IE插件都发布了,未来应该大有希望。

4、双层PDF

双层PDF是这样的PDF文件:PDF文件的每一页都包含两层,下层是从纸质文件扫描出来的原始图像,上层是用OCR软件对扫描图像进行识别后产生的文字结果,但字体效果设置成透明。这样用户在阅读PDF文件时看到的是扫描图像,可以100%保留原始版面效果(包括公章、签名),在需要的时候,又可以通过透明的文字信息支持选择、复制、检索等功能。
与普通PDF文件相比,双层PDF能够同时兼顾视觉效果和使用方便性,因此在国内办公、档案领域正在引起重视,我个人相信会有美好的“钱途”。

显然,双层PDF的内容检索、内容复制与OCR识别结果有直接的关系。先不说目前国内OCR软件的识别率如何,最关键的一点是目前没有任何一个中文OCR引擎是免费、开源的(英文的则有gocr等一批),所以双层PDF生成工具也都不是免费的,而是“面向企业市场”,我相信穷困的个人用户在不违法的情况下很难消受得起。

PostScript与PCL

PostScript是专门为打印图形和文字而设计的一个编程语言,它与打印的介质无关,不管您是在纸上、胶片上打印,还是在屏幕显示都适合。它是一 种页面描述语言,与HTML语言类似。 PostScript是由Adobe公司在 1985年提出来的,首先应用在了苹果的LaserWriter打印机上。PostScript的主要目标是提供一种独立于设备的能够方便地描述图像的语 言。独立于设备意味着,不需要借助任何具体设备的特性(例如,打印机的分辨率)来描述一个图像,因而这个描述不需要经过任何修改即可用在其他的 PostScript打印机上进行打印。
PostScript文件是以文本方式存储的,与HTML文件类似。这个您只要用写字板打开一个 PostScript文件就可以看到。PostScript文件本身只是用PostScript语言描述了所要显示或者打印的图像有哪些特征、参数,在显 示或者打印PostScript文件的时候,再由PostScript解释器解释执行,进行具体的打印或者显示,得到所要的图象。PostScript文 件在PostScript文件阅读器中的显示。可以看到PostScript文件经过解释显示,得到了彩色的页面。
与其他格式的文件相比, PostScript文件具有很多优点,上面所提到的独立于设备就是其中很重要的一点。PostScript文件还具有独立于操作系统平台的优点。因为很 多Unix的图形环境本身就把对PostScri pt的支持作为核心的一部分,所以无论您使用的是Windows操作系统,还是Unix操作系统,都可以阅读和打印PostScript文件,这样交流起 来就比较方便。由于PostScript文件是以文本方式存储,因而文件比较小,适合在 Internet上传输。还有就是在PostScript设备(打印机、显示器)上打印和显示有着得天独厚的优势,可以达到最好的效果。
生成PostScript文件有几种途径:
(1)您可以参照PostScript的语言格式,自己按照需要直接用文本编辑器写一个PostScript文件,当然如果文件比较复杂的话,工作量就不小了,而且还得熟悉PostS cript的语法;
(2)您可以使用专门的PostScript文件编辑软件或者某些文字、图像编辑软件提供的功能来生成PostScript文件;
(3)还有一种最简单的方法,就是在您的操作系统中添加一个PostScript打印机(虚拟的),然后在文字编辑器或者图形编辑器中,您所需要的图像通过那个PostScript打印机打印到另一个文件里,得到的文件就是您想要的PostScript文件啦!
PostScript 是一种与设备无关的打印机语言,即在定义图像时可以根本不考虑输出设备的特性(如打印机的分辨率、纸张大小等),而且它对文本和图形实行同样的处理过程, 这就给处理字体带来了极大的灵活性。由于PostScript的设备无关特性,在输出到特定输出设备,譬如对分辨率、纸张大小、进纸盒进行选择时, PostScript通过打印机描述(PostScript Printer Description )文件来实行各种打印机的不同特性。PPD文件主要提供以下与打印机有关的特定信息:默认/最高分辨率,是否支持半色调监控,用户设定的监控信息,页面大 小定义,页面可打印区域,默认字体(通常为 Courier),是否支持双面打印等等。每一种不同的PostScript打印机都分别对应有专门的PPD文件。在Adobe公 司的网站 http//:www.adobe.com/上提供了各种主流的PPD文件。通过PS驱动程序,各种不同的应用软件将各自的数据转换成 PostScript格式。由于打印机只能接受位图格式,当打印机控制器将PostScript转换成位图格式时,由打印机中专门的光栅图像处理器 (Raster Image Processor)来完成这一转换过程。
由于使用PostScript打印机对打印控制器的要求都比较高,另外PostScript是Adobe公司的注册产品,打印机厂商在其产品中使用 PostScript语言要支付Adobe公司一笔费用,因此使用 PostScript的打印机的成本要比使用其他语言和控制方式的打印机要高。因此目前也出现了一些PostScript仿真,像HP公司的一些激光打印 机中使用的PostScript仿真,可以和Adobe公司的PostScript完全兼容,也无需再支付Adobe公司相应的费用。
PCL语言
正是Adobe公司的对PostScript语言的收费方式,给HP公司的PCL( Printer Command Language,打印机控制语言)语言提供了发展空间,PCL语言是HP公司于70年代针对其打印机产品推出的一种打印机页面描述语言。HP公司的市场 策略与Adobe完全不同,其他厂商可以在他们的打印机产品中自由模仿或使用PCL语言。正是PCL语言的开放性,降低了使用PCL语言的打印机产品的成 本,从而使其在打印机产品中的普及程度远远高于PostScript语言。
PCL语言最初也是为点阵打印机设计的,PCL3是第一个得到广泛应用的版本,但它只支持一些简单的打印任务。PCL4虽然还只能应用在个人打印机 中,但增加了对图形打印的支持,但由于解释工作比较简单,PCL4比后期的PCL5和PCL6对打印控制器的要求要低很多。
PCL5是HP公司为它的激光打印机LaserJetⅢ设计的,它提供了一些与PostScript语言相似的功能,开始支持矢量字库和矢量图形描 述,实现了WYSIWYG(What You See Is What You Get, 所见即所得), PCL5中也使用了各种压缩技术来减小数据量,加快数据传输。 PCL5e 开始支持双向数据通讯,从而使打印机可以向计算机发送打印机的状态信息。PCL5c增加了对彩色打印的支持。输出的代码为ASCII码。
1996年HP公司发布了PCL6,它更加灵活,是一个目标朝向的控制语言,使处理多图形的文件的速度大大加快,实现了更好的WYSIWYG,可以更好地处理Web页面。输出的代码为Binary(二进制)码。
两种语言的比较
1. PostScript和PCL两者的工作流程都是首先在计算机的一端将打印内容解释成标准的页面描述文件,这种文件可以被所有采用这种语言的打印机所识 别,传送到打印机的核心——控制器中,然后在打印机控制器中将页面描述文件解释成可以打印的图像。从工作流程的角度看,采用这两种语言的打印方式对打印机 的“大脑”要求较高,需要打印机能够自己独立处理转换的任务,并且需要打印机本身有足够的内存。
2. PostScript和PCL都具备了标准化和与设备无关性的优势,对计算机系统资源占用也较少,两种语言的高版本还提高了对字库、图形和图像的解释能 力,对于提供了高打印质量的产品,大都采用了此两类语言。但相对来说,由于对打印机核心部分——打印控制器性能的要求较高,一定程度会增加机器成本,尤其 是PostScript对打印控制器的性能更高。
3. 经过对多款使用PCL语言和PostScript语言的黑白和彩色激光打印机进行测试。发现,使用PCL语言的打印机在处理文本或一些常见办公应用软件下 的文档时具有非常明显的速度优势,在这些应用下,在打印质量方面与使用PostScript语言的打印机也没有差距。使用PostScript语言的打印 机在常见办公应用下的打印速度要慢一些,但在处理PDF文件或在Photoshop等软件下打印大的图形图像文件时具有一定的速度优势,同时其在图形表现 准确度、色彩表现准确度和一些字库表现准确度方面也比PCL语言有优势。 所以PCL语言比较适合一些普通的商务办公应用,而PostScript语言更加适合对图形和色彩准确度要求比较高的专业应用。这也是目前许多打印机产品 同时提供PCL和PostScript两个版本的驱动的一个重要原因。

图形图像库集合

Google三维API O3D

O3D 是一个开源的 Web API 用来在浏览器上创建界面丰富的交互式的 3D 应用程序。这是一种基于网页的可控3D标准。此格式期望真正的基于浏览器,独立于操作系统之外,并且支持主流的3D显卡,这样就可以在网页中实现效果逼真 的3D动画。在线演示:http://o3… 更多O3D信息

最新新闻: 谷歌联手Mozilla基金开发3D互联网图像技术发布于 2个月前

绘图引擎 RRDtool

简单的说,RRDtool (Round Robin Database Tool)就是一个强大的绘图的引擎,很多工具例如MRTG都可以调用rrdtool绘图。 更多RRDtool信息

最新新闻: RRDtool 1.4.3 发布发布于 2个月前

计算机视觉库 OpenCV

OpenCV是Intel开源计 算机视觉库。它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV 拥有包括 300 多个C函数的跨平台的中、高层 API。它不依赖于其它的外部库——尽管也可以使用某些外部库。 Op… 更多OpenCV信息

最新新闻: OpenCV从SourceForge迁移到ros.org 发布于 6个月前

图像处理类库 CImg

The CImg Library是一个强大的图像处理类库。在代码中使用此类可以导入/导出,处理,和显示图片,它是一个强大的处理图像的C++工具箱。 更多CImg信息

2D图形库AGG

AGG,全名:Anti- GrainGeometry,是一个开源的、高效的2D图形库。AGG的功能与GDI+的功能非常类似,但提供了比GDI+更灵活的编程接口,其产生的图形的质量也非常高,而且它是跨平台的,其宣传可以在非常多的操作系统上运行。 主要的功能有: 1、支持ALPHA、G… 更多AGG信息

Google图形处理引擎 skia

skia是个 2D向量图形处 理函数库,包含字型、座标转换,以及点阵图都有高效能且简洁的表现。不仅用于Google Chrome浏览器,新兴的Android开放手机平台也采用skia作为绘图处理,搭配OpenGL/ES与特定的硬体特征,强化显示的效果自2005 年Skia被Google收购后,一… 更多skia信息

三维图形渲染引擎 OGRE

OGRE是一个三维 (3D)图形渲染引擎。它是面向对象的,并且高效,抽象化了不同的API和平台,这样可以以场景为对象来使用物体,支持多种场景.它已经成功地被应用于诸多三维仿真领域,包括网络游戏和三维仿真项目。 功能和特点◆ 简单易用的面向对象接口◆ 最小化… 更多OGRE信息

开源图形库 FreeImage

一个自由、开源图形库–FreeImage (支持位图构件―例 如调色板和数据位―的便易访问;将位图从一种位深度转换到另一种位深度;当有多幅位图页―例如TIFF―时访问位图的不同页;基本的位图处理,如旋转、翻 转(flipping)和重采样,或点操作,如亮度和对… 更多FreeImage信息

3D引擎 Irrlicht Engine

Irrlicht Engine 是一个用C++开发的高性能实时的3D引擎,同时提供了.NET版本,这是一个跨平台的使用了D3D、OpenGL的3D渲染引擎。 更多Irrlicht Engine信息

最新新闻: Irrlicht Engine 1.7 发布,C++的3D引擎发布于 4个月前

移动设备上的OpenGL OpenGL ES

OpenGL ES (OpenGL for Embedded Systems) 是 OpenGL 三维图形 API 的子集,针对手机、PDA和游戏主机等嵌入式设备而设计。该API由Khronos集团定义推广,Khronos是一个图形软硬件行业协会,该协会主要关注图形和多媒体方面的开放标准。 OpenGL ES 是从 Op… 更多OpenGL ES信息

高质量图形图表库 MathGL

MathGL is … 是一个在Windows和Linux下生成高质量图形的类库;用来根据大量的数组生成各种图表可轻松嵌入到其他程序中可生成各种各样的图表 更多MathGL信息

最新新闻: 高质量图形图表库 MathGL 1.10 发布发布于 5个月前

开源图形库 CxImage

CxImage是一个可以用于MFC 的C++图像处理类库类,它可以打开,保存,显示,转换各种常见格式的图像文件,比如BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K 等格式的文件。可以实现BMP<->JPG,PNG <>TIFF格式等等的互相… 更多CxImage信息

图像识别类库 Tesseract OCR

原本由惠普开发的图像识别类库tesseract-ocr已经更新到2.04, 就是最近Google支持的那个OCR。原先是惠普写的,现在Open source了。 1.03版本以前是在sourceforge上发布,现在的更新版本到google-code上了,据说曾经的图像识别能力排名第三。现在大家都很 关… 更多Tesseract OCR信息

开源图形API OpenGL

OpenGL 是行业领域中最为广泛接纳的 2D/3D 图形 API, 其自诞生至今已催生了各种计算机平台及设备上的数千优秀应用程序。OpenGL 是独立于视窗操作系统或其它操作系统的,亦是网络透明的。在包含CAD、内容创作、能源、娱乐、游戏开发、制造业、… 更多OpenGL信息

最新新闻: OpenGL 4.0 发布发布于 3个月前

图形处理器开发环境 CUDA

CUDA 工具包是一种针对支持CUDA功能的GPU(图形处理器)的C语言开发环境。CUDA开发环境包括:· nvcc C语言编译器· 适用于GPU(图形处理器)的CUDA FFT和BLAS库· 分析器· 适用于GPU(图形处理器)的gdb调试器(在… 更多CUDA信息

C++视觉库 VXL

VXL (the Vision-something-Libraries)是计算机视觉研究和实现库集。它从TargetJr和IUE演变而来,目的是成为一个轻量级、速 度快和持久的系统。它可移植到很多平台。包含的库◆ 数字化容器和法则:vnl◆ 图像管理:vil◆ 几何图形:vgl◆ I/O控制:vsl◆ … 更多VXL信息

三维图形渲染库 OGRE 3D

OGRE 3D 是一个被广泛使用的开源三维图形渲染库,成功地被应用于诸多三维仿真领域,其中包括网络游戏和一些商业的三维仿真项目 更多OGRE 3D信息

最新新闻: 游戏引擎OGRE 3D 1.7.0 RC 宽松的MIT授权发布于 5个月前 C++ PNG类库 PNGwriter

PNGwriter 是一个用来创建PNG格式图像的C++类库。示例: #include <pngwriter.h>int main(){ int i; int y; pngwriter png(300,300,0,”test.png”); for(i = 1; i < 300;i++) { y = 150+100*sin((double)i*9/300.0); … 更多PNGwriter信息 OpenGL应用框架 GLFW

GLFW是一个OpenGL的应用框架,支持Linux和Windows. 更多的效果截图:http://glfw.sourceforge.net/screenshots.html 更多GLFW信息

人脸识别 faceservice.cgi

faceservice.cgi 是一个用来进行人脸识别的 CGI 程序, 你可以通过上传图像,然后该程序即告诉你人脸的大概坐标位置。faceservice是采用 OpenCV 库进行开发的。 更多faceservice.cgi信息

libpng

libpng 软件包包含 libpng 库.这些库被其他程式用于读写png文件. 安装 libpng 用以下命令安装 libpng: make prefix=/usr \ ZLIBINC=/usr/include ZLIBLIB=/usr/lib -f scripts/makefile.linux && make prefix=/usr install -f scripts/makefile…. 更多libpng信息

JPEG 图像压缩库 LibJPEG

LibJPEG 是一个广泛使用的 JPEG 图像压缩库,采用 C 语言开发。 更多LibJPEG信息

OpenGL实现包 Mesa

Mesa是一个类OpenGL(http://www.opengl.org)的开源实现. 更多Mesa信息

最新新闻: Mesa 7.5 正式发布,引入Gallium3D构架发布于 10个月前

C++图形库 GOBLIN Graph Library

GOBLIN图形库包括一个C + +类库的一个大型系列图优化的方法、GOSH以及TCL /Tk脚本语言的扩展。GOBLIN包括一个图形编辑器,并支持标准图形布局方法。 更多GOBLIN Graph Library信息

图像处理库 GD

GD 是一个开源的图像处理库,支持 PNG/JPEG/GIF以及其他格式的图像。GD一般被用来创建图表、图形、缩略图以及其他图像相关的处理操作。 更多GD信息

3D图形开发库 OpenSceneGraph

OpenSceneGraph是一款高性能的3D图形开发库。广泛应用在可视化仿真、游戏、虚拟现实、高端技术研发以及建模等领域。使用标准的C++和 OpenGL编写而成,可以运行在Windows系列、OSX、GNU/Linux、IRIX、Solaris、HP-Ux、AIX以及FreeBSD操 作系统。 … 更多OpenSceneGraph信息

OpenGL图形接口 glew

GLEW是一个跨平台的C++扩展库,基于OpenGL图形接口。使用OpenGL的朋友都知道,window目前只支持OpenGL1.1的涵数,但 OpenGL现在都发展到2.0以上了,要使用这些OpenGL的高级特性,就必须下载最新的扩展,另外,不同的显卡公司,也会发布一些只有自家显卡才 支… 更多glew信息

数码相片在线编辑

数码相片在线编辑用ASP+ImageMagik制作的在线照片编辑- 放大,缩小,裁切工具:方便制作论坛头像,在没有图片处理工具的电脑上使用,简单,方便,支持gif动画裁剪! 目前前端采用JS进行图形处理,后台用ImageMagik进行图片压缩等处理。… 更多数码相片在线编辑信息

C语言的JPEG操作库 OpenJPEG

OpenJPEG是一个C语言编写的开放源码的JPEG 2000编解码器。它已经制定了以推广使用的JPEG 2000 ,最新的压缩标准由因Joint Photographic Experts Group ( JPEG格式) 。除了基本的编解码器,其他各种功能正在开发,其中包括JP2和MJ2 (运动JPEG 2000 )的文… 更多OpenJPEG信息

2D/3D 图形开发库 Visualization Library

Visualization Library 是一个 C++ 的中间件用来开发基于 OpenGL 2.1 的 2D/3D 应用程序,支持高级特性包括 OpenGL Shading 语言、帧缓冲对象、多目标渲染、Vertex 以及点阵缓冲对象、KdTree/AABB frustum culling 等等。提供一个基于 Unicode 的多语言文本… 更多Visualization Library信息

免费开源图形API Mesa3D

Mesa3D是一个几乎和Opengl相同的免费开源图形API,它在功能上一点也不输给Opengl。作为免费开源软件,免去了诸多侵权问题的烦恼。不过最好还是不要用它来开发商业软件,这样有违开源精神。 更多Mesa3D信息

BMP图像处理库 bmplib

bmplib 是一个用来创建 24位 BMP 位图的 C 语言库,不依赖于其他程序库。 更多bmplib信息

向量图形库 Picasso

Picasso 是一个高质量的向量图形渲染库,支持 path , matrix , gradient , pattern , image 和 truetype font 等功能. alpha blending svg rendering gis maps instrument … 更多Picasso信息

摄像头图像捕捉 QuickCapture

QuickCapture是一个简单和易于扩展的应用程序以最小的依赖性,旨在收集和处理图像取自网络摄像头。它提供了一个强大的功能集,并包含一个插件系统部分灵感来自Pidgin。 更多QuickCapture信息

2D 图形引擎 Quad-Ren

Quad-Ren 是一个独立的决议2D图形引擎,旨在缓解点阵图的发展为基础的应用程序,主要是游戏。应用四任将功能相同的,不论屏幕分辨率或长宽比,窗口或全屏。 更多Quad-Ren信息

Symbian图像处理扩展库 NokiaCV

NokiaCV 是在 Nokia的Symbian操作系统,扩展图像处理能力和规范内部的操作系统图像操作。NokiaCV 提供的标准图像操作方法,以及一套线性代数行动需要 在许多先进的图像应用程序。这是一个未来的基石先进图像库。一些扩展很可能会造成我们的研究小组和提供… 更多NokiaCV信息

3D渲染引擎 Genesis3D

Genesis3D 是实时3D渲染环境,所有的实时3D的需要。有大量的在线社区,免费网上论坛,许多链接Genesis3D开发商…你会发现所有的支持和工具,您需要 着手开发世界一流的,实时三维应用程序。如果您是新的发展与Genesis3D ,当前版本的软件开发工具包是1.1… 更多Genesis3D信息

大图像处理工具 VIPS

VIPS 是一个图像处理软件,特别适合非常大的图像处理。它由一个强大的,可重复利用的程序库和一个图形用户界面组成。 更多VIPS信息

3D引擎 Apocalyx

Apocalyx是一个基于OpenGL的3D引擎. 更多Apocalyx信息

OCR识别 OCRopus

Ocropus的(TM)是一个先进的文件分析和OCR系统,采用可插入的布局分析,可插入的字符识别,自然语言统计建模和多语言支持功能。 更多OCRopus信息

C 图像操作库 Jhead

Jhead 是一个用C语言开发的用来操作图像文件的EXIF信息的库。读取 EXIF 信息时输出如下: Sample jhead output: File name : 0805-153933.jpgFile size : 463023 bytesFile date : 2001:08:12 21:02:04Camera make : CanonCamera model : Can… 更多Jhead信息

最新新闻: Jhead 2.90 发布,C语言的图形EXIF解析库发布于 4个月前

图形处理包 DevIL

DevIL (即以前的OpenIL)是一个跨平台的图形处理包,支持BMP,JPG,GIF等多种图形文件格式. 更多DevIL信息

OpenGL应用工具包 GLUT

GLUT代表 OpenGL应用工具包,英文全称为OpenGL Utility Toolkit,是一个和窗口系统无关的软件包,它由Mark Kilgard在SGI时写的。作为AUX库的功能更强大的替代品,用于隐藏不同窗口系统API的复杂性。是一个学习OpenGL编程的一个良好开端。感 谢GLUT,使我们可… 更多GLUT信息

OpenVRML

OpenVRML is a VRML and X3D browser plug-in and C++ toolkit for incorporating VRML support into applications. OpenVRML provides VRML97 and Classic VRML X3D parsers, a runtime, and an OpenGL renderer as C++ libraries. The renderer is fully… 更多OpenVRML信息

Jet3D

Jet3D 是一个C++的高性能实时的三维图形渲染引擎。 更多Jet3D信息

场景图绘制类库 Papyrus

Papyrus 是一个 C++ 的二维场景图绘制类库。Papyrus 跟 Gnome:Canvas 库的功能类似。下面是一些绘制的场景图例子: 200×200 (3kb) 200×200 (5… 更多Papyrus信息

C++图像处理库 ExactImage

ExactImage 是一个快速的 C++ 图像处理库,与 ImageMagick 不同的是,ExactImage 允许对多个色彩空间和色深进行操作;更低的内存占用和CPU占用;某些优化算法速度是 ImageMagick 的 20 倍,显示大图片的速度是 ImageMagick 的 10 倍。… 更多ExactImage信息

最新新闻: ExactImage 0.8.0 发布发布于 2个月前

OpenGL的C++封装 D’Enfent Engine

D’Enfent Engine 是一个C++的类库,用来提供对 OpenGL 函数的高级封装,非常适合用于游戏开发,提供一个完整的API手册和一个入门指南。 更多D’Enfent Engine信息

NVIDIA Scene Graph

NVIDIA Scene Graph (NVSG) 软件开发套件是一个面向对象的编程库,主要用于创建场景图形的应用程序。大一种事后补充。而NVSG 是围绕着色器完全重新进行设计。NVSG 利用 CgFX – 一个元文件格式,这个格式可以让着色器在应用程序之间轻松共享。Viewe… 更多NVIDIA Scene Graph信息

最新新闻: NVIDIA公司预发布其195.xx Linux驱动程序发布于 2个月前

C语言的EXIF库 libexif

libexif 是一个用来读取数码相机照片中包含的 EXIF 信息的 C 语言库,支持多种平台。 更多libexif信息

Exiv2

Exiv2 是一个用来提取图片中的EXIF、LPTC 和 XMP 元数据信息的C++类库。同时还提供了命令行工具。示例代码: Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]); assert(image.get() != 0); image->readMetadata(); Exi… 更多Exiv2信息

三维应用开发环境 Croquet

Croquet 是一个功能强大的开放源码软件开发环境,用于创建和大型分布式部署多用户虚拟三维应用程序和metaverses是( 1 )持久性( 2 )深入的合作,( 3 )相互联系和( 4 )互操作。Croquet 的架构支持同步通信,协作,资源共享和计算之间的大量用户在多… 更多Croquet信息

Symbian绘图库 Cairo for Symbian OS

Cairo for Symbian OS 是绘图库 Cairo 在 Symbian 操作系统上的移植版本。 示例代码: // CMyAppView derives from CCoeControl//void CMyAppView::ConstrucL(const TRect& aRect) { CreateWindowL(); SetRect(aRect); ActivateL(); iSurface = cair… 更多Cairo for Symbian OS信息

数据可视化库 Tulip

Tulip 是一种专为巨大的图形可视化的软件系统。它可在个人电脑( PIII 600 256MB内存)管理多达50万的图形 。Tulip 架构提供下列功能:三维可视化,三维的修改,插件支持,支持集群和导航,自动图形绘制,自动聚类图,自动选择的内容,并自动着色元素等。 … 更多Tulip信息

计算机图形渲染库 Voreen

Voreen是计算机图形可视化交互式卷库。它提供了数容积数据可视化技术和利用了可编程图形硬件(着色用)加速渲染。附带的应用程序允许创建和测试新的渲染技术。 Voreen实现与C + +和使用OpenGL / GLSL的渲染。 更多Voreen信息

最新新闻: 图形渲染库 Voreen 2.0 发布发布于 5个月前

C++向量图生成库 CreEPS

CreEPS 是一个C++类,提供一个容易从内部生成的代码向量图的界面。该图存储为压缩的PostScript(EPS)的文件。它具有所有的基本图形元素,用户可配置的填充类型和printf风格的文本输出。包含大量例子文件。 更多CreEPS信息

医学影像转换工具 XMedCon

XMedCon 是一个医学专用影像档转换工具与程式库。以C语言撰写。 更多XMedCon信息

Apache图像处理模块 mod_gfx

mod_gfx 是一个对图像进行即时处理的 Apache 模块,安装方法: Ensure APXS, libgd, and gcc are installed Compile module (run make) Copy module/mod_gfx.so to your apache modules directory Configure Apache to use module Restart Apache … 更多mod_gfx信息

LibRaw

LibRaw 是一个用来处理 RAW (CRW/CR2, NEF, RAF, DNG, and others) 格式图片的 C++ 库,支持各种操作系统。 更多LibRaw信息

最新新闻: LibRaw 0.9.0 发布发布于 1个月前

libQGLViewer

libQGLViewer 是一个用以简化了Qt开发OpenGL三维浏览器的C++库。它提供了一些典型的3D查看器的功能,如能够移动相机使用鼠标,这是缺乏大多数其他的API 。其它特点包括鼠标操纵框架,插值关键帧,对象选择,立体显示,截图保存,等等。它可以使用OpenGL的初… 更多libQGLViewer信息

OpenGL工具包 Freeglut

Freeglut是一个GLUT (OpenGL Utility Toolkit) 的开源实现,使用非常广泛。OpenGL Redbook使用Freeglut代替GLUT编写代码。 更多Freeglut信息

Cafu 3D引擎

这个引擎支持一系列3D渲染,材质制作,多玩家在线,跨平台和可被多编译器编译。但它采用了双协议,商业版是闭源的,源代码在GPLv3许可证下发布。 更多Cafu 3D引擎信息

WaYee3D Toolkit

WaYee3D ToolKit 一个基C++和Ogre的插件式3D应用程序框架,开源。框架主要就是用来做编辑器这一类的应用程序。C++ 插件式软件架构。 MFC Ribbon界面command 模式Undo/Redo支持。Unicode支持。 … 更多WaYee3D Toolkit信息

渲染器的高级着色语言 Open Shading Language

Open Shading Language (OSL) is a small but rich language for programmable shading in advanced renderers and other applications. OSL is similar to C, as well as other shading languages, however, it is specifically designed for advanced re… 更多Open Shading Language信息

begtostudy-imagelib

begtostudy-imagelib 是一个开源的VC图像库 更多begtostudy-imagelib信息

Magick++

Magick++ 是 ImageMagick 图像处理库的面向对象 C++ API 调用包。 更多Magick++信息

Equalizer

Equalizer is a programming interface and resource management system for scalable OpenGL applications. 更多Equalizer信息

Python图像处理 Mahotas

Mahotas 是一个 Python 的图像处理库,包含大量的图像处理算法,使用 C++ 实现的算法,处理性能相当好。 更多Mahotas信息 光栅化软件渲染器 SoftArt

SoftArt是一款光栅化的软件渲染器,设计目标是达到Direct3D 10/11的核心功能的实现。我们的设计目的主要包括以下几点: 一个高度可移植的光栅化图形管线的软件实现图形硬件工作原理的展现和教学为下一代Many Core或Larrabee类的多x86处理器架构的计算设… 更多SoftArt信息

图形布局引擎 GLE

GLE (Graphics Layout Engine) 是一个图形脚本语言,主要为创建图表、数据和幻灯片而用,支持多种图表类型 (function plots, histograms, bar graphs, scatter plots, contour lines, color maps, surface plots, …) ,使用简单,仅需通过一些图形化命令… 更多GLE信息

OpenCSG

OpenCSG is a library that does image-based CSG(Constructive Solid Geometry) rendering using OpenGL. OpenCSG is written in C++ and supports most modern graphics hardware using Microsoft Windows or the Linux operating system…. 更多OpenCSG信息

图像处理和分析 Leptonica

Leptonica 广泛用于图像处理和图像分析应用。 更多Leptonica信息

QTeXEngine

QTeXEngine 是一个 QtiPlot 的扩展插件,用来将二维的图形转成 TeX 格式文档,所有通过 QtiPlot 的 QPainter 绘制的图形都可以通过它来导出,下面是一个例子: void MyClass::exportTeX(const QString& fileName){QTeXPaintDevice tex(fileName, QSi… 更多QTeXEngine信息

lib3ds

lib3d 是一个用于读取3ds格式三维模型的标准类库 更多lib3ds信息

OpenCV功能

图像数据操作(内存分配与释放,图像复制、设定和转换)

图像/视频的输入输出(支持文件或摄像头的输入,图像/视频文件的输出)

矩阵/向量数据操作及线性代数运算(矩阵乘积、矩阵方程求解、特征值、奇异值分解)

支持多种动态数据结构(链表、队列、数据集、树、图)

基本图像处理(去噪、边缘检测、角点检测、采样与插值、色彩变换、形态学处理、直方图、图像金字塔结构)

结构分析(连通域/分支、轮廓处理、距离转换、图像矩、模板匹配、霍夫变换、多项式逼近、曲线拟合、椭圆拟合、狄劳尼三角化)

摄像头定标(寻找和跟踪定标模式、参数定标、基本矩阵估计、单应矩阵估计、立体视觉匹配)

运动分析(光流、动作分割、目标跟踪)

目标识别(特征方法、HMM模型)

基本的GUI(显示图像/视频、键盘/鼠标操作、滑动条)

图像标注(直线、曲线、多边形、文本标注)

算术编码

算术编码 是一种无损数据压缩方法,也是一种熵编码的方法。和其它熵编码方法不同的地方在于,其他的熵编码方法通常是把输入的消息分区为符号,然后对每个符号进行编码,而算术编码是直接把整个输入的消息编码为一个数,一个满足(0.0 ≤ n < 1.0)的小数n。

目录

[隐藏]

 算术编码工作原理

在给定符号集和符号概率的情况下,算术编码可以给出接近最优的编码结果。使用算术编码的压缩算法通常先要对输入符号的概率进行估计,然后再编码。这个估计越准,编码结果就越接近最优的结果。

: 对一个简单的信号源进行观察,得到的统计模型如下:

  • 60% 的机会出现符号 中性
  • 20% 的机会出现符号 阳性
  • 10% 的机会出现符号 阴性
  • 10% 的机会出现符号 数据结束符. (出现这个符号的意思是该信号源’内部中止’,在进行数据压缩时这样的情况是很常见的。当第一次也是唯一的一次看到这个符号时,解码器就知道整个信号流都被解码完成了。)

算术编码可以处理的例子不止是这种只有四种符号的情况,更复杂的情况也可以处理,包括高阶的情况。所谓高阶的情况是指当前符号出现的概率受之前出现符号的影响,这时候之前出现的符号,也被称为上下文。比如在英文文档编码的时候,例如,在字母Q或者q出现之后,字母u出现的概率就大大提高了。这种模型还可以进行自适应的变化,即在某种上下文下出现的概率分布的估计随着每次这种上下文出现时的符号而自适应更新,从而更加符合实际的概率分布。不管编码器使用怎样的模型,解码器也必须使用同样的模型。

一个简单的例子 以下用一个符号串行怎样被编码来作一个例子: 假如有一个以A、B、C三个出现机会均等的符号组成的串行。若以简单的分组编码会十分浪费地用2 bits来表示一个符号: 其中一个符号是可以不用传的(下面可以见到符号B正是如此)。 为此, 这个串行可以三进制的0和2之间的有理数表示, 而且每位数表示一个符号。 例如, “ABBCAB” 这个串行可以变成0.011201(base3)(即0为A, 1为B, 2为C)。用一个定点二进制数字去对这个数编码使之在恢复符号表示时有足够的精度,譬如0.001011001(base2) – 只用了9个bit,比起简单的分组编码少(1 – 9/12)x100% = 25%。 这对于长串行是可行的因为有高效的、适当的算法去精确地转换任意进制的数字。

编码过程的每一步,除了最后一步,都是相同的。编码器通常需要考虑下面三种数据:

  • 下一个要编码的符号
  • 当前的区间(在编第一个符号之前,这个区间是[0,1), 但是之后每次编码区间都会变化)
  • 模型中在这一步可能出现的各个符号的概率分布(像前面提到的一样,高阶或者自适应的模型中,每一步的概率并不必须一样)

编码器将当前的区间分成若干子区间,每个子区间的长度与当前上下文下可能出现的对应符号的概率成正比。当前要编码的符号对应的子区间成为在下一步编码中的初始区间。

: 对于前面提出的4符号模型:

  • 中性对应的区间是 [0, 0.6)
  • 阳性对应的区间是 [0.6, 0.8)
  • 阴性对应的区间是 [0.8, 0.9)
  • 数据结束符对应的区间是 [0.9, 1)

当所有的符号都编码完毕,最终得到的结果区间即唯一的确定了已编码的符号串行。任何人使用该区间和使用的模型参数即可以解码重建得到该符号串行。

实际上我们并不需要传输最后的结果区间,实际上,我们只需要传输该区间中的一个小数即可。在实用中,只要传输足够的该小数足够的位数(不论几进制),以保证以这些位数开头的所有小数都位于结果区间就可以了。

Arithmetic encoding.svg

: 下面对使用前面提到的4符号模型进行编码的一段信息进行解码。编码的结果是0.538(为了容易理解,这里使用十进制而不是二进制;我们也假设我们得到的结果的位数恰好够我们解码。下面会讨论这两个问题)。

像编码器所作的那样我们从区间[0,1)开始,使用相同的模型,我们将它分成编码器所必需的四个子区间。分数0.538落在NEUTRAL坐在的子区间[0,0.6);这向我们提示编码器所读的第一个符号必然是NEUTRAL,这样我们就可以将它作为消息的第一个符号记下来。

然后我们将区间[0,0.6)分成子区间:

  • 中性 的区间是 [0, 0.36) — [0, 0.6) 的 60%
  • 阳性 的区间是 [0.36, 0.48) — [0, 0.6) 的 20%
  • 阴性 的区间是 [0.48, 0.54) — [0, 0.6) 的 10%
  • 数据结束符 的区间是 [0.54, 0.6). — [0, 0.6) 的 10%

我们的分数 .538 在 [0.48, 0.54) 区间;所以消息的第二个符号一定是NEGATIVE。

我们再一次将当前区间划分成子区间:

  • 中性 的区间是 [0.48, 0.516)
  • 阳性 的区间是 [0.516, 0.528)
  • 阴性 的区间是 [0.528, 0.534)
  • 数据结束符 的区间是 [0.534, 0.540).

我们的分数 .538 落在符号 END-OF-DATA 的区间;所以,这一定是下一个符号。由于它也是内部的结束符号,这也就意味着编码已经结束。(如果数据流没有内部结束,我们需要从其它的途径知道数据流在何处结束——否则我们将永远将解码进行下去,错误地将不属于实际编码生成的数据读进来。)

同样的消息能够使用同样短的分数来编码实现如 .534、.535、.536、.537或者是.539,这表明使用十进制而不是二进制会带来效率的降低。这是正确的是因为三位十进制数据能够表达的信息内容大约是9.966;我们也能够将同样的信息使用二进制分数表示为.10001010(等同于0.5390625),它仅需8位。这稍稍大于信息内容本身或者消息的信息熵,大概是概率为0.6%的 7.361位信息熵。(注意最后一个0必须在二进制分数中表示,否则消息将会变得不确定起来。)

 精度和再正规化

上面对算术编码的解释进行了一些简化。尤其是,这种写法看起来好像算术编码首先使用无限精度精度的数值计算总体上表示最后节点的分数,然后在编码结束的时候将这个分数转换成最终的形式。许多算术编码器使用有限精度的数值计算,而不是尽量去模拟无限精度,因为它们知道解码器能够匹配、并且将所计算的分数在那个精度四舍五入到对应值。一个例子能够说明一个模型要将间隔[0,1]分成三份并且使用8位的精度来实现。注意既然精度已经知道,我们能用的二进制数值的范围也已经知道。

符号 概率(使用分数表示) 减到8位精度的间隔(用分数表示) 减到8位精度的间隔(用二进制表示) 二进制范围
A 1/3 [0, 85/256) [0.00000000, 0.01010101) 00000000 – 01010100
B 1/3 [85/256, 171/256) [0.01010101, 0.10101011) 01010101 – 10101010
C 1/3 [171/256, 1) [0.10101011, 1.00000000) 10101011 – 11111111

一个称为再归一化的过程使有限精度不再是能够编码的字符数目的限制。当范围减小到范围内的所有数值共享特定的数字时,那些数字就送到输出数据中。尽管计算机能够处理许多位数的精度,编码所用位数少于它们的精度,这样现存的数据进行左移,在右面添加新的数据位以尽量扩展能用的数据范围。注意这样的结果出现在前面三个例子中的两个里面。

符号 概率 范围 能够输出的数据位 再归一化后的范围
A 1/3 00000000 – 01010100 0 00000000 – 10101001
B 1/3 01010101 – 10101010 None 00101010 – 11010101
C 1/3 10101011 – 11111111 1 01010110 – 11111111

 算术编码和其他压缩方法的联系

哈夫曼编码

在算术编码和哈夫曼编码之间有很大的相似性 — 实际上,哈夫曼编码只是算术编码的一个特例 — 但是由于算术编码将整个消息翻译成一个表示为 基数 b,而不是将消息中的每个符号翻译成一系列的以b为基数的数字,它通常比哈夫曼编码更能达到最优熵编码

 区间编码

算术编码与区间编码有很深的相似渊源,它们如此相似以至于通常认为它们的性能是相同的,如果确实有什么不同的话也只是区间编码仅仅落后几个位的值而已。区间编码与算术编码不同,通常认为它不被任何公司的专利所涵盖。

区间编码的原理是这样的,它没有像算术编码那样从[0,1]开始并根据每个字符出现的概率把它分成相应的不同的小区间,它从如000,000,000,000到999,999,999,999这样一个很大的非负整数区间开始,并且根据每个字符的概率划分成小的子区间。当子区间小到一定程度最后结果的开头数字出现的时候,那些数字就能够“左移”出整个运算,并且用“右边”的数字替换–每次出现移位时,就大体相当于最初区间的一个回归放大(retroactive multiplication)。

关于算术编码的美国专利

许多算术编码所用的不同方法受美国专利的保护。其中一些专利对于实现一些国际标准中定义的算术编码算法是很关键的。在这种情况下,这些专利通常按照一种合理和非歧视RAND)授权协议使用(至少是作为标准委员会的一种策略)。在一些著名的案例中(包括一些涉及 IBM的专利)这些授权是免费的,而在另外一些案例中,则收取一定的授权费用。RAND条款的授权协议不一定能够满足所有打算使用这项技术的用户,因为对于一个打算生产拥有所有权软件的公司来说这项费用是“合理的”,而对于自由软件开源软件项目来说它是不合理的。

在算术编码领域做了很多开创性工作并拥有很多专利的一个著名公司是IBM。一些分析人士感到那种认为没有一种实用并且有效的算术编码能够在不触犯IBM和其它公司拥有的专利条件下实现只是数据压缩界中的一种持续的都会传奇(尤其是当看到有效的算术编码已经使用了很长时间最初的专利开始到期)。然而,由于专利法没有提供“明确界线”测试所以一种威慑心理总让人担忧法庭将会找到触犯专利的特殊应用,并且随着对于专利范围的详细审查将会发现一个不好的裁决将带来很大的损失,这些技术的专利保护然而对它们的应用产生了一种阻止的效果。至少一种重要的压缩软件bzip2,出于对于专利状况的担心,故意停止了算术编码的使用而转向Huffman编码。

关于算术编码的美国专利列在下面。

  • Patent 4,122,440 — (IBM) 提交日期 March 4, 1977, 批准日期 Oct 24, 1978 (现在已经到期)
  • Patent 4,286,256 — (IBM) 批准日期 Aug 25, 1981 (大概已经到期)
  • Patent 4,467,317 — (IBM) 批准日期 Aug 21, 1984 (大概已经到期)
  • Patent 4,652,856 — (IBM) 批准日期 Feb 4, 1986 (大概已经到期)
  • Patent 4,891,643 — (IBM) 提交时间 1986/09/15, 批准日期 1990/01/02
  • Patent 4,905,297 — (IBM) 批准日期 Feb 27, 1990
  • Patent 4,933,883 — (IBM) 批准日期 Jun 12, 1990
  • Patent 4,935,882 — (IBM) 批准日期 Jun 19, 1990
  • Patent 4,989,000 — (???) 提交时间 1989/06/19, 批准日期 1991/01/29
  • Patent 5,099,440
  • Patent 5,272,478 — (Ricoh)

注意:这个列表没有囊括所有的专利。关于更多的专利信息请参见后面的链接。[1]

算术编码的专利可能在其它国家司法领域存在,参见软件专利中关于软件在世界各地专利性的讨论。

 

参考

JBig2

From Wikipedia, the free encyclopedia

 

Jump to: navigation, search

 

JBIG2
Developed by Joint Bi-level Image Experts Group
Latest release 2
Contained by Portable Document Format, FAX
Standard(s) ITU T.88 & ISO/IEC 14492
Website http://jbig2.com/

JBIG2 is an image compression standard for bi-level images, developed by the Joint Bi-level Image Experts Group. It is suitable for both lossless and lossy compression. According to a press release[1] from the Group, in its lossless mode JBIG2 typically generates files one third to one fifth the size of Fax Group 4 and one half to one quarter the size of JBIG, the previous bi-level compression standard released by the Group. JBIG2 has been published in 2000 as the international standard ITU T.88,[2] and in 2001 as ISO/IEC 14492.[3]

Contents

[hide]

 Functionality

Ideally, a JBIG2 encoder will segment the input page into regions of text, regions of halftone images, and regions of other data. Regions which are neither text nor halftones are typically compressed using a context-dependent arithmetic coding algorithm called the QM coder. Textual regions are compressed as follows: the foreground pixels in the regions are grouped into symbols. A dictionary of symbols is then created and encoded, typically also using context-dependent arithmetic coding, and the regions are encoded by describing which symbols appear where. Typically, a symbol will correspond to a character of text, but this is not required by the compression method. For lossy compression the difference between similar symbols (e.g., slightly different impressions of the same letter) can be neglected; for lossless compression, this difference is taken into account by compressing one similar symbol using another as a template. Halftone images may be compressed by reconstructing the grayscale image used to generate the halftone and then sending this image together with a dictionary of halftone patterns. An overview of JBIG2 may be found in.[4] Overall, the algorithm used by JBIG2 to compress text is very similar to the JB2 compression scheme used in the DjVu file format for coding binary images.

PDF files versions 1.4 and above may contain JBIG2 compressed data. Open source decoders for JBIG2 are jbig2dec,[5] the java-based jbig2-imageio[6] and the decoder found in versions 2.00 and above of xpdf. An open source encoder is jbig2enc.[7]

Technical details

Typically, a bi-level image consists mainly of a large amount of textual and halftone data in which the same shapes appear repeatedly and the bi-level image is segmented into three regions: text, halftone, and generic regions. Each region is coded differently and the coding methodologies are described in the following passage.

 Text image data

Text coding is based on the nature of human visual interpretation. A human observer cannot tell the difference of two instances of the same characters in a bi-level image even though they may not exactly match pixel by pixel. Therefore, only the bitmap of one representative character instance needs to be coded instead of coding the bitmaps of each occurrence of the same character individually. For each character instance, the coded instance of the character is then stored into a “symbol dictionary”.[8] There are two encoding methods for text image data: pattern matching and substitution (PM&S) and soft pattern matching (SPM). These methods are presented in the following subsections.[9]

Block diagrams of (Left) pattern matching and substitution method and (Right) soft pattern matching method.

Pattern matching and substitution: After performing image segmentation and match searching, and if a match exists, we code an index of the corresponding representative bitmap in the dictionary and the position of the character on the page. The position is usually relative to another previously coded character. If a match is not found, the segmented pixel block is coded directly and added into the dictionary. Typical procedures of pattern matching and substitution algorithm are displayed in the left block diagram of the figure below. Although the method of PM&S can achieve outstanding compression, substitution errors could be made during the process if the image resolution is low.

Soft pattern matching: In addition to a pointer to the dictionary and position information of the character, refinement data is also required because it is a crucial piece of information used to reconstruct the original character in the image. The deployment of refinement data can make character-substitution error mentioned earlier highly unlikely. The refinement data contains the current desired character instance which is coded using the pixels of both the current character and the matching character in the dictionary. Since it is known that the current character instance is highly correlated with the matched character, the prediction of the current pixel is more accurate.

 Halftones

Halftone images can be compressed using two methods. One of the methods is similar to the context-based arithmetic coding algorithm which adaptively positions the template pixels in order to obtain correlations between the adjacent pixels. In the second method, descreening is performed on the halftone image so that the image is converted back to grayscale. The converted grayscale values are then used as indexes of fixed-sized tiny bitmap patterns contained in a halftone bitmap dictionary. This allows decoder to successfully render a halftone image by presenting indexed dictionary bitmap patterns neighboring with each other.

 Arithmetic entropy coding

All three region types including text, halftone, and generic regions may all use arithmetic coding. JBIG2 specifically uses the MQ coder.

Patents

Patents for JBIG2 are owned by IBM and Mitsubishi. Free licenses should be available after a request. JBIG and JBIG2 patents are not the same.[10][11][12]

References

  1. ^ Press release from the Joint Bi-level Image experts Group
  2. ^ “ITU-T Recommendation T.88 — T.88 : Information technology – Coded representation of picture and audio information – Lossy/lossless coding of bi-level images”. http://www.itu.int/rec/T-REC-T.88. Retrieved 2011-02-19.
  3. ^ “ISO/IEC 14492:2001 – Information technology — Lossy/lossless coding of bi-level images”. http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=22394. Retrieved 2011-02-19.
  4. ^ JBIG2-the ultimate bi-level image coding standard, by F. Ono, W. Rucklidge, R. Arps, and C. Constantinescu, in pp. 140–143, Proceedings, 2000 International Conference on Image Processing, (Vancouver, BC, Canada), vol. 1.
  5. ^ jbig2dec home page
  6. ^ open source jbig2 plugin for Java’s ImageIO
  7. ^ jbig2enc home page
  8. ^ F. Ono, W. Rucklidge, R. Arps, and C. Constantinescu, “JBIG2-the ultimate bi-level image coding standard,” Image Processing, 2000. Proceedings. 2000 International Conference on , vol.1, pp.140-143 vol.1, 2000.
  9. ^ P. Howard, F. Kossentini, B. Martins, S. Forchhammer, and W. Rucklidge, “The emerging JBIG2 standard,” Circuits and Systems for Video Technology, IEEE Transactions on , vol.8, no.7, pp.838-848, Nov 1998.
  10. ^ What is the patent situation with JBIG?, http://www.jpeg.org/jbig/faq.phtml?action=show_answer&question_id=q3f042a7298c94
  11. ^ What is JBIG2?, http://www.swiftview.com/pclcorner/pclcorner1.htm#JBIG2, retrieved 2012-04-07
  12. ^ JBIG2 patents, http://www.archivum.info/comp.compression/2009-07/00024/Re-JBIG2-patents.html, retrieved 2012-04-07

 External links

无损 JBIG2 编码库(Lossless JBIG2 Encoder)

http://www.cnblogs.com/pdfpatcher/archive/2012/02/01.html

有网友希望提供 PDFPatcher 的 JBIG2 编码库,因发此博文。

此处提供的编码库源自agl在Github的开源代码。该代码编译后输出 EXE 文件,编码现存位图文件或 StdIn 提供的数据,未提供被其它应用程序调用的 DLL 库。为了在 PDF 补丁丁中增加 JBIG2 编码功能,我修改了该代码,去除了其有损压缩功能及 Leptonica 图像库的依赖关系,减少了编码器的文件大小。

导出函数

DLL 库导出的函数有三个(除下列方法之外,还有原代码提供的jbig2_encode_generic方法,该方法的调用方式请参见原代码的说明):

jbig2_encode 方法用于编码传入的字节数组。其参数有六个:

  1. Width:图像宽度
  2. Height:图像高度
  3. Stride:一行像素所占的双字(DWORD)数
  4. ZeroIsWhite:将BW的0视为白色
  5. BW:图像的字节数组(Byte[]),此字节数组是原始黑白图像的二进制数据,默认情况下,二进制位1表示白色,0表示黑色
  6. Length:字节数组长度
  7. 传出参数:编码后的 JBIG2 字节数组

jbig2_encode 方法实际上是调用  jbig2_encode_generic方法,为方便从其它程序调用而设,见所附源代码。

release 方法用于释放 jbig2_encode 方法编码后字节数组所占用的内存,传入参数是 jbig2_encode 方法返回的指针。

 

 

 

下载(Download)

点击此处下载 JBIG2 无损压缩 DLL 库

Click here to download JBIG2 Lossless Compression DLL.