待管理员删除的问题
您的代码中存在算法问题,渐变示例加剧了该问题,但在具有非常微妙渐变的图像中不太明显。
正如您所描述的,您的像素格式是BGR。因此,在图像的开头,输入如下所示:
R11 + 0: B0
R11 + 1: G0
R11 + 2: R0
R11 + 3: B1
R11 + 4: G1
R11 + 5: R1
R11 + 6: B2
R11 + 7: G2
R11 + 8: R2
要正确转换为灰度,您希望最终得到
RDI + 0: B0/3 + G0/3 + R0/3
RDI + 1: B0/3 + G0/3 + R0/3
RDI + 2: B0/3 + G0/3 + R0/3
RDI + 3: B1/3 + G1/3 + R1/3
RDI + 4: B1/3 + G1/3 + R1/3
RDI + 5: B1/3 + G1/3 + R1/3
RDI + 6: B2/3 + G2/3 + R2/3
RDI + 7: B2/3 + G2/3 + R2/3
RDI + 8: B2/3 + G2/3 + R2/3
这是你的算法一开始所做的事情:
pmovzxbd xmm0, [r11 + rax]
这会加载
xmm0
[B0, G0, R0, B1]。
pmovzxbd xmm1, [r11 + rax - 1]
这会加载
xmm1
[??, B0, G0, R0],其中 ??是数组开头之前的一个字节,且值未定义。我将继续假设该字节现在的值为 0。
paddd xmm0, xmm1
这会将
xmm0
设置为 [B0, G0 + B0, R0 + G0, B1 + R0]。
pmovzxbd xmm1, [r11 + rax + 1]
这会将
xmm1
设置为 [G0, R0, B1, G1]。
paddd xmm0, xmm1
这会将
xmm0
设置为 [B0 + G0, R0 + G0 + B0, R0 + G0 + B1, B1 + R0 + G1]。
然后将该向量转换为浮点数并除以 3,然后转换回整数。最后你这样做:
movups [rdi + rax], xmm0
将双字向量写入输出。但是...您的输出应该是字节位图,而不是双字位图!幸运的是,您的代码也被破坏了,因为它在下一次迭代中继续以 1 字节的偏移量继续,覆盖了您刚刚编写的所有内容,除了第一个字节(它恰好是第一个像素值的最低有效字节)。经过一系列迭代后,您最终会得到如下输出:
RDI + 0: B0/3 + G0/3
RDI + 1: B0/3 + G0/3 + R0/3
RDI + 2: G0/3 + R0/3 + B1/3
RDI + 3: R0/3 + B1/3 + G1/3
RDI + 4: B1/3 + G1/3 + R1/3
RDI + 5: G1/3 + R1/3 + B2/3
RDI + 6: R1/3 + B2/3 + G2/3
RDI + 7: B2/3 + G2/3 + R2/3
RDI + 8: G2/3 + R2/3 + B3/3
看看它是如何涂抹在像素上的,而不是每个像素的通道是该像素通道的平均值?这就是导致错误输出的原因。要修复代码,请重写它,使其实际上分别对每个像素的 B/G/R 求和,而不是执行您所拥有的那种运行总和。
实现这一点有点棘手。例如,您可以首先对像素进行解交织,这样您就有一个所有 B 的向量、一个所有 R 的向量和一个所有 G 的向量。如果有,您可以上转换为 16 位,求和,然后除以 3(我建议使用
vpmulhw
乘以 65536/3 = 21845,因为这比浮点运算更快)。最后交错存储。
确保不要过度读取输入或写入超过输出末尾!