PSET4:过滤器(少)

PSET4: Filter(less)

我正在尝试 Pset4 的过滤器问题(不太舒服)。我在下面写了这段代码来反映图像。但它根本不起作用。但是编译没问题。

// Reflect image horizontally
void reflect(int height, int width, RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++)  //for rows
    {
        int start = 0;
        for (int end = width; end > 0; end--)
        {
            BYTE tempR, tempB, tempG;
            if(start < end)
            {
                tempR = image[i][start].rgbtRed;
                tempB = image[i][start].rgbtBlue;
                tempG = image[i][start].rgbtGreen;
                image[i][start].rgbtRed = image[i][end].rgbtRed;
                image[i][start].rgbtBlue = image[i][end].rgbtBlue;
                image[i][start].rgbtGreen = image[i][end].rgbtGreen;
                image[i][end].rgbtRed = tempR;
                image[i][end].rgbtBlue = tempB;
                image[i][end].rgbtGreen = tempG;
                start += 1;
            }
        }
    }
    return;
}

在我看到评论之前,根据代码,这看起来像是“反转[光栅]线上所有像素的顺序”。

几个问题...

end 应该从 width - 1 开始 [并且 而不是 width]。它从行中最后一个像素 过去 处开始(即 下一个 行的第一个像素)。对于最后一行,这是 UB [未定义的行为]。

因此,效果是移动了一个像素,我敢打赌该行的第一个和最后一个像素看起来“很有趣”...

内部循环条件应该是start < end而不是end > 0,我们应该完全消除if (start < end)

除了正确性之外,这还将消除最后 50% 的内部循环。那些 不是 传输数据 [因为 if 会变成假,并且在该行的其余部分仍然如此]。因此,循环进行了两倍的循环迭代(即)只有第一次迭代做了有用的工作。

换句话说,内部 for 循环进行了 width 次迭代而不是 width / 2 次迭代。


这是清理和更正后的代码:

// Reflect image horizontally
void
reflect(int height, int width, RGBTRIPLE image[height][width])
{

    // for rows
    for (int i = 0; i < height; i++) {
        int start = 0;

        for (int end = width - 1;  start < end;  --end, ++start) {
            BYTE tempR, tempB, tempG;

            tempR = image[i][start].rgbtRed;
            tempB = image[i][start].rgbtBlue;
            tempG = image[i][start].rgbtGreen;

            image[i][start].rgbtRed = image[i][end].rgbtRed;
            image[i][start].rgbtBlue = image[i][end].rgbtBlue;
            image[i][start].rgbtGreen = image[i][end].rgbtGreen;

            image[i][end].rgbtRed = tempR;
            image[i][end].rgbtBlue = tempB;
            image[i][end].rgbtGreen = tempG;
        }
    }
}

虽然优化器可能从上面生成高效的代码,这里有一个版本,其中startend是指针。这样编译器更容易看出意图,也更简单易读:

// Reflect image horizontally
void
reflect(int height, int width, RGBTRIPLE image[height][width])
{

    // for rows
    for (int i = 0; i < height; i++) {
        RGBTRIPLE *start = &image[i][0];
        RGBTRIPLE *end = &image[i][width - 1];

        for (;  start < end;  --end, ++start) {
            BYTE tempR, tempB, tempG;

            tempR = start->rgbtRed;
            tempB = start->rgbtBlue;
            tempG = start->rgbtGreen;

            start->rgbtRed = end->rgbtRed;
            start->rgbtBlue = end->rgbtBlue;
            start->rgbtGreen = end->rgbtGreen;

            end->rgbtRed = tempR;
            end->rgbtBlue = tempB;
            end->rgbtGreen = tempG;
        }
    }
}