待删除

问题描述 投票:0回答:1

待管理员删除的问题

grayscale
1个回答
4
投票

您的代码中存在算法问题,渐变示例加剧了该问题,但在具有非常微妙渐变的图像中不太明显。

正如您所描述的,您的像素格式是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,因为这比浮点运算更快)。最后交错存储。

确保不要过度读取输入或写入超过输出末尾!

© www.soinside.com 2019 - 2024. All rights reserved.