虽然曾经学过图像处理,对图像处理的基础理论还是很有感悟,但是没有真正做过图像处理方面的开发。在学《数字图像处理》《数字图像分析》《图像恢复与重建》等课程时,做过一些实验,主要是验证一些经典算法;但是工程和实验还是有很大差别的。这次有机会做了一个图像处理相关的服务端程序,这种感觉很明显。
在做实验室,主要是针对算法,所处理的对象都是已经读入的二维数组,基本上是一个数学问题。
但是实际项目中,可能会化更多的时间在图像格式的问题上。这一般使用一些图像处理库来做的,当然也可以自己写;如果能自己写一个处理互联网上各种图像的程序,那收获一定不小。总而言之,我还是决定使用第三方库:)
1, FreeImage,这是规模中等的库。简单的看了一下它的设计框架,印象最深刻的一点是一种类似Linux文件系统的read/write/seek接口——上层调用read/write/seek,但是具体是什么由下层模块决定,即把内存管理方式屏蔽了,可以是文件,也可以是内存,还可以由用户自己去实现。
FreeImage底层是用C实现的,上层封装的有C++接口,如fipMuiltiPage之类,但是封装的不太好。例如,它的大部分成员函数都是返回bool型,只知道成功与否,而不知道具体错误原因。
另外,FreeImage在读某些jpg文件的exif时出现分配巨大内存的问题,后来只好注释掉读取exif的代码。当然这是jpg文件本身的错误,但是也说明FreeImage的容错能力有限,对于服务器端开发不太合适。
FreeImage的C++接口对gif的处理也不太好处理时,很多操作没有反应。
2,ImageMagick是一个巨大的图像处理库,它本身也是提供一套命令行工具,提供perl、php、c++等接口,当然他的底层也是用C语言写的。
ImageMagick的实现框架没有深入研究,但是单从其C++封装来看,非常好用。
1)提供了异常机制,对于图像处理这种大量内存操作来说,出现异常还是很容易的,尤其是读入一个图片时,格式不对、数据被破坏等问题都可能导致不可预知的错误。
2)ImageMagick提供了Blob类作为内存块管理的接口,这个简单的类给使用者提供了较大的灵活性。使得用户的内存管理和ImageMagick的内存管理又一个明显的界限和结合点。
3)以Image类代表一帧图像,几乎所有的操作函数都是在Image类中实现的。
4)提供了大量的算法可供选择,例如采样、量化、模糊等。
5)以STL的扩展来提供多帧图像(如gif)的处理能力,这种设计很好用,但是当时我又一个疑惑是:是不是多有的多帧图像都能转换成“独立”的单帧呢?而且,即便现在是这样,今后会不会出现不能的情况呢?ImageMagick既然这样实现,估计还是有这个信心的。
6)调用第三方程序处理。有些格式转换可能不能归结为图像处理问题,ImageMagick可以调用第三方软件。例如如果输入是一个html文件,它会试图去找html2ps去转换,找不到则抛出异常。总之,提供了这种扩展能力。
但是ImageMagick6.5.7之前的版本又一个问题,读某些png图片时会崩溃,跟踪代码发现是底层C++代码在开启-O2优化时的异常行为,如果不打开这个优化则不会崩溃,但是性能差很多。在6.5.7之后这个问题修复了。
这是对ImageMagick库的一个浅显的认识,但是其架构让人感觉很大气。
ImageMagick的编译安装
到官网上下载最新的版本,例如ImageMagick-x.y.z-n.tar.bz2;同时在其网站上的delegates目录下下载jasper、jpeg、tiff、png等库的代码。如果要支持lzw压缩,还需要从网上搜一个叫libtiffxxx的库。
先依次编译安装jpeg、jasper、png、tiff到某个目录,例如/home/me/programs/。需要注意的是变异tiff时需要把libtiff包(指包含一个tif_lzw.c文件)中的tif_lzw.c文件拷贝到tiff的子目录libtiff下覆盖原来的;这样tiff就有了lzw压缩的能力。
另一个要注意的是编译jasper时,在configure阶段需要显示指定./configure CFLAGS=” -fPIC” –prefix=/home/me/programs/,否则生成的代码不能重定位,编译ImageMagick的链接阶段会出错。
然后解压ImageMagick-x.y.z-n.tar.bz2,进入该目录。./configure CPPFLAGS=” -I/home/me/programs/include” LDFLAGS=” -L/home/me/programs/lib” –prefix=/home/me/programs –with-png=yes –with-tiff=yes –with-perl=no –with-jpeg=yes然后make install即可。这里with-perl=no是因为perl接口会到/usr/local/下安装文件,可能没有权限。
安装好了,运行还需要一些设置:
需要到处环境变量LD_LIBRARY_PATH=/home/me/programs/lib
PATH=$PATH:/home/me/programs/bin
MAGICK_CODER_MODULE_PATH=/home/me/programs/ImageMagick-6.5.7/modules-Q16/coders/
还有其他环境变量,上面几个是必须的,其他的详见:
http://www.imagemagick.org/script/resources.php