日期:2014-05-20  浏览次数:20910 次

Imagemagick+Jmagick合成大图片内存溢出
public static boolean resize(String fromPath, int w, int h) {  
log.debug("开始压缩图片"+fromPath);
try {
FileInputStream f = new FileInputStream (fromPath) ;
//数组的大小和文件的大小一致
byte[] b = new byte[f.available()]; 
f.read(b);
f.close() ;
ImageInfo info = new ImageInfo() ;
MagickImage image = new MagickImage(info,b);
MagickImage scaled = image.scaleImage(w ,h);
scaled.setFileName(fromPath);
scaled.writeImage(info);
scaled.destroyImages() ;
log.debug("图片压缩成功!");
return true;
} catch (FileNotFoundException e) {
e.printStackTrace();
return false;
} catch (IOException e) {
e.printStackTrace();
return false;
} catch (MagickException e) {
e.printStackTrace();
return false;
}
  }  

图片缩放,裁减等操作时,图片的像素唱过6000x9000或者上万的时候处理速度就极慢,而且造成死机、当机、其他程序不能运行,不能做任何操作等;有没有大牛帮忙出出主意,用什么方式能够提高图片处理速度,降低cpu和内存的占用率,并且不降低图片处理的效果的!在线等!

------解决方案--------------------
在你的启动命令加入下面的参数试试
java -Xms1024m -Xmx2048m Text
原则上32位JDK最大内存不超过4G,64位JDK不超过128G,应该不会出错了

JAVA不像C++可以操作指针,文件都是一次性加载,你要保证启动时的初始化最大内存够用,否则就会报内存溢出。
------解决方案--------------------
byte[] b = new byte[f.available()];
f.read(b);
f.close() ;

图片如果比较大,你这样创建数组,每次都分配这么大的空间,而且你后面还要处理图片转换,虽然是用jni方式调用的,但是imagemagick本身效率就不高,肯定要等待,内存又不能立即释放,线程一多,肯定容易挂了。。

建议: 把图片转换功能抠出来,异步处理。弄几个线程跑,线程放池里,每次并发10个左右的线程,把你要转换的参数放队列中,这样内存占用率不会高的,既提高效率又能重复利用
------解决方案--------------------
这个问题,好像最直观的方法,就是加大JVM占用内存,但是如果图片太大了,超过可用的最大内存,也还是没有办法处理。
非要在java里处理吗?用其它做图软件不可以吗?
------解决方案--------------------
把图片分割成4X4或8X8,分别处理.再拼起来.哈哈.