Cs50 棕褐色将图像从正常转换为棕褐色的问题

标签 c filter cs50

我正在开发一个名为 filter 的 cs50 程序(不太舒服,第 4 周),它必须将图像从正常图像转换为棕褐色图像。除非必须将颜色转换为白色,否则它工作正常。当尝试传输白色时,它只是将其转换为蓝色和绿色。就像这样:

原版

ORIGINAL

棕褐色

enter image description here

正如您所看到的,除了白色或接近白色的颜色之外,它可以很好地转换所有内容。 这是我的代码(仅限棕褐色部分):


void sepia(int height, int width, RGBTRIPLE image[height][width])
{
    for(int j = 0; j < width; j++)
    {
       for (int i = 0; i < height; i++)
       {
           int sepiared =  image[i][j].rgbtRed *.393  +   image[i][j].rgbtGreen *.769 +  image[i][j].rgbtBlue *.189;
           int sepiagreen =  image[i][j].rgbtRed *.349  +  image[i][j].rgbtGreen *.686 +  image[i][j].rgbtBlue *.168;
            int sepiablue =  image[i][j].rgbtRed *.272  +   image[i][j].rgbtGreen *.534 +  image[i][j].rgbtBlue *.131;
           image[i][j].rgbtRed = sepiared;
           image[i][j].rgbtGreen = sepiagreen;
           image[i][j].rgbtBlue = sepiablue;
       }
    }

    return;
}

请帮助我理解为什么会发生这种情况。 Clang 不打印任何错误消息。

您真诚的, 迷失在代码中:)

最佳答案

首先,顺便说一句,当您有 CS50 问题时,请在提问前先在 StackOverflow 中搜索关键字。答案大概就在那里。如果您搜索 sepia RGBTRIPLE cs50,您会得到相当多的结果。

进行大量像素处理后,您将磨练一些有用的调试直觉。其中:

  • 如果您看到对角线偏移,则图像的每行字节数可能大于宽度乘以像素大小。 (特别是在 YCbCr 图像中或图像缓冲区与 128 位 vector 大小对齐的平台上。)
  • 2x 或 0.5x 图像显示可能意味着您没有注意到 Retina 显示屏上的比例值。
  • 某些色彩空间错误会立即让您发现 BGR 与 RGB 字节排序问题。根本没有蓝色 channel 还是全蓝色?可能将 ARGB 与 BGRA 混合。

但更重要的是:

  • 如果您在明亮或颜色饱和的区域看到奇怪的现象,则您的像素分量值可能过饱和(超过最大值,并丢弃高位)。

每次 (1) 将一个颜色分量乘以大于 1 的数字或 (2) 将多个颜色分量相加时,您需要考虑如果超过最大值会发生什么。如果您的中级数学将两个值相加然后除以 2,请确保您的编译操作将使用足够大的变量大小来容纳额外的位。

因此,在此处的内部循环中,当对白色像素进行操作时,几乎每个颜色分量都会超过 255(即红色和绿色会超过,但不会超过蓝色,因为棕褐色的蓝色含量较低):

int sepiared =  image[i][j].rgbtRed *.393  +   image[i][j].rgbtGreen *.769 +  image[i][j].rgbtBlue *.189;
int sepiagreen =  image[i][j].rgbtRed *.349  +  image[i][j].rgbtGreen *.686 +  image[i][j].rgbtBlue *.168;
int sepiablue =  image[i][j].rgbtRed *.272  +   image[i][j].rgbtGreen *.534 +  image[i][j].rgbtBlue *.131;

结果值为 {255, 255, 255} x {.393+.769+.189, .349+.686+.168, .272+.534+.131} 或 {344.5, 306.8 ,238.9}。

但是,由于 RGBTRIPLE 结构的 BYTE 组件中的这些值没有足够的位,因此您的值将不正确。因此,您可以这样做:

int sepiared =  (int) image[i][j].rgbtRed *.393  +   image[i][j].rgbtGreen *.769 +  image[i][j].rgbtBlue *.189;
int sepiagreen =  (int) image[i][j].rgbtRed *.349  +  image[i][j].rgbtGreen *.686 +  image[i][j].rgbtBlue *.168;
int sepiablue =  (int) image[i][j].rgbtRed *.272  +   image[i][j].rgbtGreen *.534 +  image[i][j].rgbtBlue *.131;
sepiared = min(sepiared, 255);
sepiagreen = min(sepiagreen, 255);
sepiablue = min(sepiablue, 255);

请注意,我做了两项更改:

  1. 将每个表达式中的第一个值转换为 (int);否则计算将以字节为单位进行,并且您将丢失高位。
  2. 对每个像素组件强制使用最大值 255。

在考虑其他答案时,请添加我的第一个修复。如果您已经放弃了高位,则检查最大值 255 将无济于事!

关于Cs50 棕褐色将图像从正常转换为棕褐色的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63416505/

相关文章:

c - 错误 : invalid operands to binary expression ('float' and 'float' )

当文件位于不同的文件夹中时无法创建项目

filter - Hbase 0.94 中的列值范围过滤器

javascript - 如何使用Lodash _.filter过滤多条件?

c - Luhn 算法的 for 循环中的未知值

c - 如何通过更改参数来更改C中变量的值

c - 在 C 中打印所有列表元素

c - OpenGL 与 SDL,我做错了什么?

External Interrupt Program 会不会太长不能正常工作?

c - 图像卷积,误差生成滤波图像