在Java中缩放图像的最佳方法是什么?

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

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

查看Java Image I / O API以读取/写入映像。 然后使用AffineTransformresize。

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

我真的建议给imgscalr看看。

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

基本用法如下:

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

这是最简单的调用,其中库将对质量进行最佳猜测,尊重您的图像比例,并将结果拟合到320×320的边界框中。 注意,边界框只是所使用的最大W / H,因为您的图像比例得到尊重,所得到的图像仍然会尊重,例如320×200。

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

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

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

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

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

希望有所帮助。

另请参阅java-image-scaling库。 它为ImageIO创造了更高质量的图像。

我知道这是一个非常古老的问题,但我使用标准Java API获得了自己的解决方案

 import java.awt.*; import java.awt.event.*; import javax.imageio.* import java.awt.image.*; BufferedImage im, bi, bi2; Graphics2D gfx; int imWidth, imHeight, dstWidth, dstHeight; int DESIRED_WIDTH = 500, DESIRED_HEIGHT = 500; im = ImageIO.read(new File(filePath)); imWidth = im.getWidth(null); imHeight = im.getHeight(null); dstWidth = DESIRED_WIDTH; dstHeight = (dstWidth * imHeight) / imWidth; bi = new BufferedImage(dstWidth, dstHeight, im.getType()); gfx = bi.createGraphics(); gfx.drawImage(im, 0, 0, dstWidth, dstHeight, 0, 0, imWidth, imHeight, null); bi2 = new BufferedImage(DESIRED_WIDTH, DESIRED_HEIGHT, im.getType()); gfx = bi2.createGraphics(); gfx.drawImage(bi, 0, 0, DESIRED_WIDTH, DESIRED_HEIGHT, null); ImageIO.write(bi2, "jpg", new File(filePath)); 

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

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

Java语言有两个接口:

JMagick使用JNI接口到ImageMagick

im4java什么是ImageMagick的命令行界面

我试过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)产生了更好的效果。

发现这更快:

 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(); } }