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编写的web应用程序(Spring、Hibernate/JPA、Struts2),用户可以在其中上传图像并将它们存储在文件系统中。我想要缩放这些图像,以便它们在站点上显示一致的大小。哪些函数库或内置函数将提供最好的结果?在作出决定时,我将考虑以下标准:
- Free/Open Source (essential)
- 免费/开源(重要)
- Easy to implement
- 容易实现
- Quality of results
- 质量的结果
- Performance
- 性能
- Size of executable
- 可执行文件的大小
7 个解决方案
#1
4
Have a look at the Java Image I/O API to read/write the image. Then use AffineTransform to resize.
查看Java映像I/O API来读取/写入映像。然后使用AffineTransform来调整大小。
Also, here's a complete example using java.awt.Image.
另外,这里有一个使用java.awt.Image的完整示例。
#2
9
I would really recommend giving imgscalr a 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透明,你只会发现如果你突然开始“黑色”图像在规模经营或可怕的结果,给你最好的结果可用在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传递到映像中(并且库会自动为您修复六年的BufferedImageOp JDK bug !)
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.
希望有帮助。
#3
4
Look into also to java-image-scaling library. It created better quality images that ImageIO.
还可以查看java-image- scale库。它创造了比ImageIO更高质量的图像。
#4
1
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.
我相信它是可以改进和适应的。
#5
0
The best tool for image editing is ImageMagick and it is open source.
图像编辑的最佳工具是ImageMagick,它是开源的。
There are two interfaces for the Java Language:
Java语言有两个接口:
JMagick which uses JNI interface to ImageMagick
JMagick使用JNI接口实现ImageMagick
and
和
im4java what is a command line interface for ImageMagick
什么是ImageMagick的命令行接口
#6
0
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)能产生更好的结果。
#7
-1
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();
}
}
#1
4
Have a look at the Java Image I/O API to read/write the image. Then use AffineTransform to resize.
查看Java映像I/O API来读取/写入映像。然后使用AffineTransform来调整大小。
Also, here's a complete example using java.awt.Image.
另外,这里有一个使用java.awt.Image的完整示例。
#2
9
I would really recommend giving imgscalr a 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透明,你只会发现如果你突然开始“黑色”图像在规模经营或可怕的结果,给你最好的结果可用在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传递到映像中(并且库会自动为您修复六年的BufferedImageOp JDK bug !)
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.
希望有帮助。
#3
4
Look into also to java-image-scaling library. It created better quality images that ImageIO.
还可以查看java-image- scale库。它创造了比ImageIO更高质量的图像。
#4
1
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.
我相信它是可以改进和适应的。
#5
0
The best tool for image editing is ImageMagick and it is open source.
图像编辑的最佳工具是ImageMagick,它是开源的。
There are two interfaces for the Java Language:
Java语言有两个接口:
JMagick which uses JNI interface to ImageMagick
JMagick使用JNI接口实现ImageMagick
and
和
im4java what is a command line interface for ImageMagick
什么是ImageMagick的命令行接口
#6
0
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)能产生更好的结果。
#7
-1
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();
}
}