Java中缩放缓冲图像

在本教程中,我们将介绍如何使用基本 Java API 重新缩放图像。我们将展示如何从文件加载图像和将图像保存到文件,并解释重新缩放过程的一些技术方面。

1、用Java加载图像
在本教程中,我们将使用一个简单的 JPG 图像文件。我们将使用与基本 Java SDK 捆绑在一起的ImageIO API 加载它。该 API 有一些预设的ImageReader,适用于 JPEG 和 PNG 等格式。ImageReaders知道如何读取各自的图像格式并从图像文件中获取位图。

我们将使用的方法是 来自 ImageIO 的读取方法。此方法有一些重载,但我们将使用最简单的一个:

BufferedImage srcImg = ImageIO.read(new File("src/main/resources/images/sampleImage.jpg"));

正如我们所看到的,read()方法提供了一个BufferedImage对象,它是图像位图的主要 Java 表示形式。

2.、重新缩放图像
在重新缩放加载的图像之前,我们必须做一些准备工作。

创建目标图像
首先,我们必须创建一个新的 BufferedImage对象,表示内存中缩放后的图像,也称为目标图像。由于我们要重新缩放,这意味着生成的图像将具有与原始图像不同的宽度和高度。

我们必须在新的 BufferedImage 中设置缩放尺寸:

float scaleW = 2.0f, scaleH = 2.0f;
int w = srcImg.getWidth() * (int) scaleW;
int h = srcImg.getHeight() * (int) scaleH;
BufferedImage dstImg = new BufferedImage(w, h, srcImg.getType());

如代码所示,宽度和高度的缩放因子不需要相同。然而,它们通常是这样的,因为使用不同的缩放因子会给我们带来扭曲的结果。
  • BufferedImage 构造函数还需要一个imageType参数。不要将其与图像文件格式(例如 PNG 或 JPEG)混淆; 图像类型决定了新 BufferedImage的颜色空间。该类本身为受支持的值提供静态 int成员,例如 分别针对彩色和灰度图像的BufferedImage.TYPE_INT_RGB和BufferedImage.TYPE_BYTE_GRAY 。在我们的例子中,我们将使用与源图像相同的类型,因为我们只是更改比例。

下一步是应用转换,将源图像调整为我们的目标大小。

应用AffineTransform
我们将通过应用缩放仿射变换来缩放图像。这些线性变换可以将点从一个 2D 平面映射到另一个 2D 平面。根据变换,目标平面可以是原始平面的放大甚至旋转版本。

在我们的例子中,我们将仅应用缩放。最简单的思考方法是获取构成图像的所有点,并通过缩放因子 来增加它们之间的距离。

让我们创建一个 AffineTransform及其各自的操作:

AffineTransform scalingTransform = new AffineTransform();
scalingTransform.scale(scaleW, scaleH);
AffineTransformOp scaleOp = new AffineTransformOp(scalingTransform, AffineTransformOp.TYPE_BILINEAR);

AffineTransform 定义我们将应用什么操作,而AffineTransformOp定义它的应用方式。我们创建一个使用 scalingTransform的操作,并使用双线性插值应用它。

所选择的插值算法是根据具体情况确定的,并指示如何选择新图像的像素值。这些插值算法的作用以及为什么它们是强制性的超出了本文的范围。理解它们需要知道我们为什么使用这些线性变换以及它们如何应用于 2D 图像。

一旦scaleOp准备好,我们就可以将其应用到 srcImg并将结果放入 dstImg中:

dstImg = scaleOp.filter(srcImg, dstImg);

最后,我们可以将 dstImg保存到文件中,以便我们可以查看结果:

ImageIO.write(dstImg, "jpg", new File("src/main/resources/images/resized.jpg"));