在 Java 中缩放图像的最佳方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/816548/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the best way to scale images in Java?
提问by Peter Kelley
I have a web application written in Java (Spring, Hibernate/JPA, Struts2) where users can upload images and store them in the file system. I would like to scale those images so that they are of a consistent size for display on the site. What libraries or built in functions will offer the best results? I will consider the following criteria in making my decision (in this order):
我有一个用 Java(Spring、Hibernate/JPA、Struts2)编写的 Web 应用程序,用户可以在其中上传图像并将它们存储在文件系统中。我想缩放这些图像,以便它们在网站上显示的大小一致。哪些库或内置函数会提供最好的结果?我将在做出决定时考虑以下标准(按此顺序):
- Free/Open Source (essential)
- Easy to implement
- Quality of results
- Performance
- Size of executable
- 免费/开源(必不可少)
- 易于实施
- 结果质量
- 表现
- 可执行文件的大小
采纳答案by moinudin
Have a look at the Java Image I/O APIto read/write the image. Then use AffineTransformto resize.
查看Java Image I/O API来读/写图像。然后使用AffineTransform调整大小。
Also, here'sa complete example using java.awt.Image.
此外,这里有一个使用 java.awt.Image 的完整示例。
回答by Riyad Kalla
I would really recommend giving imgscalra look.
我真的建议给imgscalr看看。
It is released under an Apache 2 license, hosted on GitHub, been deployed in a handful of web applications already, has a very simple, but pedantically documented API, has code that works around 2 major image bugs in the JDK for you transparently that you'll only ever notice if you suddenly start getting "black" images after a scale operation or horrible-looking results, gives you the best possible looking results available in Java, is available via Maven as well as a ZIP and is just a single class.
它是在 Apache 2 许可下发布的,托管在GitHub 上,已经部署在少数 Web 应用程序中,具有非常简单但经过详细记录的 API,具有可以解决 JDK 中 2 个主要图像错误的代码'只会注意到,如果您在缩放操作或看起来很糟糕的结果后突然开始获得“黑色”图像,为您提供 Java 中可能的最佳外观效果,可通过 Maven 和 ZIP 获得,并且只是一个类.
Basic use looks like this:
基本用法如下所示:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);
This is the simplest call where the library will make a best-guess at the quality, honor your image proportions, and fit the result within a 320x320 bounding box. NOTE, the bounding box is just the maximum W/H used, since your image proportions are honored, the resulting image would still honor that, say 320x200.
这是最简单的调用,库将在其中对质量进行最佳猜测,尊重您的图像比例,并将结果放入 320x320 边界框内。注意,边界框只是使用的最大 W/H,因为您的图像比例受到尊重,生成的图像仍然会尊重该比例,例如 320x200。
If you want to override the automatic mode and force it to give you the best-looking result and even apply a very mild anti-alias filter to the result so it looks even better (especially good for thumbnails), that call would look like:
如果您想覆盖自动模式并强制它为您提供最佳效果,甚至对结果应用非常温和的抗锯齿过滤器,使其看起来更好(尤其适用于缩略图),该调用将如下所示:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, Method.QUALITY,
150, 100, Scalr.OP_ANTIALIAS);
These are all just examples, the API is broad and covers everything from super-simple use cases to very specialized. You can even pass in your own BufferedImageOps to be applied to the image (and the library automatically fixes the 6-year BufferedImageOp JDK bug for you!)
这些都只是示例,API 非常广泛,涵盖了从超级简单的用例到非常专业的所有内容。您甚至可以传入您自己的 BufferedImageOps 以应用于图像(并且该库会自动为您修复 6 年的 BufferedImageOp JDK 错误!)
There is a lot more to scaling images in Java successfully that the library does for you, for example always keeping the image in one of the best supported RGB or ARGB image types while operating on it. Under the covers the Java2D image processing pipeline falls back to an inferior software pipeline if the image type used for any image operations is poorly supported.
该库为您在 Java 中成功缩放图像还有很多其他功能,例如,在对图像进行操作时,始终将图像保持在最受支持的 RGB 或 ARGB 图像类型之一。如果用于任何图像操作的图像类型得不到很好的支持,Java2D 图像处理管道就会回退到劣质的软件管道。
If all that sounded like a lot of headache, it sort of is... that's why I wrote the library and open sourced it, so folks could just resize their images and move on with their lives without needing to worry about it.
如果这一切听起来很头疼,那是……这就是我编写库并将其开源的原因,这样人们就可以调整图像大小并继续他们的生活,而无需担心。
Hope that helps.
希望有帮助。
回答by Juha Syrj?l?
Look into also to java-image-scalinglibrary. It created better quality images that ImageIO.
还要查看java-image-scaling库。它创建了比 ImageIO 质量更好的图像。
回答by kajo
The best tool for image editing is ImageMagickand it is open source.
图像编辑的最佳工具是ImageMagick,它是开源的。
There are two interfaces for the Java Language:
Java 语言有两个接口:
JMagickwhich uses JNI interface to ImageMagick
JMagick使用 JNI 接口到 ImageMagick
and
和
im4javawhat is a command line interface for ImageMagick
im4java什么是 ImageMagick 的命令行界面
回答by eric
Found this to be faster:
发现这更快:
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();
}
}
回答by Vijay Kumar Kanta
I know this is a very old question, but I got my own solution for this using standard Java API
我知道这是一个非常古老的问题,但我使用标准 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));
I am sure it can be improved and adapted.
我相信它可以改进和适应。
回答by Mladen Adamovic
I tried imgscalr comparing to standard Java 1.6 and I cannot say it is better.
我尝试将 imgscalr 与标准 Java 1.6 进行比较,但我不能说它更好。
What I've tried is
我试过的是
BufferedImage bufferedScaled = Scalr.resize(sourceImage, Method.QUALITY, 8000, height);
and
和
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);
some 5 minute testing by my eye got impression that second thing (pure Java 1.6) produces better results.
我的眼睛进行了大约 5 分钟的测试,感觉第二件事(纯 Java 1.6)会产生更好的结果。

