我有一個用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