CS50 pset4 - 过滤器(不太舒服),棕褐色功能

CS50 pset4 - filter (less comfortable), sepia function

我为过滤器 pset 的棕褐色功能编写了代码。代码编译没有任何错误,但输出图像不完全是棕褐色。但是,在我以不同的方式编写代码后,它工作正常。有人可以解释为什么会这样吗?

第一个代码:

void sepia(int height, int width, RGBTRIPLE image[height][width])
{

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            RGBTRIPLE pixel={0,0,0};
            RGBTRIPLE pix = image[i][j];

            pixel.rgbtBlue = round(0.272 * pix.rgbtRed + 0.534 * pix.rgbtGreen + 0.131 * pix.rgbtBlue);
            pixel.rgbtGreen = round(0.349 * pix.rgbtRed + 0.686 * pix.rgbtGreen + 0.168 * pix.rgbtBlue);
            pixel.rgbtRed = round(0.393 * pix.rgbtRed + 0.769 * pix.rgbtGreen + 0.189 * pix.rgbtBlue);

            if(pixel.rgbtBlue > 255)
            {
                pixel.rgbtBlue = 255;
            }
             if(pixel.rgbtGreen > 255)
            {
                pixel.rgbtGreen = 255;
            }

             if(pixel.rgbtRed > 255)
            {
                pixel.rgbtRed = 255;
            }

            image[i][j] = pixel;

        }
    }
    return;
}

第一个代码输出图像:

第二个代码:

void sepia(int height, int width, RGBTRIPLE image[height][width])
{

    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            int red = image[i][j].rgbtRed;
            int green = image[i][j].rgbtGreen;
            int blue = image[i][j].rgbtBlue;

            //calculate sepia values
            int sepiaRed = round(.393 * red + .769 * green + .189 * blue);
            if(sepiaRed > 255)
            {
                sepiaRed = 255;
            }

            int sepiaGreen = round(.349 * red + .686 * green + .168 * blue);
            if(sepiaGreen > 255)
            {
                sepiaGreen = 255;
            }

            int sepiaBlue = round(.272 * red + .534 * green + .131 * blue);
            if(sepiaBlue > 255)
            {
                sepiaBlue = 255;
            }

            image[i][j].rgbtRed  = sepiaRed;
            image[i][j].rgbtGreen = sepiaGreen;
            image[i][j].rgbtBlue = sepiaBlue;


        }
    }
    return;
}

第二次代码输出:

两个版本的区别在于计算新像素值的类型

在第一个版本中,类型是 RGBTRIPLE 的组成成员 - 我假设它是一个无符号的 8 位整数。

 pixel.rgbtBlue = round(0.272 * pix.rgbtRed + 0.534 * pix.rgbtGreen + 0.131 * pix.rgbtBlue);

在这一行(以及绿色和红色像素的等效项)中, 该值可以超过 255,然后在分配给 pixel.rgbtBlue.

时通过分配给 8 位无符号整数来截断该值

以下钳位饱和:

    if(pixel.rgbtBlue > 255)
    {
        pixel.rgbtBlue = 255;
    }

将始终执行 false,因为 pixel.rgbtBlue 不能容纳大于 255 的值。

在代码的第二个版本中,使用了更大的 int,并且不会发生截断,从而使 clamp-to-255 能够正常工作。

正如上面的人已经评论的那样,第一个在 if 条件中有一个被截断的值,因为 avarage 操作导致一个大于 255 的数字...这就是过滤器不能正常工作的原因。 我会考虑在第二个上少用“if/else”,也许使用“Ternary Operator”以获得更清晰的代码:

        image[i][j].rgbtGreen = (sepiaGreen > 255) ? 255 : sepiaGreen;
        image[i][j].rgbtRed = (sepiaRed > 255) ? 255 : sepiaRed;
        image[i][j].rgbtBlue = (sepiaBlue > 255) ? 255 : sepiaBlue;