在Java中扩展图像的最佳方法是什么?

时间:2009-05-03 07:59:04

标签: java image web-applications graphics image-scaling

我有一个用Java编写的Web应用程序(Spring,Hibernate / JPA,Struts2),用户可以上传图像并将其存储在文件系统中。我想缩放这些图像,使它们具有一致的大小,以便在网站上显示。哪些库或内置函数将提供最佳结果?我将在做出决定时考虑以下标准(按此顺序):

  • 免费/开源(必备)
  • 易于实施
  • 结果质量
  • 性能
  • 可执行文件的大小

7 个答案:

答案 0 :(得分:9)

我真的建议你看一下imgscalr

它是在{2}上托管的Apache 2许可下发布的,已经部署在少数几个Web应用程序中,有一个非常简单,但是GitHub,代码可以解决2个主要图像如果你在规模操作后突然开始获得“黑色”图像或看起来很糟糕的结果,你会发现JDK中的错误,你可以通过Maven获得最好的Java结果作为一个ZIP,只是一个单独的类。

基本用法如下:

BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);

这是最简单的调用,其中库将对质量进行最佳猜测,尊重您的图像比例,并将结果放在320x320的边界框中。注意,边界框只是使用的最大W / H,因为您的图像比例很受尊重,因此产生的图像仍然可以尊重,例如320x200。

如果你想覆盖自动模式并强制它给你最好看的结果,甚至对结果应用一个非常温和的抗锯齿过滤器,这样它看起来更好(特别适合缩略图),看起来像:

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

这些都只是示例,API很广泛,涵盖了从超简单用例到非常专业的所有内容。您甚至可以传入自己的BufferedImageOps以应用于图像(并且库会自动修复6年的BufferedImageOp JDK错误!)

在Java中成功缩放图像以及图书馆为您所做的工作还有很多,例如,在操作图像时始终将图像保持为最佳支持的RGB或ARGB图像类型之一。如果用于任何图像操作的图像类型得不到支持,Java2D图像处理管道将落后于劣质软件管道。

如果这听起来很麻烦,那就是......这就是我编写图书馆并开源的原因,所以人们可以调整图像大小并继续生活,而不必担心它

希望有所帮助。

答案 1 :(得分:4)

查看Java Image I/O API来读取/写入图像。然后使用AffineTransform调整大小。

另外,here's是使用java.awt.Image的完整示例。

答案 2 :(得分:4)

同时查看java-image-scaling库。它为ImageIO创造了更高质量的图像。

答案 3 :(得分:1)

我知道这是一个非常古老的问题,但我使用标准Java API

获得了我自己的解决方案
chromium: [ERROR:web_contents_delegate.cc(199)] WebContentsDelegate::CheckMediaAccessPermission: Not supported.

我相信它可以改进和改编。

答案 4 :(得分:0)

图像编辑的最佳工具是ImageMagick,它是开源的。

Java语言有两个接口:

JMagick使用JNI接口到ImageMagick

im4java什么是ImageMagick的命令行界面

答案 5 :(得分:0)

我尝试使用imgscalr与标准Java 1.6相比,我不能说它更好。

我尝试的是

BufferedImage bufferedScaled = Scalr.resize(sourceImage, Method.QUALITY, 8000, height);

  Image scaled = sourceImage.getScaledInstance(-1, height, Image.SCALE_SMOOTH);
  BufferedImage bufferedScaled = new BufferedImage(scaled.getWidth(null),  scaled.getHeight(null), BufferedImage.TYPE_INT_RGB);
  bufferedScaled.getGraphics().drawImage(scaled, 0, 0, null);

我的眼睛进行了大约5分钟的测试,结果表明第二件事(纯Java 1.6)会产生更好的结果。

答案 6 :(得分:-1)

发现这更快:

public static BufferedImage getScaledInstance(final BufferedImage img, final int targetWidth, final int targetHeight,
                                              final Object hint) {
    final int type = BufferedImage.TYPE_INT_RGB;
    int drawHeight = targetHeight;
    int drawWidth = targetWidth;
    final int imageWidth = img.getWidth();
    final int imageHeight = img.getHeight();
    if ((imageWidth <= targetWidth) && (imageHeight <= targetHeight)) {
        logger.info("Image " + imageWidth + "/" + imageHeight + " within desired scale");
        return img;
    }
    final double sar = ((double) imageWidth) / ((double) imageHeight);
    if (sar != 0) {
        final double tar = ((double) targetWidth) / ((double) targetHeight);
        if ((Math.abs(tar - sar) > .001) && (tar != 0)) {
            final boolean isSoureWider = sar > (targetWidth / targetHeight);
            if (isSoureWider) {
                drawHeight = (int) (targetWidth / sar);
            }
            else {
                drawWidth = (int) (targetHeight * sar);
            }
        }
    }
    logger.info("Scaling image from " + imageWidth + "/" + imageHeight + " to " + drawWidth + "/" + drawHeight);
    final BufferedImage result = new BufferedImage(drawWidth, drawHeight, type);
    try {
        final Graphics2D g2 = result.createGraphics();
        try {
            if (hint != null) {
                g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
            }
            g2.drawImage(img, 0, 0, drawWidth, drawHeight, null);
        }
        finally {
            g2.dispose();
        }
        return result;
    }
    finally {
        result.flush();
    }
}