代码之家  ›  专栏  ›  技术社区  ›  Joshua

我需要调整图像上传后在爪哇/ Struts。如何做到这一点?

  •  3
  • Joshua  · 技术社区  · 15 年前

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

    有图书馆能帮我吗?

    编辑:我应该注意,调整大小应该只在上传时进行。在浏览器中呈现新的图像大小时,应该从缓存的副本中提取图像大小,而不是重新进行大小调整。换言之,不同的大小应该只生成一次,而不是每次请求图像时。

    5 回复  |  直到 13 年前
        1
  •  2
  •   Bozho    15 年前

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

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

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

    我记得在获取图像大小并因此必须使用IMAGE信息时,使用原生Java库有一些性能问题。

    希望这有帮助。

        2
  •  2
  •   jsn    15 年前

    This 可能会有所帮助。对于Afaik,有多种方法可以做到这一点,速度/图像质量各不相同。

        3
  •  2
  •   georgeawg    14 年前

    Josh

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

    当我第一次开始研究Java中的图像缩放时,我看到了你在这里搜索到的东西…200个问题问同一件事,50个不同的方法,其中25个显然是“错的”,而且很头疼。

    我真的很喜欢解决这样的问题,所以我坐下来收集所有的反馈、所有的bug报告、所有的提示、所有的技巧和人们遇到的所有问题,并将它们汇编成一个超级简单的, 1-class API 这对你来说“一切都很好”。

    最简单的API用例如下:

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

    但是考虑到你想要做一些非常小的不同的尺寸,你需要使用克里斯坎贝尔(Java2d团队)推荐的增量缩放技术的质量缩放方法,并将预先定义的卷积应用到结果中,以稍微软化缩略图,因为它太小了。

    例子:

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

    如果您不想,您不需要同时提供w/h,图像的比例始终保持不变,边界用作边界框,以确保图像至少适合它(但不会违反图像的比例)。

    如果你曾经用卷积的方法来尝试软化图像,你知道找到合适的内核,它足够锋利,看起来很好,但足够柔软,可以去掉锯齿,你知道这是一个皇家的皮娅——我有一个 predefined 图书馆是与巴西的一个社交网站合作一周的结果,该网站利用图书馆来缩放个人资料图片,我认为我们把它定位了。

    当然,您可以将它作为一个起点并提供自己的scaler类,它允许您传递任何BufferedImageOp,它将自动应用于生成的缩放图像(并解决导致图像损坏的6岁JDK错误)。

    这个库还为您做了许多其他“最佳实践”的事情,比如确保尽快刷新增量图像以减少内存使用,而不是丢弃虚拟机,始终将图像保存在支持的最佳图像类型中,这样就永远不会使用Java2d中的软件管道(当人们上载GI时,您可能已经注意到了这一点)。fs如果您使用的是手工代码,那么最终看起来像垃圾——imgscalr修复了这个问题),以及其他一些符合我对“一切都做对了”库的要求的细节。

    希望有帮助。

        4
  •  0
  •   Eli Acherkan    15 年前

    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;
    }
    
        5
  •  0
  •   PATRY Guillaume    15 年前

    从我们的Java门户页面之一的实用功能 (从几个论坛的示例中编码,我不声称是作者)

    希望这有帮助
    纪尧姆帕特里

    /**
     * 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;
    

    }