首页 > 解决方案 > 将图像从正常转换为棕褐色的cs50棕褐色问题

问题描述

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

原来的

原来的

棕褐色

在此处输入图像描述

如您所见,它转换了一切都很好,除了白色或接近白色的颜色。这是我的代码(仅限棕褐色部分):


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 不打印任何错误消息。

你真的,迷失在代码中:)

标签: cfiltercs50

解决方案


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

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

  • 如果您看到对角线偏移,则图像的每行字节数可能大于宽度乘以像素大小。(尤其是在 YCbCr 图像或图像缓冲区与 128 位矢量大小对齐的平台上。)
  • 2x 或 0.5x 图像显示可能意味着您没有注意 Retina 显示器上的比例值。
  • 某些色彩空间错误会立即将您指向 BGR 与 RGB 字节排序问题。根本没有蓝色通道或全是蓝色?可能将 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 将无济于事!


推荐阅读