java图片处理解决方案

项目需要调整图片服务器的解决方案,这次调整使用fastdfs存储小文件,也就是图片,因为现在还没有fastdfs的.net版的客服端,所以理所当然把处理图片放到了java这块,使用java来处理图片并且上传到fastdfs上。

之前还真没用java整过图片,因为一般没这个需求,现在的需求是要根据前台传过来的尺寸进行图片的缩略,自适应缩放,留白,加水印操作。

一开始我使用jdk自带的一套图片处理库来处理图片,也就是sun的JPEGCodec,测试发现它会把所有的图片全部转换成jpeg格式,也就是说把bmp,gif,png这种格式的图片全部转换成了jpeg格式,而且对于gif动画图片缩放就只能对第一帧缩放,所以对于gif这种的的缩放完之后就“不动了”。

之后使用Graphics2D+ImageIO的方式,先判断图片的格式,然后缩放的时候强制的把图片格式作为参数传给ImageIO来处理,
ImageIO.write(image, pic_type, out);


但是对于gif动画图片缩放也只对第一帧缩放,所以对于gif这种的的缩放完之后也是“不动了”。
最后在网上发现了一个架包 --gif4j ,它可以对gif动画图片进行缩放但是对于加水印和留白操作就无能为力了。

最后在做压力测试时发现,使用这种方式(java的jdk+gif4j),特别是对于大图的操作,大图我这边测试的是6~7M的图片,发现非常非常耗cpu和内存,当然程序已经优化过的前提下测试,图片都以流的方式进行操作。但是这种cpu和内存的消耗简直是开玩笑了,要是需要处理的图片一多,每秒过百的请求服务器就得卡死,而且这种方式处理的图片质量不是特别高。


在这种方案放弃之后,发现了ImageMagick。
ImageMagick (TM) 是一个免费的创建、编辑、合成图片的软件。它可以读取、转换、写入多种格式的图片。图片切割、颜色替换、各种效果的应用,图片的旋转、组合,文本,直线,多边形,椭圆,曲线,附加到图片伸展旋转。ImageMagick的大多数功能的使用都来源于命令行工具。它还支持以下程序语言: Perl, C, C++, Python, PHP, Ruby, Java;现成的ImageMagick接口(PerlMagick, Magick++, PythonMagick, MagickWand for PHP, RubyMagick, and JMagick)是可利用的。


利用Java 的JNI(java本地调用),依赖操作系统提供的功能, 操作批量、大图片,这种方式效率比较高。
然后当然是开搞,ImageMagick 在windows和linux下的配置稍有不同,详细情况可以参考:http://www.imagemagick.org/script/index.php


下面贴出使用JMagick调用Imagemagick进行缩略的代码。


public void resize1(String src, String dsec, int width, int height,
int quality) {
ImageInfo info = null;
MagickImage image = null;
Dimension imageDim = null;
MagickImage scaled = null;
try {
info = new ImageInfo(src);
info.setQuality(quality);
image = new MagickImage(info);
imageDim = image.getDimension();

int srcW = imageDim.width;
int srcH = imageDim.height;

int[] i = PicUtil.getWandH(srcW, srcH, width, height, 1);

scaled = image.scaleImage(i[0], i[1]);
scaled.setFileName(dsec);
scaled.writeImage(info);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (scaled != null) {
scaled.destroyImages();
}
if (image != null) {
image.destroyImages();
}
}
}



这里注意,使用完之后要释放资源。

if (scaled != null) {
scaled.destroyImages();
}
if (image != null) {
image.destroyImages();
}


否则会很伤,你懂的。


加水印代码:
	public void addWater(String src, String src_biao, String dsrc,
int position, int quality) {
ImageInfo info = null;
ImageInfo logo_info = null;
MagickImage image = null;
MagickImage logo_image = null;
Dimension imageDim = null;
Dimension logo_imageDim = null;
// MagickImage compositeimage = null;
try {
info = new ImageInfo(src);
info.setQuality(quality);
image = new MagickImage(info);
imageDim = image.getDimension();
logo_info = new ImageInfo(src_biao);
logo_image = new MagickImage(logo_info);
logo_imageDim = logo_image.getDimension();

int[] ii = WaterPosition.position(position, imageDim.width,
logo_imageDim.width, imageDim.height, logo_imageDim.height);
image.compositeImage(CompositeOperator.AtopCompositeOp, logo_image,
ii[0], ii[1]);
image.setFileName(dsrc);
image.writeImage(info);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (logo_image != null) {
logo_image.destroyImages();
}
if (image != null) {
image.destroyImages();
}
}
}



代码都整完之后,进行压力测试,问题出来了,java调用JNI的方式存在内存隐患,至于原因,可以网上查查。现在的情况就是如果可以10天半个月重启下服务,那没问题,但是如果长时间的跑着服务,它会把内存耗尽,然后死掉。

很郁闷,是吧,我也很郁闷。但我想做就做个NB点的吧,然后发现了GraphicsMagick+im4java这种方式。
具体的不介绍了,网上资料很少,例子代码更少,我在这里贴几段,仅供参考。


缩放代码:
	public void resize1(String src, String dsec, int o_width, int o_heigh,
int width, int height, double quality) {
int[] i = PicUtil.getWandH(o_width, o_heigh, width, height, 1);
ConvertCmd cmd = new ConvertCmd(true);
IMOperation op = new IMOperation();
op.addImage(src);
op.scale(i[0], i[1]);
op.quality(quality);
op.addImage(dsec);
try {
cmd.run(op);
} catch (Exception e) {
log.error(e,e);
}
}



加水印:

	public void addWater(String src, String src_biao, String dsrc,
int position, double quality) {
CompositeCmd cmd = new CompositeCmd(true);
IMOperation op = new IMOperation();
op.gravity(WaterPosition.positionMagick(position));
op.quality(quality);
op.addImage();
op.addImage();
op.addImage();
try {
cmd.run(op, src_biao, src, dsrc);
} catch (Exception e) {
log.error(e,e);
}
}


我大功告成了!
请将后戳名改成.rar然后解压,然后将其导入项目里,注释:必须为shh方案的javaweb 项目 <!-- fck编辑器 --> <servlet> <servlet-name>SimpleUploader</servlet-name> <servlet-class> com.fredck.FCKeditor.uploader.SimpleUploaderServlet </servlet-class> <init-param> <!-- 此参数用于设置文件上传路径 --> <param-name>baseDir</param-name> <param-value>/UserFiles/</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>true</param-value> </init-param> <init-param> <!-- 此参数用于设置是否开启上传功能 --> <param-name>enabled</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>AllowedExtensionsFile</param-name> <param-value></param-value> </init-param> <init-param> <!-- 此参数用于设置禁止上传的文件类型 --> <param-name>DeniedExtensionsFile</param-name> <param-value> php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi </param-value> </init-param> <init-param> <param-name>AllowedExtensionsImage</param-name> <param-value>jpg|gif|jpeg|png|bmp</param-value> </init-param> <init-param> <param-name>DeniedExtensionsImage</param-name> <param-value></param-value> </init-param> <init-param> <param-name>AllowedExtensionsFlash</param-name> <param-value>swf|fla</param-value> </init-param> <init-param> <param-name>DeniedExtensionsFlash</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet> <servlet-name>Connector</servlet-name> <servlet-class> com.fredck.FCKeditor.connector.ConnectorServlet </servlet-class> <init-param> <param-name>baseDir</param-name> <param-value>/UserFiles/</param-value> </init-param> <init-param> <param-name>debug</param-name> <param-value>false</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- fck编辑器 -->
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值