如何创建将缓冲图像旋转 90 度的反转?
How to create the inverse of rotating a buffered image 90 degrees?
我一辈子都弄不清楚这个函数是如何工作的,更不用说如何创建撤销了。我正在尝试编辑这个图像编辑程序,我需要为这个 rotate90 滤镜添加一个撤消功能。需要明确的是,我知道之前有人问过类似的问题,我已经看到大约 20 个相关的 Whosebug 问题,但我只是不理解它。
public static void apply(ColorImage image) {
int height = image.getHeight();
int width = image.getWidth();
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
Color pix = image.getPixel(x, y);
image.setPixel(height - y - 1, x, pix);
}
}
}
上面的代码假定将缓冲图像顺时针旋转 90 度。我将如何创建此函数的反函数?
要了解旋转功能的工作原理,请考虑字母 F 的图像,宽 3 像素,高 5 像素,并将其旋转 90°:
\ 0 1 2 \ 0 1 2 3 4
+------ +----------
0| * * * 0| * * * * *
1| * 1| * *
2| * * 2| *
3| *
4| *
您可以看到 (0,0) 处的 *
像素应映射到 (4,0 处的像素]) 在旋转后的图像中; (1,0) 处的像素映射到 (4,1) 处的像素;在 (2,0) 到 (4,2) 的像素,... (etc) ... 最后,在 ( 0,4) 映射到 (0,0)
第一个坐标(原始图像的 x
)映射到旋转图像的 y
坐标应该是显而易见的。 (我在上面加粗了这些值)。这应该可以解释为什么 x
值在 setPixel()
调用中显示为 y
坐标:
image.setPixel(???, x, pix);
将原始图像的y
坐标转换为旋转图像的x
坐标并不复杂。第 0 行成为最后一列,最后一行成为第零列。由于原始图像为 5 像素高,旋转后的图像变为 5 像素宽,最后一列为 height-1
。随着 y
向下增加原始图像,旋转图像的相应列减少,为旋转后的 x
列提供 height-1-y
。
image.setPixel(height - y - 1, x, pix);
两个问题:
1) 对于这张3×5像素的图像,(0,0)处的像素映射到(4,0),超出了image
的范围;在该坐标处设置像素的颜色应该会给你一个 IndexOutOfBoundsException
.
2) 如果图像是正方形的(从而避免了 IndexOutOfBoundsException
异常),您将在读取原始像素值之前用转换后的像素值覆盖原始图像的某些像素值。这会损坏您的图像。
以上两个问题都有一个简单的修复方法。创建并 return 一个新图像。
反转旋转
如果原始旋转将 (0,0) 处的像素移动到 (4,0),要反转旋转,您需要将 (4,0) 处的像素移动到 (0,0) .这可以通过两种方式完成:
- 稍微调整坐标变换,或者
- 从转换后的像素坐标读取并写入未转换的像素坐标。
留给学生练习。
我一辈子都弄不清楚这个函数是如何工作的,更不用说如何创建撤销了。我正在尝试编辑这个图像编辑程序,我需要为这个 rotate90 滤镜添加一个撤消功能。需要明确的是,我知道之前有人问过类似的问题,我已经看到大约 20 个相关的 Whosebug 问题,但我只是不理解它。
public static void apply(ColorImage image) {
int height = image.getHeight();
int width = image.getWidth();
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
Color pix = image.getPixel(x, y);
image.setPixel(height - y - 1, x, pix);
}
}
}
上面的代码假定将缓冲图像顺时针旋转 90 度。我将如何创建此函数的反函数?
要了解旋转功能的工作原理,请考虑字母 F 的图像,宽 3 像素,高 5 像素,并将其旋转 90°:
\ 0 1 2 \ 0 1 2 3 4
+------ +----------
0| * * * 0| * * * * *
1| * 1| * *
2| * * 2| *
3| *
4| *
您可以看到 (0,0) 处的 *
像素应映射到 (4,0 处的像素]) 在旋转后的图像中; (1,0) 处的像素映射到 (4,1) 处的像素;在 (2,0) 到 (4,2) 的像素,... (etc) ... 最后,在 ( 0,4) 映射到 (0,0)
第一个坐标(原始图像的 x
)映射到旋转图像的 y
坐标应该是显而易见的。 (我在上面加粗了这些值)。这应该可以解释为什么 x
值在 setPixel()
调用中显示为 y
坐标:
image.setPixel(???, x, pix);
将原始图像的y
坐标转换为旋转图像的x
坐标并不复杂。第 0 行成为最后一列,最后一行成为第零列。由于原始图像为 5 像素高,旋转后的图像变为 5 像素宽,最后一列为 height-1
。随着 y
向下增加原始图像,旋转图像的相应列减少,为旋转后的 x
列提供 height-1-y
。
image.setPixel(height - y - 1, x, pix);
两个问题:
1) 对于这张3×5像素的图像,(0,0)处的像素映射到(4,0),超出了image
的范围;在该坐标处设置像素的颜色应该会给你一个 IndexOutOfBoundsException
.
2) 如果图像是正方形的(从而避免了 IndexOutOfBoundsException
异常),您将在读取原始像素值之前用转换后的像素值覆盖原始图像的某些像素值。这会损坏您的图像。
以上两个问题都有一个简单的修复方法。创建并 return 一个新图像。
反转旋转
如果原始旋转将 (0,0) 处的像素移动到 (4,0),要反转旋转,您需要将 (4,0) 处的像素移动到 (0,0) .这可以通过两种方式完成:
- 稍微调整坐标变换,或者
- 从转换后的像素坐标读取并写入未转换的像素坐标。
留给学生练习。