IM4J+GM处理网站图片

来源:互联网 发布:mac好用的绘画软件 编辑:程序博客网 时间:2024/04/23 22:28

IM4J+GM处理网站图片

现在做的网站需要保存用户上传的图片,同时需要进行压缩和图片切割等特殊效果的处理。


一开始我们用的是JMagick+ ImageMagick处理用户上传的图片,但是存在一个非常严重的问题,Tomcat在跑了大概10天左右后会crash掉,异常内容为:


magick.MagickException: Unable to retrieve handle

从表象看,应该是没有释放ImageMagick的句柄导致的,查找API后发现程序中没有调用


 


magick.MagickImage.destroyImages() Called by finalize to deallocate the image handle.

在程序加上本方法,情况有所改善,大概在40天左右后出现了一次tomcat进程crash。


 


似乎并没有从本质上找到问题的根本。。。


在JMagick的邮件列表中找到一份我认为有价值的邮件,http://sourceforge.net/mailarchive/message.php?msg_name=20cf28cd1002231148s33c99843q875f59906dd32b8b%40mail.gmail.com


里面讲到了JMagick作为应用服务的缺点,并建议可以使用IM4JAVA:


The "JNI hazard" here is that if something you use (f.ex libtiff for reading
TIFF files) has a memory bug then it can make your whole JVM crash. Thats of
course frustrating and therefore its great to have im4java around, which
starts IM as an external process, so JVM crashes are avoided.
* *
Coolest thing would be if JMagick and im4java could have the same API so it
was easy to switch depending on luckyness. Ive asked the author of im4java
to attemt to be as compatible as possible, but as im4java is very much
different internally its limited how much can be done in that direction.

If you don't like the risk, stick to im4java. If your want optimal
performance give JMagick a try.

And, its not JMagick that is buggy, its what it depends on (hereunder IM)
that is not always (memory) bug free on long running processes.
I also have never seen a mismatch between JMagick binary and ImageMagick
binaries leading to crashes.

 


所以我把思路转向了IM4Java。


IM4Java的官网http://im4java.sourceforge.net/index.html


在 Developer's Guide
中提到im4java支持ImageMagick和GraphicsMagick。GraphicsMagick是ImageMagick的一个分支,相对于ImageMagick而言,TA处理速度更快,消耗资源更少,并且大的图片处理网站,如 Flickr
and Etsy 已经在使用TA了。


下载GraphicsMagick的Q8版本(还有Q16、Q32的,版本见的区别可以查看ImageMagick的官网,大致意思是每像素用多少bit来存储信息,16、32要比8消耗更多的内存^_^)。


下面这段话是在GraphicsMagick的邮件列表中找到的:


> I've got question about IM Q16 & Q8. What's a difference between that two versions?
I know, that Q16 version takes 2 times more memory than Q8.
But is that so great precision in algorithm is needed in converting jpegs, gif or pngs
(I need IM for converting that types of formats)

& JPEG and GIF only have 8-bit versions, so there will almost certainly be no benefit to using Q16.
It is possible to have 16-bit PNGs, but if you have to ask, you probably don't have to worry about it

安装GraphicsMagick和IM4Java非常简单,按照官网做就ok了,下面是一个简单的例子:


 


/**
* 居中切割图片(不支持gif图片切割)
* 1、如果源图宽高都小于目标宽高,则只压缩图片,不做切割
* 2、如果源图宽高都大于目标宽度,则根据宽度等比压缩后再居中切割
* 3、其它条件下,则压缩图片(不做缩放)后再居中切割
*
* 该方法在知道源图宽度(sw)和高度(sh)的情况下使用
*
* @param srcPath 源图路径
* @param desPath 切割图片保存路径
* @param sw 源图宽度
* @param sh 源图高度
* @param dw 切割目标宽度
* @param dh 切割目标高度
* @throws Exception
*/
public void cropImage(String srcPath, String desPath, int sw, int sh, int dw, int dh) throws Exception {

if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0)
return;

IMOperation op = new IMOperation();
op.addImage();

if((sw <= dw) && (sh <= dh)) //如果源图宽度和高度都小于目标宽高,则仅仅压缩图片
{
op.resize(sw, sh);
}

if((sw <= dw) && (sh > dh)) //如果源图宽度小于目标宽度,并且源图高度大于目标高度
{
op.resize(sw, sh); //压缩图片
op.append().crop(sw, dh, 0, (sh-dh)/2);//切割图片
}

if((sw > dw) && (sh <= dh)) //如果源宽度大于目标宽度,并且源高度小于目标高度
{
op.resize(sw, sh);
op.append().crop(dw, sh, (sw - dw)/2, 0);
}

if(sw > dw && sh > dh) //如果源图宽、高都大于目标宽高
{
float ratiow = (float)dw / sw; //宽度压缩比
float ratioh = (float)dh / sh; //高度压缩比

if(ratiow >= ratioh) //宽度压缩比小(等)于高度压缩比(是宽小于高的图片)
{
int ch = (int)(ratiow * sh); //压缩后的图片高度

op.resize(dw, null); //按目标宽度压缩图片
op.append().crop(dw, dh, 0, (ch > dh)?((ch - dh)/2):0); //根据高度居中切割压缩后的图片
}
else //(宽大于高的图片)
{
int cw = (int)(ratioh * sw); //压缩后的图片宽度

op.resize(cw, null); //按计算的宽度进行压缩
op.append().crop(dw, dh, (cw > dw)?((cw - dw)/2):0, 0); //根据宽度居中切割压缩后的图片

}
}

op.addImage();

ConvertCmd convert = new ConvertCmd(ture);

convert.run(op, srcPath, desPath);

}
原创粉丝点击