`
shz2008bj
  • 浏览: 489076 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

预览图生成策略

阅读更多
有一段时间内存老涨,跟踪到图片上传可能有问题
测了一下:

LoadRunner场景:
每10秒加16个VUser
VUser总量800
分4台PC代理执行
全部robot相册表单上传图片一个功能点

分步压力测试:
1.使用现有程序
20多分钟后大概上传了5000多张1024*768的桌面图片后,
jprofiler显示内存堆占据极大,主要是byte类占据
top一下,发现java进程占了1.9G内存,而且还在涨。
负载也很高:load average: 24.18, 0.15, 0.09

2.将上传图片功能完全注释掉,只剩下空壳
半个小时后,内存保持在600M-800M
负载正常:load average: 0.07, 0.04, 0.15
正常
如此看来上传图片功能是有问题。

3.将上传图片功能留下,把其后的生成预览图注释掉。
半个小时后,内存保持在800M-900M
正常
如此看来commons-upload没问题(否则就要试一下改用cos等上传组件),
可能是生成预览图有问题

检查生成预览图程序,是直接用J2D的Graphic2D将图画出来,用iio保存的

优化:
将预览图程序重构为策略模式。
将所有可能方案作为策略实现,一个个试。
通过查资料,
找到:awt,j2d,jai,iio,jmagick,imagej,imagemanip等方案。

Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.Dimension;  
  4. import java.io.File;  
  5. import java.io.IOException;  
  6.   
  7. import org.apache.commons.io.FileUtils;  
  8. import org.apache.commons.logging.Log;  
  9. import org.apache.commons.logging.LogFactory;  
  10.   
  11. /** 
  12.  *  
  13.  * 此类负责与调用者打交道 
  14.  *  
  15.  * @author 梁飞 liangfei0201@163.com 
  16.  * 
  17.  */  
  18. public class PreivewManager {  
  19.       
  20.     protected static final Log log = LogFactory.getLog(PreivewManager.class);  
  21.       
  22.     private PreviewGenerator previewGenerator;  
  23.       
  24.     public PreivewManager(PreviewGenerator previewGenerator) {  
  25.         this.previewGenerator = previewGenerator;  
  26.     }  
  27.       
  28.     /** 
  29.      * 一些通用的处理就在这先做了 
  30.      *  
  31.      * @param source 
  32.      * @param target 
  33.      * @param width 
  34.      * @param height 
  35.      * @throws IOException 
  36.      */  
  37.     public void generatePreview(String source, String target, int width, int height) throws IOException {  
  38.         if (source == null || ! new File(source).exists()) {  
  39.             return;  
  40.         }  
  41.         checkDir(target);  
  42.           
  43.         Dimension d = previewGenerator.getSize(source);  
  44.         int w = (int)d.getWidth();  
  45.         int h = (int)d.getHeight();  
  46.         if (w <= width && h <= height) {  
  47.             copy(source, target); //如果图片较小,就直接copy过去  
  48.         } else {  
  49.             //同比缩放  
  50.             if (w > width || h > height) {  
  51.                 if(w * height > h * width){  
  52.                     height = h * width / w;  
  53.                 }else{  
  54.                     width = w * height / h;  
  55.                 }  
  56.             } else {  
  57.                 width = w;  
  58.                 height = h;  
  59.             }  
  60.             previewGenerator.generate(source, target, width, height);  
  61.         }  
  62.         return ;  
  63.     }  
  64.       
  65.     private void checkDir(String target) {  
  66.         File dir = new File(target).getParentFile();  
  67.         if (! dir.exists()) {  
  68.             dir.mkdirs();  
  69.             log.warn(dir.getAbsolutePath() + " not exists! already auto made!");  
  70.         }  
  71.     }  
  72.       
  73.     private void copy(String source, String target) throws IOException {  
  74.         FileUtils.copyFile(new File(source), new File(target));  
  75.     }  
  76. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.Dimension;  
  4. import java.io.IOException;  
  5.   
  6. /** 
  7.  *  
  8.  * 预览图生成的策略接口 
  9.  *  
  10.  * @author 梁飞 liangfei0201@163.com 
  11.  * 
  12.  */  
  13.   
  14. public interface PreviewGenerator {  
  15.       
  16.     /** 
  17.      * 主要用于判断是否为大图,小图就copy 
  18.      * @param source 源图片位置 
  19.      * @return Dimension 图片的大小 
  20.      * @throws IOException 
  21.      */  
  22.     public Dimension getSize(String source) throws IOException;  
  23.       
  24.     /** 
  25.      * 处理生成预览图的策略方法 
  26.      * 大小判定,比例调整已在PreivewManager,请直接使用width,height 
  27.      * @param source 源图片位置 
  28.      * @param target 保存预览图位置 
  29.      * @param width 预览图宽度 
  30.      * @param height 预览图高度 
  31.      * @throws IOException 
  32.      */  
  33.     public void generate(String source, String target, int width, int height) throws IOException;  
  34.       
  35. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4. import java.io.IOException;  
  5.   
  6. /** 
  7.  *  
  8.  * BufferedImage 的读写处理策略接口 
  9.  *  
  10.  * @author 梁飞 liangfei0201@163.com 
  11.  * 
  12.  */  
  13. public interface ImageProvider {  
  14.       
  15.     public BufferedImage readImage(String source) throws IOException;  
  16.       
  17.     public void saveImage(BufferedImage image, String target) throws IOException;  
  18.   
  19. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4. import java.io.BufferedInputStream;  
  5. import java.io.BufferedOutputStream;  
  6. import java.io.FileInputStream;  
  7. import java.io.FileOutputStream;  
  8. import java.io.IOException;  
  9.   
  10. import com.sun.image.codec.jpeg.JPEGCodec;  
  11. import com.sun.image.codec.jpeg.JPEGImageDecoder;  
  12. import com.sun.image.codec.jpeg.JPEGImageEncoder;  
  13.   
  14. /** 
  15.  *  
  16.  * Sun的非标准JPEG处理类,没ImageIO之前,全靠它撑着 
  17.  *  
  18.  * @author 梁飞 liangfei0201@163.com 
  19.  * 
  20.  */  
  21.   
  22. public class CodecImageProvider implements ImageProvider {  
  23.   
  24.     public BufferedImage readImage(String source) throws IOException {  
  25.         BufferedInputStream bis = null;  
  26.         try {  
  27.             bis = new BufferedInputStream(new FileInputStream(source));  
  28.             JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(bis);  
  29.             return decoder.decodeAsBufferedImage();  
  30.         } finally {  
  31.             if (bis != null) {  
  32.                 bis.close();  
  33.             }  
  34.         }  
  35.     }  
  36.   
  37.     public void saveImage(BufferedImage image, String target) throws IOException {  
  38.         BufferedOutputStream bos = null;  
  39.         try {  
  40.             bos = new BufferedOutputStream(new FileOutputStream(target));  
  41.             JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos);  
  42.             encoder.encode(image);  
  43.         } finally {  
  44.             if (bos != null) {  
  45.                 bos.close();  
  46.             }  
  47.         }  
  48.     }  
  49.   
  50. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.image.BufferedImage;  
  4. import java.io.File;  
  5. import java.io.IOException;  
  6. import java.util.Iterator;  
  7.   
  8. import javax.imageio.IIOImage;  
  9. import javax.imageio.ImageIO;  
  10. import javax.imageio.ImageTypeSpecifier;  
  11. import javax.imageio.ImageWriteParam;  
  12. import javax.imageio.ImageWriter;  
  13. import javax.imageio.stream.ImageOutputStream;  
  14.   
  15. /** 
  16.  *  
  17.  * 标准的Java实现图形处理包,处理性能待考量 
  18.  *  
  19.  * @author 梁飞 liangfei0201@163.com 
  20.  * 
  21.  */  
  22.   
  23. public class IioImageProvider implements ImageProvider {  
  24.   
  25.     public BufferedImage readImage(String source) throws IOException {  
  26.         return ImageIO.read(new File(source));  
  27.     }  
  28.   
  29.     public void saveImage(BufferedImage image, String target) throws IOException {  
  30.         File targetFile = new File(target);  
  31.         ImageWriter writer = null;  
  32.         ImageOutputStream outputStream = null;  
  33.         try {  
  34.             ImageTypeSpecifier type = ImageTypeSpecifier  
  35.                     .createFromRenderedImage(image);  
  36.             Iterator iterator = ImageIO.getImageWriters(type, "JPEG");  
  37.             if (!iterator.hasNext()) {  
  38.                 return;  
  39.             }  
  40.             writer = (ImageWriter) iterator.next();  
  41.             IIOImage iioImage = new IIOImage(image, nullnull);  
  42.             ImageWriteParam param = writer.getDefaultWriteParam();  
  43.             param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);  
  44.             param.setCompressionQuality(1.0f);  
  45.             outputStream = ImageIO.createImageOutputStream(targetFile);  
  46.             writer.setOutput(outputStream);  
  47.             writer.write(null, iioImage, param);  
  48.         } finally {  
  49.             if (outputStream != null) {  
  50.                 outputStream.close();  
  51.             }  
  52.             if (writer != null) {  
  53.                 writer.abort();  
  54.             }  
  55.         }  
  56.     }  
  57.   
  58. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.Dimension;  
  4. import java.awt.Image;  
  5. import java.awt.Toolkit;  
  6. import java.io.IOException;  
  7.   
  8. /** 
  9.  *  
  10.  * 最原始的方法,Toolkit一般用于桌面加载图片,调用的地方到处是ImageObserver 
  11.  *  
  12.  * @author 梁飞 liangfei0201@163.com 
  13.  * 
  14.  */  
  15. public class AwtPreviewGenerator implements PreviewGenerator {  
  16.   
  17.     public Dimension getSize(String source) throws IOException {  
  18.         Image image = Toolkit.getDefaultToolkit().getImage(source);  
  19.         return new Dimension(image.getWidth(null), image.getHeight(null));  
  20.     }  
  21.   
  22.     public void generate(String source, String target, int width, int height)  
  23.             throws IOException {  
  24.         Image image = Toolkit.getDefaultToolkit().getImage(source);  
  25.         image = image.getScaledInstance(width, height, Image.SCALE_FAST);  
  26.         // TODO Image保存方式待定  
  27.         // imageProvider.saveImage((BufferedImage)image, target);  
  28.     }  
  29.   
  30. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.Color;  
  4. import java.awt.Dimension;  
  5. import java.awt.Graphics2D;  
  6. import java.awt.RenderingHints;  
  7. import java.awt.image.BufferedImage;  
  8. import java.io.IOException;  
  9.   
  10. /** 
  11.  *  
  12.  * 这个是自己操大刀,用Graphics直接画出来,再保存 
  13.  *  
  14.  * 注:重构前,就此类+IioImageProvider的实现方式 
  15.  *  
  16.  * @author 梁飞 liangfei0201@163.com 
  17.  * 
  18.  */  
  19.   
  20. public class J2dPreviewGenerator implements PreviewGenerator {  
  21.       
  22.     private ImageProvider imageProvider;  
  23.       
  24.     public J2dPreviewGenerator(ImageProvider imageProvider) {  
  25.         this.imageProvider = imageProvider;  
  26.     }  
  27.   
  28.     public Dimension getSize(String source) throws IOException {  
  29.         BufferedImage image = imageProvider.readImage(source);  
  30.         return new Dimension(image.getWidth(), image.getHeight());  
  31.     }  
  32.   
  33.     public void generate(String source, String target, int width, int height) throws IOException {  
  34.         BufferedImage sourceImage = imageProvider.readImage(source);  
  35.         BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);  
  36.         Graphics2D g = null;  
  37.         try {  
  38.             g = (Graphics2D) image.createGraphics();  
  39.             g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);  
  40.             g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);  
  41.             // TODO hints待调整 ...  
  42.             g.setColor(Color.white);  
  43.             g.fillRect(00, width, height);  
  44.             g.drawImage(sourceImage, 00, width, height, null);  
  45.         } finally {  
  46.             if (g != null) {  
  47.                 g.dispose();  
  48.             }  
  49.         }  
  50.         imageProvider.saveImage(image, target);  
  51.     }  
  52.   
  53. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.Dimension;  
  4. import java.awt.RenderingHints;  
  5. import java.awt.geom.AffineTransform;  
  6. import java.awt.image.AffineTransformOp;  
  7. import java.awt.image.BufferedImage;  
  8. import java.io.IOException;  
  9.   
  10. /** 
  11.  *  
  12.  * 标准的Image处理的装饰器模式实现,感觉比直接操Graphic好些 
  13.  *  
  14.  * @author 梁飞 liangfei0201@163.com 
  15.  * 
  16.  */  
  17.   
  18. public class OpPreviewGenerator implements PreviewGenerator {  
  19.       
  20.     private ImageProvider imageProvider;  
  21.       
  22.     public OpPreviewGenerator(ImageProvider imageProvider) {  
  23.         this.imageProvider = imageProvider;  
  24.     }  
  25.   
  26.     public Dimension getSize(String source) throws IOException {  
  27.         BufferedImage image = imageProvider.readImage(source);  
  28.         return new Dimension(image.getWidth(), image.getHeight());  
  29.     }  
  30.   
  31.     public void generate(String source, String target, int width, int height) throws IOException {  
  32.         BufferedImage sourceImage = imageProvider.readImage(source);  
  33.         AffineTransform affineTransform = new AffineTransform();  
  34.         affineTransform.scale(width, height);  
  35.         RenderingHints hints = new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_DEFAULT);  
  36.         // TODO hints待调整 ...  
  37.         AffineTransformOp affineTransformOp = new AffineTransformOp(affineTransform, hints);  
  38.         BufferedImage image = new BufferedImage(width, height, sourceImage.getType());  
  39.         image = affineTransformOp.filter(sourceImage, image);  
  40.         imageProvider.saveImage(image, target);  
  41.     }  
  42.   
  43. }  


Java代码 复制代码
  1. package com.sanook.hompy.util.image.preview;  
  2.   
  3. import java.awt.Dimension;  
  4. import java.awt.image.renderable.ParameterBlock;  
  5. import java.awt.image.renderable.RenderableImage;  
  6. import java.io.File;  
  7. import java.io.FileOutputStream;  
  8. import java.io.IOException;  
  9.   
  10. import javax.media.jai.JAI;  
  11. import javax.media.jai.ParameterBlockJAI;  
  12. import javax.media.jai.PlanarImage;  
  13.   
  14. import com.sun.media.jai.codec.ImageCodec;  
  15. import com.sun.media.jai.codec.ImageEncoder;  
  16. import com.sun.media.jai.codec.JPEGEncodeParam;  
  17.   
  18. /** 
  19.  *  
  20.  * ImageIO的前身,但保持独立发展,比ImageIO绑定JDK,更新速度快多了 
  21.  *  
  22.  * @author 梁飞 liangfei0201@163.com 
  23.  * 
  24.  */  
  25.   
  26. public class JaiPreviewGenerator implements PreviewGenerator {  
  27.   
  28.     public Dimension getSize(String source) throws IOException {  
  29.         ParameterBlockJAI loadPB = new ParameterBlockJAI("fileload");  
  30.         loadPB.setParameter("filename", source);  
  31.   &nbs
分享到:
评论

相关推荐

    html5图片上传本地生成缩略图预览

    在图片预览和缩略图生成中,我们可以利用Canvas的drawImage方法将图片加载到Canvas上,然后通过调整Canvas的宽度和高度来生成缩略图。 3. **Data URL**:Data URL是一种内联资源表示方式,可以直接在页面中嵌入图像...

    C#实现图片个性化预览

    7. **性能优化**:在处理大量图片时,可能需要考虑缓存策略,例如将生成的缩略图保存到内存或磁盘,避免每次预览都重新生成。 8. **异常处理**:为了程序的健壮性,需要捕获可能出现的异常,比如文件不存在、权限...

    html5移动端图片上传本地生成缩略图预览(单图上传)

    预览图片后,我们可能还需要生成缩略图,以减小数据传输量或适应不同的展示尺寸。这里我们可以利用HTML5的Canvas元素。 1. 创建一个canvas元素,并获取其2D渲染上下文。 ```javascript var canvas = document....

    缩略图生成sample代码

    缓存策略可以用来减少重复工作,例如,当同一文件的缩略图已经生成过,可以存储在内存中以供后续使用。此外,还可以根据文件大小或复杂性来调整缩略图的生成质量,以平衡性能和视觉效果。 6. **错误处理和调试**: ...

    图形预览-图片自动预览程序

    在计算机系统中,图形预览是指在不打开文件的情况下,通过缩略图或小窗口显示文件内容的一种功能。这通常涉及到图像处理算法,如缩放、色彩管理和格式转换。为了实现这一功能,开发人员需要编写代码来读取不同类型的...

    .Net图片上传预览

    综上所述,实现.NET图片上传预览功能涉及前端图片的Base64编码预览、后端的文件接收和验证、异步处理、错误处理以及安全策略等多个方面。理解并熟练掌握这些知识点,能够帮助开发者构建稳定、安全且用户体验良好的...

    移动页面预览图片并生成截图示例

    在移动应用开发中,"移动页面预览图片并生成截图示例"是一个常见的需求,尤其在社交媒体、在线购物和图像编辑应用中。这个过程通常涉及以下几个关键知识点: 1. **图片选择**: 用户需要从本地设备选取图片,这可以...

    java 生成网页图片Web源代码

    9. **缓存策略**:为了提高性能,可以考虑在服务器端缓存生成的图片,避免重复计算。这可能涉及到使用内存缓存(如Guava Cache)或文件系统缓存。 10. **安全考虑**:当处理用户数据生成图片时,需要防止跨站脚本...

    截图缩略图生成源码2012417

    【截图缩略图生成源码2012417】是一个编程代码资源,主要功能是处理用户上传的图片,进行裁剪并生成缩略图,最终保存到本地供用户下载。这个源码适用于需要在网站或应用中实现快速、自动化生成图片缩略图的场景,...

    PoolImage 比赛showcase谱面预览生成器 (图片).zip

    PoolImage 比赛showcase谱面预览生成器是一个专为音乐节奏游戏设计的工具,主要用于生成比赛展示用的谱面预览图片。这个工具的源代码是比赛项目的一部分,旨在帮助参赛者或者赛事组织者高效、统一地制作高质量的谱面...

    【Unity地图生成插件】Map Graph 灵活的地图生成工具,快速生成各种类型的程序化地图

    文件名:Map Graph v1.25.unitypackage Map Graph 是一款为 Unity 开发的强大地图生成插件,...地形与地貌生成:支持复杂的地形生成,开发者可以通过高度图、噪声算法等生成逼真的自然环境,如山脉、河流、平原等。

    多文件预览上传-多图片预览上传

    - 文件命名策略和冲突处理是关键,通常通过生成唯一ID或使用时间戳避免重名问题。 4. **安全性考虑**: - 需要限制文件类型,防止恶意用户上传不安全或大体积的文件,可以通过检查文件扩展名或者MIME类型实现。 ...

    input file上传图片预览

    由于浏览器的安全策略,不能直接使用File对象的URL,所以我们需要创建一个`FileReader`来读取文件内容并生成一个可安全使用的URL。 ```javascript const reader = new FileReader(); reader.onload = function...

    图片生成缩略图片

    7. **性能优化**:为了提升服务响应速度,可以采用缓存策略,将生成的缩略图存储起来,下次请求相同图片时直接返回。还可以利用CDN(内容分发网络)加速图片的传输。 8. **响应式设计**:在移动设备上,缩略图的...

    jQuery带删除功能多图片上传预览插件

    2. **读取文件**:使用`FileReader` API逐个读取选中的图片文件,生成预览图。 3. **创建预览元素**:为每张图片创建一个包含预览图和删除按钮的DOM元素,并添加到预览容器中。 4. **删除操作**:为删除按钮绑定点击...

    asp.net图片预览

    1. 图片缩略图:如果需要生成缩略图,可以将用户上传的图片发送到ASP.NET服务器,使用GDI+或第三方库如ImageMagick生成缩略图,然后返回Base64编码的缩略图数据。 2. 图片质量控制:服务器端可以调整图片的质量和...

    上传图片并预览Demo

    此外,为了提供更好的用户体验,可以将图片转换为预览尺寸,如生成缩略图,这可以通过JavaScript库如`canvas`或`sharp`(Node.js环境)来实现。 2. **实时预览**:使用`FileReader`的`readAsDataURL()`方法,可以将...

    根据文件模板实现预览、生成word、pdf、excel(后端-项目)

    例如,工厂模式可用于创建文件处理对象,根据文件类型动态选择合适的生成或预览策略。单例模式可以用于确保文件服务类在整个应用中只有一个实例,避免资源浪费。观察者模式则可以用于文件变化监听,当模板文件更新时...

    公司联系方式地图生成器公司地址地图生成

    3. "HtmlView.fne" - 可能是用于显示地图代码或者预览生成的HTML嵌入代码的文件。 4. "krnln.fnr" - 这个文件名没有明确的指示,但它可能是程序运行所需的库文件或其他支持文件。 总结来说,这个工具软件为公司提供...

Global site tag (gtag.js) - Google Analytics