我有一个用Java编写的Web应用程序(Spring,Hibernate/JPA,Struts2),用户可以上传图像并将它们存储在文件系统中。我想缩放这些图片,以便它们在网站上显示的尺寸一致。哪些库或内置函数将提供最佳结果?我会考虑做出我的决定下列标准(顺序):在Java中缩放图像的最佳方式是什么?
- 自由/开源(必需)
- 容易实现的结果
- 质量
- 性能
- 的大小可执行文件
我有一个用Java编写的Web应用程序(Spring,Hibernate/JPA,Struts2),用户可以上传图像并将它们存储在文件系统中。我想缩放这些图片,以便它们在网站上显示的尺寸一致。哪些库或内置函数将提供最佳结果?我会考虑做出我的决定下列标准(顺序):在Java中缩放图像的最佳方式是什么?
看看Java Image I/O API来读取/写入图像。然后使用AffineTransform来调整大小。
另外,here's使用java.awt.Image的完整示例。
也看看java-image-scaling库。它创造了更好的图像质量ImageIO。
图像编辑的最佳工具是ImageMagick它是开源的。
有两个接口为Java语言:
JMagick它使用JNI接口ImageMagick的
和
im4java什么是ImageMagick的
一个命令行界面我真的建议给imgscalr一看。
它是在Apache 2许可下发布,托管在GitHub,被部署在Web应用程序已经屈指可数,有一个非常简单的,但是pedantically documented API,有一个透明的工作解决2个主要的图像错误在JDK为你的代码你只会注意到,如果你突然开始在缩放操作或可怕的结果后得到“黑色”图像,给你最好的可用Java结果的结果,可以通过Maven以及ZIP获得,并且只是一个单班。
基本使用方法如下:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);
这就是图书馆将成为在质量最好的猜测,孝敬您的图像比例,以及320×320边框内符合结果的最简单的调用。注意,边界框只是使用的最大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 bug!)
还有很多东西在Java中成功缩放图像例如,对于您来说,始终将图像保存为支持最佳的RGB或ARGB图像类型之一。如果用于任何图像操作的图像类型得不到支持,则Java2D图像处理管道将回退到较差的软件管道。
如果听起来像很多令人头疼的事情,那就是......这就是为什么我编写图书馆并开放源代码的原因,所以人们可以调整他们的图像大小并继续他们的生活而不必担心它。
希望有所帮助。
我试过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();
}
}
我知道这是一个非常古老的问题,但我有我自己的这个使用标准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));
我相信它可以改进和适应。
您引用的示例使用`getScaledInstance()`,而不是AffineTransform。那它是哪一个?我读过“getScaledInstance”的混合评论不是性能... – gdbj 2017-04-17 14:51:43