【问题标题】:How to resize a BufferedImage in Java如何在 Java 中调整 BufferedImage 的大小
【发布时间】:2014-03-30 01:09:21
【问题描述】:

我正在寻找在 Java 中调整 BufferedImage 大小的最简单(并且仍然没有问题)的方法。

在某个问题的某个问题的回答中,用户 coobird 提出了以下解决方案,用他的话来说(我稍微改动了一点):

**

Graphics 对象具有绘制Image 的方法,同时还执行调整大小操作:

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();

这将采用originalImage 并将其绘制在newImage 上,宽度和高度为SMALL_SIZE

**

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

  • 如果我想将图像调整为 更大 尺寸,而不仅仅是更小的尺寸,它是否也可以工作(使用完全相同的代码)?

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

如果有更好的方法,请提出建议。

谢谢

【问题讨论】:

    标签: java bufferedimage


    【解决方案1】:

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

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

    【讨论】:

    • 为什么要放大图像使其模糊?放大 2,2 意味着将每个像素放大两倍,但保持相同的比例,对吗?如果是这样,那为什么会有问题?另外,是不是有一个内置的 Java 类来处理这个问题,而不是我必须想出一些算法来防止质量损失?
    • 示例:您有一个 8 像素的图像,4 个黑色像素,然后是 4 个白色像素。您将其放大 2.2:您最终将得到 8 个黑色圆饼,1 个灰色圆饼和 8 个白色圆饼。现有像素之间的新像素将计算为两个现有像素的平均值,这将降低两个区域之间的对比度(边缘)。 - 这不是通常的语言库试图解决的问题。
    • @Prog 您可以查看此问题以了解可能的开箱即用解决方案:stackoverflow.com/questions/7951290/…
    【解决方案2】:

    单步缩放的主要问题是它们通常不会产生高质量的输出,因为它们专注于获取原始图像并将其压缩到更小的空间中,通常通过丢弃大量像素信息(不同的算法做不同的事情,所以我在概括)

    drawGraphics 会扩大和缩小规模吗?是的,它会有效地做到这一点还是产生高质量的输出?这些将归结为实现,一般来说,默认使用的大多数缩放算法都专注于速度。您可以通过一些方式影响这些,但通常,除非您在小范围内进行缩放,否则质量通常会受到影响(根据我的经验)。

    您可以查看The Perils of Image.getScaledInstance(),了解有关该主题的更多详细信息和讨论。

    一般来说,一般建议要么使用专用库,例如​​ imgscalr,从我玩了十分钟的情况来看,它做得很好,要么执行阶梯式。

    阶梯式刻度基本上以 2 的幂向上或向下移动图像,直到达到所需的大小。请记住,按比例放大只不过是把一个像素放大一点,所以如果你放大到一个非常大的尺寸,质量将永远是一个问题。

    例如...

    请记住,任何缩放通常都是一项昂贵的操作(基于图像的原始大小和目标大小),因此通常最好尝试在绘制过程之外并尽可能在后台执行这些操作。

    还有一个问题,是否要保持图像的纵横比?根据您的示例,图像将以方形方式缩放(拉伸以满足目标尺寸的要求),这通常是不希望的。您可以将-1 传递给宽度或高度参数,底层算法将保持原始图像的纵横比,或者您可以简单地控制并做出更多决定,决定是否要将图像填充或适合目标区域,例如...

    一般来说,我大部分时间都避免使用drawImagegetScaledInstance(如果您的缩放范围仅在小范围内或想要进行低质量、快速的缩放,这些可以工作)并且更多地依赖于诸如适合/填充目标区域和阶梯式缩放。使用我自己的方法的原因简单归结为并不总是被允许使用外部库。很高兴不必在可以的地方重新发明轮子

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-18
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 2013-02-05
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      相关资源
      最近更新 更多