关于GraphicsMagick+im4java的研究心得【原创】

        做网站往往需要处理各种各样的图片,对于jdk自带的一套图片处理库,他的特点是稳定简单,但是对图片处理来说,性能确实很不咋的!
        于是我转向了以C++处理为核心的java处理包—— JMagick+ ImageMagick 。jmagick是一个开源的API,利用JNI(Java Native Interface)技术实现了对ImageMagickAPI 的Java访问接口,因此也将比纯Java实现的图片操作函数在速度上要快。实地测试后发现,速度果然提高了不少,但是质量却大大下降了,在大量测试数据下,每生成100张图片约会有5张图片生成出现错误,还会出现down机的情况。对于一个商业应用来说,这个是绝对不可以接受的,于是对jmagick的研究暂放一段时间。
        经过韩boss指导,我转向了 GraphicsMagick+im4java 的研究,输入关键词google一下,很容易就可以找到http://javantsky.iteye.com/blog/747807 ,这篇博客,文章介绍GraphicsMagick+im4java 性能高,运行稳定!
        于是我开始了对GraphicsMagick+im4java实际研究:
        个人感觉im4java就是graphicsmagick的外面包装了一层“纸”,一个java转换的命令行输出工具,其api也基本没有参考价值(有些与实际不符的地方),GraphicsMagick+im4java的核心在于GraphicsMagick。
        作为一个缩放+切割功能的实现,可以使用

gm convert input.jpg -thumbnail 100x100^ -gravity center -extent 100x100 output.jpg

         这条命令,经过测试发现,thumbnail命令的效率还不如原有java实现的效率,可能用它来实现这么简单的功能是高射炮打蚊子了,关于GraphicsMagick各项参数的使用的文章,网上实在是少之又少,于是只能靠自己了!
        我找到了所有和缩放有关的命令,经过一一验证,最终选择了sample命令。相比最初的纯java实现,内存节省了约70%,CPU效率提高了约80%,耗费时间约节省了72%,下面为我找到的所有缩放有关的GraphicsMagick命令的测试数据:
Graphics+im4java性能对比:
        记录一(其中内存和CPU为观测数据):
        原有java实现:
            图片大小:2.5M(2592x1944)
            内存:1185M(共)
            CPU:170%(共)(按双核)
            耗时:162,875ms/200张(线程池10)
            输出图片大小:36.1K

        thumbnail命令实现:

gm convert input.jpg -thumbnail 600x600^ -gravity center -extent 600x600 output.jpg

            图片大小:2.5M(2592x1944)
            内存:150M/线程
            CPU:9%/线程
            耗时:193,423ms/200张(线程池10)
            输出图片大小:78.5K

        geometry命令实现:

gm convert input.jpg -geometry 600x600^ -gravity center -extent 600x600 output.jpg

            图片大小:2.5M(2592x1944)
            内存:50M/线程
            CPU:9%/线程
            耗时:94,518ms/200张(线程池10)
            输出图片大小:101.8K

        resize命令实现:

gm convert input.jpg -resize 600x600^ -gravity center -extent 600x600 output.jpg

              图片大小:2.5M(2592x1944)

            内存:55M/线程
            CPU:13%/线程
            耗时:97,342ms/200张(线程池10)
            输出图片大小:101.8K

        sample命令实现:

gm convert input.jpg -sample 600x600^ -gravity center -extent 600x600 output.jpg

              图片大小:2.5M(2592x1944)

            内存:35M/线程
            CPU:9%/线程
            耗时:46,541ms/200张(线程池10)
            输出图片大小:117.3K

        sample(quality:50)

gm convert input.jpg -sample 600x600^ -gravity center -extent 600x600 -quality 50 output.jpg

            图片大小:2.5M(2592x1944)
            内存:40M/线程
            CPU:16%/线程
            耗时:68,839ms/200张(线程池10)
            输出图片大小:47.2

        scale命令实现:

gm convert input.jpg -scale 600x600^ -gravity center -extent 600x600 output.jpg

              图片大小:2.5M(2592x1944)

            内存:42M/线程
            CPU:8%/线程
            耗时:68,778ms/200张(线程池10)
            输出图片大小:99.2K

        在sample命令下,可以通过修改quality参数的值,来修改输出图片质量,改变输出图片大小。以下为我的测试数据:
        记录二:

            sample对比(无quality设置):
            图片大小:2.5M(2592x1944)
            内存:32(\)M/线程
            CPU:9%/线程
            耗时:46,659ms/200张(线程池10)
            输出图片大小:117.3K

            sample(quality:50)
            图片大小:2.5M(2592x1944)
            内存:28M/线程
            CPU:9%/线程
            耗时:40,549ms/200张(线程池10)
            输出图片大小:48.8

            sample(quality:60)
            图片大小:2.5M(2592x1944)
            内存:35M(\)/线程
            CPU:8%(\)/线程
            耗时:45,647ms/200张(线程池10)
            输出图片大小:53.3

            sample(quality:75)
            图片大小:2.5M(2592x1944)
            内存:30M(\)/线程
            CPU:9%(\)/线程
            耗时:45,719ms/200张(线程池10)
            输出图片大小:65.6

            sample(quality:85)
            图片大小:2.5M(2592x1944)
            内存:32M(\)/线程
            CPU:8%(\)/线程
            耗时:46,510ms/200张(线程池10)
            输出图片大小:84.5

            sample(quality:95)
            图片大小:2.5M(2592x1944)
            内存:34M(\)/线程
            CPU:8%(\)/线程
            耗时:47,650ms/200张(线程池10)
            输出图片大小:156.0

            sample(quality:100)
            图片大小:2.5M(2592x1944)
            内存:34M(\)/线程
            CPU:11%(\)/线程
            耗时:50,469ms/200张(线程池10)
            输出图片大小:298.1

ConvertCmd cvcmd = new ConvertCmd();
Operation op = new Operation();
op.addImage();
op.addRawArgs("-sample", "600x600^");
op.addRawArgs("-gravity", "center");
op.addRawArgs("-extent", "600x600");
op.addRawArgs("-quality", "100");
op.addImage();

cvcmd.run(op, srcImg, desImg);

        这是我从文小猫童鞋那里找到的一张她自制的美食图片,源图像文件像素为1944x2592,处理后为600x600;


关于GraphicsMagick+im4java的研究心得【原创】

        由于个人能力有限,欢迎大家指出不足,提出更好的解决方案!

        欢迎大家访问我们的网站http://meishidaren.com

        im4java官方网站:
        http://im4java.sourceforge.net/index.html
        im4java的api:
        http://im4java.sourceforge.net/api/
        graphicsmagick的官方网站:
        http://www.graphicsmagick.org/index.html
        graphicsmagick的命令行参数解析:
        http://www.graphicsmagick.org/utilities.html