我需要在Java / Struts上传后调整图像大小。这该怎么做?

时间:2010-01-18 20:28:35

标签: java image struts resize

我们正在构建一个处理图片上传的应用程序。我希望用户能够以给定的大小上传图像,比如128x128,然后让服务器自动生成其他大小,例如64x64,57x57和25x25。

是否有图书馆可以帮助我解决这个问题?

编辑:我应该注意,调整大小只应在上传时进行。当在浏览器中呈现新的图像大小时,它应该从缓存的副本中拉出 - 而不是再次调整大小。换句话说,不应该只生成一次不同的尺寸,而不是每次请求图像。

5 个答案:

答案 0 :(得分:2)

This可能会有所帮助。 AFAIK,有多种方法可以做到这一点,具有不同的速度/图像质量。

答案 1 :(得分:2)

我已经使用ImageIO和ImageInfo库来实现类似的功能。到目前为止它们还算不错。

http://java.sun.com/javase/6/docs/api/javax/imageio/ImageIO.html

http://kickjava.com/src/imageinfo/ImageInfo.java.htm

我记得在获取图像大小时因本机java库存在一些性能问题,因此不得不使用ImageInfo。

希望这有帮助。

答案 2 :(得分:2)

乔希,

这正是我为imgscalr写的this app(Apache 2)所做的 - 到目前为止,从世界各地处理了几十万张图片并且没有报告损坏的结果。

当我第一次开始研究Java中的图像缩放(对于那个项目)时,我看到了你在这里搜索的内容...... 200个问题同样的问题,50个不同的方法,25个“错误”显然还有很多头痛。

我真的很喜欢解决这样的问题,所以我坐下来收集所有反馈,所有错误报告,所有提示,所有技巧以及人们遇到的所有问题,并将它们全部编译成超级简单,1-class API只为你做“一切正常”。

最简单的API用例如下所示:

BufferedImage scaledImg = Scalr.resize(img, 150);

但是考虑到你想要做一些非常小的不同尺寸,你需要使用QUALITY缩放方法,该方法采用Chris Campbell(Java2D团队)推荐的增量缩放技术并将预定义的ConvolveOp应用于缩小缩略图的结果因为它太小了。

示例:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY, 
                                       50, Scalr.OP_ANTIALIAS);

如果你不想要,你不需要同时提供w / h,图像的比例总是得到尊重,并且边界用作边界框以确保图像至少适合它(但永远不会违反图像的比例这样做。)

如果你曾经使用过ConvolveOps尝试软化图像,你就会知道找到合适的内核,它看起来很好但又足够柔软以摆脱锯齿,你知道这是一个皇家PIA - 我在图书馆中predefined的一个结果是与巴西社交网站合作一周的结果,该网站使用图书馆来扩展个人资料图片,我认为我们已将其钉在上面。

当然你可以用它作为一个起点并提供你自己的,Scalr类允许你传递任何BufferedImageOp,它将自动应用于生成的缩放图像(并且可以在6年内工作) -old导致图像损坏的JDK错误。)

该库还为您提供了一系列其他“最佳实践”内容,例如确保尽快刷新增量映像以保持内存使用率并且不会丢弃VM,始终保持最佳映像 - 支持的图像类型,因此Java2D中的软件管道从未使用过(如果您使用手动代码,人们上传GIF时可能已经注意到它,最终看起来像垃圾 - imgscalr修复此问题)以及其他一些适合的区域我对“只做一切正确”的图书馆的要求。

希望有所帮助。

答案 3 :(得分:0)

来自a related source in the Swing tutorial

/**
 * Resizes an image using a Graphics2D object backed by a BufferedImage.
 * @param srcImg - source image to scale
 * @param w - desired width
 * @param h - desired height
 * @return - the new resized image
 */
private Image getScaledImage(Image srcImg, int w, int h){
    BufferedImage resizedImg = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
    Graphics2D g2 = resizedImg.createGraphics();
    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
    g2.drawImage(srcImg, 0, 0, w, h, null);
    g2.dispose();
    return resizedImg;
}

答案 4 :(得分:0)

来自我们的一个java门户页面的实用程序功能 (从几个论坛的例子编码,我不声称是作者)

希望这有帮助 Guillaume PATRY

/**
 * Convenience method that returns a scaled instance of the
 * provided {@code BufferedImage}.
 *
 * @param img the original image to be scaled
 * @param targetWidth the desired width of the scaled instance,
 *    in pixels
 * @param targetHeight the desired height of the scaled instance,
 *    in pixels
 * @param hint one of the rendering hints that corresponds to
 *    {@code RenderingHints.KEY_INTERPOLATION} (e.g.
 *    {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
 *    {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
 *    {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
 * @param higherQuality if true, this method will use a multi-step
 *    scaling technique that provides higher quality than the usual
 *    one-step technique (only useful in downscaling cases, where
 *    {@code targetWidth} or {@code targetHeight} is
 *    smaller than the original dimensions, and generally only when
 *    the {@code BILINEAR} hint is specified)
 * @return a scaled version of the original {@code BufferedImage}
 */
 public BufferedImage getScaledInstance(
            BufferedImage img,
            int targetWidth,
            int targetHeight,
            Object hint,
            boolean higherQuality) {
BufferedImage ret = (BufferedImage) img;
int w, h;
if (higherQuality) {
    // Use multi-step technique: start with original size, then
    // scale down in multiple passes with drawImage()
    // until the target size is reached
    w = img.getWidth();
    h = img.getHeight();
} else {  
    // Use one-step technique: scale directly from original
    // size to target size with a single drawImage() call
    w = targetWidth;
    h = targetHeight;
}

do {
   if (higherQuality) {
      if (w > targetWidth) {
         w /= 2;
         if (w < targetWidth) {
            w = targetWidth;
         }
      } else {
         w = targetWidth;
      }
      if (h > targetHeight) {
         h /= 2;
         if (h < targetHeight) {
        h = targetHeight;
         }
      } else {
         h = targetHeight;
      }
   }
   BufferedImage tmp = null;
   if (img.getType() == 0) {
      tmp = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
   } else {
      tmp = new BufferedImage(w, h, img.getType());
   }
   Graphics2D g2 = tmp.createGraphics();
   g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
   g2.drawImage(ret, 0, 0, w, h, null);
   g2.dispose();
   ret = tmp;
} while (w != targetWidth || h != targetHeight);
return ret;

}