我试图在java中调整内存中的bufferedImage,但要保持图像的宽高比 我有类似的东西,但这不是很好
int w = picture.getWidth();
int h = picture.getWidth();
int neww=w;
int newh=h;
int wfactor = w;
int hfactor = h;
if(w > DEFULT_PICTURE_WIDTH || h > DEFULT_PICTURE_HIGHT)
{
while(neww > DEFULT_PICTURE_WIDTH)
{
neww = wfactor /2;
newh = hfactor /2;
wfactor = neww;
hfactor = newh;
}
}
picture = Utils.resizePicture(picture,neww,newh);
答案 0 :(得分:68)
添加到Erik关于getScaledInstance的观点,如果你离开它去使用Java2D中推荐的缩放机制,你可能已经注意到你的图像看起来明显更糟。
原因是当Java2D不鼓励使用getScaledInstance和AreaAveragingScaleFilter时,他们没有用在API中使用的任何 替换它,而是使用我们自己的设备直接使用Java2D API。幸运的是,Chris Campbell(来自J2D团队)继续推荐使用增量缩放技术,该技术可为AreaAveragingScaleFilter提供类似的结果,并且运行速度更快;不幸的是,代码的大小合适,并没有解决你原来的尊重比例的问题。
大约6个月前,我一次又一次地看到关于“用Java缩放图像”的所有这些问题并最终收集了所有的建议,做了我能做的所有挖掘和研究,并将所有这些问题汇编成一个单一的“最佳实践” “image scaling library。
API很简单,因为它只有一个类和一堆静态方法。基本用法如下:
BufferedImage img = ImageIO.read(...); // load image
BufferedImage scaledImg = Scalr.resize(img, 320);
这是simplest call,其中图书馆将对质量进行最佳猜测,尊重您的图像比例,并将结果放在320x320的边框内。注意,边界框只是使用的最大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错误!)
在Java中成功缩放图像以及图书馆为您所做的工作还有很多,例如,在操作图像时始终将图像保持为最佳支持的RGB或ARGB图像类型之一。如果用于任何图像操作的图像类型得不到支持,Java2D图像处理管道将落后于劣质软件管道。
如果这听起来很麻烦,那就是......这就是我编写图书馆并开源的原因,所以人们可以调整图像大小并继续生活,而不必担心它
希望有所帮助。
答案 1 :(得分:8)
对于初学者 - 请看第2行。不应该是getHeight()
?
你不想要调整大小的while循环,你想要找出调整大小比例,这是一个简单的数学运算。
(width / height) = (new_width / new_height)
如果你知道其中一个'新'尺寸,另一个可以通过乘法找到
new_height * (width / height) = new_width
您还可以使用BufferedImage's
超类图像getScaledInstance()
提供的惰性方法 - 使用-1表示宽度或高度将保持宽高比
例如:
scaledPic = picture.getScaledInstance(new_width, -1, Image.SCALE_FAST);
答案 2 :(得分:8)
如果已知源和目标的宽度,高度,请使用以下函数确定图像的比例。
private double determineImageScale(int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) {
double scalex = (double) targetWidth / sourceWidth;
double scaley = (double) targetHeight / sourceHeight;
return Math.min(scalex, scaley);
}
然后使用此比例使用以下代码放大/缩小图像
Image scaledImage = sourceBufferedImage.getScaledInstance((int) (width * scale), (int) (height * scale), Image.SCALE_SMOOTH);
答案 3 :(得分:6)
您可以查看perils-of-image-getscaledinstance.html,了解为什么应避免在某些答案中使用getScaledInstance()
。
该文章还提供了替代代码。
答案 4 :(得分:3)
我使用这两种方法来缩放图像,其中max是目标图像的较大尺寸。对于100x100图像,它将是100,对于200x300图像,它将是300。
public static BufferedImage scale(InputStream is, int max) {
Image image = null;
try {
image = ImageIO.read(is);
} catch (IOException e) {
e.printStackTrace();
}
int width = image.getWidth(null);
int height = image.getHeight(null);
double dWidth = 0;
double dHeight = 0;
if (width == height) {
dWidth = max;
dHeight = max;
}
else if (width > height) {
dWidth = max;
dHeight = ((double) height / (double) width) * max;
}
else {
dHeight = max;
dWidth = ((double) width / (double) height) * max;
}
image = image.getScaledInstance((int) dWidth, (int) dHeight, Image.SCALE_SMOOTH);
BufferedImage bImage = toBufferedImage(image);
return bImage;
}
public static BufferedImage toBufferedImage(Image img)
{
if (img instanceof BufferedImage)
{
return (BufferedImage) img;
}
BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics2D bGr = bimage.createGraphics();
bGr.drawImage(img, 0, 0, null);
bGr.dispose();
return bimage;
}
答案 5 :(得分:0)
如果要通过保持纵横比来调整w0 x h0到w1 x h1的图片大小,请计算垂直和水平刻度并选择较小的刻度。
double scalex = 1;
double scaley = 1;
if (scalingMode == ScalingMode.WINDOW_SIZE) {
scalex = (double)getWidth() / frontbuffer.getWidth();
scaley = (double)getHeight() / frontbuffer.getHeight();
} else
if (scalingMode == ScalingMode.KEEP_ASPECT) {
double sx = (double)getWidth() / frontbuffer.getWidth();
double sy = (double)getHeight() / frontbuffer.getHeight();
scalex = Math.min(sx, sy);
scaley = scalex;
// center the image
g2.translate((getWidth() - (frontbuffer.getWidth() * scalex)) / 2,
(getHeight() - (frontbuffer.getHeight() * scaley)) / 2);
}
g2.scale(scalex, scaley);
if (interpolation != ImageInterpolation.NONE) {
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, interpolation.hint);
}
g2.drawImage(frontbuffer, 0, 0, null);
答案 6 :(得分:0)
private static BufferedImage resize(BufferedImage img, int width, int height) {
double scalex = (double) width / img.getWidth();
double scaley = (double) height / img.getHeight();
double scale = Math.min(scalex, scaley);
int w = (int) (img.getWidth() * scale);
int h = (int) (img.getHeight() * scale);
Image tmp = img.getScaledInstance(w, h, Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(w, h, img.getType());
Graphics2D g2d = resized.createGraphics();
g2d.drawImage(tmp, 0, 0, null);
g2d.dispose();
return resized;
}