这是我正在使用的代码。当我运行它时,它似乎不会改变图像中的任何东西,除了它的最后1/4。那部分变成了纯色。
void maxFilter(pixel * data, int w, int h)
{
GLubyte tempRed;
GLubyte tempGreen;
GLubyte tempBlue;
int i;
int j;
int k;
int pnum = 0;
int pnumWrite = 0;
for(i = 0 ; i < (h - 2); i+=3) {
for(j = 0 ; j < (w - 2); j+=3) {
tempRed = 0;
tempGreen = 0;
tempBlue = 0;
for (k = 0 ; k < 3 ; k++){
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
if ((data[pnum].g) > tempGreen){tempGreen = (data[pnum + k].g);}
if ((data[pnum].b) > tempBlue){tempBlue = (data[pnum + k].b);}
if ((data[(pnum + w)].r) > tempRed){tempRed = (data[(pnum + w)].r);}
if ((data[(pnum + w)].g) > tempGreen){tempGreen = (data[(pnum + w)].g);}
if ((data[(pnum + w)].b) > tempBlue){tempBlue = (data[(pnum + w)].b);}
if ((data[(pnum + 2 * w)].r) > tempRed){tempRed = (data[(pnum + 2 * w)].r);}
if ((data[(pnum + 2 * w)].g) > tempGreen){tempGreen = (data[(pnum + 2 * w)].g);}
if ((data[(pnum + 2 * w)].b) > tempBlue){tempBlue = (data[(pnum + 2 * w)].b);}
pnum++;
}
pnumWrite = pnum - 3;
for (k = 0 ; k < 3 ; k++){
((data[pnumWrite].r) = tempRed);
((data[pnumWrite].g) = tempGreen);
((data[pnumWrite].b) = tempBlue);
((data[(pnumWrite + w)].r) = tempRed);
((data[(pnumWrite + w)].g) = tempGreen);
((data[(pnumWrite + w)].b) = tempBlue);
((data[(pnumWrite + 2 * w)].r) = tempRed);
((data[(pnumWrite + 2 * w)].g) = tempGreen);
((data[(pnumWrite + 2 * w)].b) = tempBlue);
pnumWrite++;
}
}
}
}
我可以看到该代码有几个问题——很难理解,一点也不!
我认为您的主要问题是循环(正如您可能想要的那样)运行h/3 * w/3
次,对于图像中的每个3x3块运行一次。但是,对于每个块,pnum
索引运行仅增加3
,并且达到大约h*w/3
的最大值,而不是预期的h*w
。这意味着只有图像的前三分之一会受到过滤器的影响。(我怀疑你的画是"自下而上"完成的,所以这就是为什么你会看到最低部分的变化。我记得.bmp文件的结构是这样的,但也许还有其他的。)
"廉价"的解决方案是在正确的位置添加2*w
,但没有人会再理解那个代码。我建议您重写索引,并在循环的每个循环中从i
和j
显式计算pnum
。为了可读性,这一点可以改进,但相当清晰。
还有一件小事:你有类似的代码
if ((data[pnum].r) > tempRed){tempRed = (data[pnum + k].r);}
右边和左边的索引不同:这可能也会给你带来与预期不同的结果。
正如Jongware所指出的,写入输入数组总是很危险的——我相信,你的代码是为了避免这个问题,只对每个3x3块进行一次检查,但他关于单独输出数组的建议是非常明智的——你可能无论如何都不想要你的代码所带来的块状(你让每个3x3区块都是一种颜色,不是吗?),他的建议会让你避免这种情况。