如何在Java中调整BufferedImage的大小

3
我正在寻找在Java中最简单(且无问题)的方式来调整 BufferedImage 的大小。
在对一个问题的回答中,用户 coobird 建议了以下解决方案,他的话(经过我稍微更改)如下:
**
Graphics 对象有一种方法可以绘制图像并执行调整大小操作:
Graphics.drawImage(Image, int, int, int, int, ImageObserver) 方法可用于在绘制时指定图像的位置和大小。
因此,我们可以使用类似这样的代码:
BufferedImage originalImage = // .. created somehow
BufferedImage newImage = new BufferedImage(SMALL_SIZE, SMALL_SIZE, BufferedImage.TYPE_INT_RGB);

Graphics g = newImage.createGraphics();
g.drawImage(originalImage, 0, 0, SMALL_SIZE, SMALL_SIZE, null);
g.dispose();

这将使用SMALL_SIZE的宽度和高度,将originalImage绘制到newImage上。

**

这个解决方案看起来相当简单。我有两个问题:

  • 如果我想将图像调整为更大的大小,是否也可以使用完全相同的代码运行?

  • 这个解决方案有什么问题吗?

如果有更好的方法,请建议一下。

谢谢

2个回答

4
单步缩放的主要问题是它们通常不会产生质量输出,因为它们专注于将原始图像压缩到较小的空间中,通常通过丢弃大量像素信息来实现(不同的算法做不同的事情,所以我是笼统地说)。
drawGraphics可以进行缩放,但其效率或输出质量如何取决于实现方式。一般而言,默认使用的大多数缩放算法都侧重于速度。您可以在某种程度上影响这些算法,但通常除非您对小范围进行缩放,否则质量通常会受到影响(根据我的经验)。
您可以查看Image.getScaledInstance()的危险以获取有关该主题的更多详细信息和讨论。
通常建议的是要么使用专用库(例如imgscalr),十分钟内我玩过它,做得很好,要么执行阶段性缩放。
一种阶梯式比例尺基本上是通过2的幂将图像放大或缩小,直到达到所需大小。请记住,放大就是将像素稍微放大一点,因此如果将其放大到非常大的尺寸,则质量始终会成为一个问题。
例如...
- 调整大小后图像质量非常低--Java - 自动将ImageIcon缩放到标签大小 - Java:JPanel背景不缩放 请记住,任何缩放通常都是昂贵的操作(基于图像的原始大小和目标大小),因此通常最好尝试在可能的情况下在后台进行这些操作,而不是在绘制过程之外。
还有一个问题,您是否想保持图像的长宽比?根据您的示例,图像将以正方形方式缩放(拉伸以满足目标大小的要求),这通常是不希望发生的。您可以向宽度或高度参数传递-1,底层算法将保持原始图像的长宽比,或者您可以简单地控制并更多地确定是否要填充或适应目标区域的图像,例如...

一般来说,我大部分时间都避免使用drawImagegetScaledInstance(如果您的缩放范围很小或者想要进行低质量、快速的缩放,这些方法可以工作),而是更依赖于适应/填充目标区域和分步缩放等方法。使用自己的方法的原因仅仅是因为并不总是允许使用外部库。能够不重复造轮子就好了。


1

如果您设置参数,它将放大原始图像。但是:您应该使用一些智能算法来保留边缘,因为简单地放大图像会使其变得模糊,并导致更差的感知质量。

没有问题。理论上,在某些平台上甚至可以进行硬件加速。


为什么放大图像会变得模糊?放大2倍意味着每个像素扩大两倍,但保持相同的比例,对吗?如果是这样,那为什么会有问题?此外,难道没有内置的Java类来处理这个问题,而不是我必须想出一些算法来防止失去质量吗? - Aviv Cohn
你手头有一个8像素的图像,其中4个黑色像素后跟着4个白色像素。你把它放大了2.2倍:最终结果是8个黑色像素、一个灰色像素和8个白色像素。新的像素将被计算为两个现有像素的平均值,这将减少你两个区域之间的对比度(边缘)。这不是通常语言库尝试解决的问题。 - vbence
@Prog 你可以查看这个问题,寻找可能的开箱即用解决方案:https://dev59.com/Cmsz5IYBdhLWcg3wWmjL?rq=1 - vbence

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接