我编写了函数来反射(reflect) zip 文件中提供的 .bmps 图像。
经过一些研究,我发现很多解决这个问题的人都将图像的宽度除以2。但是,我觉得这不适用于我的代码。
该代码确实反射(reflect)了肉眼所见的图像,但它不符合 check50 提供的任何标准。
如果 width/2 确实是必要的,即使在我的代码中,请解释在我的代码实例中实现它背后的逻辑:
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE coloursofaddress[width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// Step 3
coloursofaddress[width - 1 - j].rgbtRed = image[i][j].rgbtRed;
coloursofaddress[width - 1 - j].rgbtGreen = image[i][j].rgbtGreen;
coloursofaddress[width - 1 - j].rgbtBlue = image[i][j].rgbtBlue;
// Step 4
image[i][j].rgbtRed = coloursofaddress[j].rgbtRed;
image[i][j].rgbtGreen = coloursofaddress[j].rgbtGreen;
image[i][j].rgbtBlue = coloursofaddress[j].rgbtBlue;
}
}
return;
}
以下是错误消息:
:( reflect correctly filters 1x2 image
expected "0 0 255\n255 0...", not "5 0 0\n255 0 0..."
:( reflect correctly filters 1x3 image
expected "0 0 255\n0 255...", not "5 0 0\n0 255 0..."
:( reflect correctly filters image that is its own mirror image
expected "255 0 0\n255 0...", not "5 0 0\n255 0 0..."
:( reflect correctly filters 3x3 image
expected "70 80 90\n40 5...", not "5 0 0\n40 50 6..."
:( reflect correctly filters 4x4 image
expected "100 110 120\n7...", not "5 0 0\n0 0 0\n..."
编辑: 通过进一步仔细检查上述代码输出的反射图像,一切似乎都很完美,除了带有随机颜色的细细附加行像素 - 不知道为什么。通过放大图片底部可以看到它,但在输入 .bmp 中不可见。
编辑2: 更仔细地检查反射图像输出后,底部的“杂散”像素线似乎正好在中间结束。看起来反射图像的整个左半部分比预期高了 1 个像素单位,而右半部分则很好。一条显示这种清晰高度划分的线依稀可见,沿着图片的中心向下延伸。这开始变得有趣了。
最佳答案
你有两个问题。
在步骤 4 中,一半的数组尚未赋值。您对第一行使用不确定的值,对其他行使用旧值。这看起来就像将图像的一半移动了 1 行。
您应该使用标准交换机制来交换值。 正如评论中提到的,您不需要费心处理单独的字段,而只需交换整个结构:
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE temp;
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
temp = image[i][j];
image[i][width - 1 - j] = image[i][j];
image[i][j] = temp;
}
}
return;
}
此外,如果您运行交换 0..width-1
的整个范围你最终会交换 image[i][0]
与 image[i][width-1]
及以后image[i][width-1]
与 image[i][0]
它将相同的像素交换两次,得到原始图像。
只需运行条件为 j < width/2
的循环:
// define a SWAP macro just for convenience during following explanation
#define SWAP(x,y) \
do { \
RGBTRIPLE temp = (x); \
(x) = (y); \
(y) = temp; \
} while (0)
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width/2; j++)
{
// Replace image[i] to make code shorter during explanation.
RGBTRIPLE *row=image[i];
SWAP(row[j], row[width - 1 - j]);
}
}
return;
}
我做了 2 个并非真正需要的替换,但使以下文本变得更短。
为什么只循环直到 j < width/2
?如果我们想要反转整数数组,让我们看看每次迭代中的内存:
width==15
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
j=0; SWAP(row[0],row[14]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|14| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
...
j=5; SWAP(row[5],row[9]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|14|13|12|11|10| 9| 6| 7| 8| 5| 4| 3| 2| 1| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
j=6; SWAP(row[6],row[8]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
j=7; SWAP(row[7],row[7]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
你可以看到,交换一半元素后,我们就完成了。对于奇数个元素,最后一次交换只会交换自身,没有任何效果。
如果您现在继续运行到 width
,你再次交换回来:
j=8; SWAP(row[8],row[6]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|14|13|12|11|10| 9| 6| 7| 8| 5| 4| 3| 2| 1| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
...
j=13; SWAP(row[13],row[1]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|14| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13| 0|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
j=14; SWAP(row[14],row[0]);
row: +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
这就是我们开始的地方。
很明显我们运行了SWAP(row[j],row[width-j-1]);
稍后与交换索引相同:SWAP(row[width-j-1],row[j]);
其作用相同。
交换两次会恢复初始状态,并且您的图像不会改变。
关于Cs50 的问题集 4 - 无滤波器 - 反射函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63461237/