c - 将图像从正常转换为棕褐色的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 不打印任何错误消息。
你真的,迷失在代码中:)
解决方案
首先,顺便说一句,当您有 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);
请注意,我做了两个更改:
- 将每个表达式中的第一个值转换为 (int); 否则计算将在字节上完成,你会失去你的高位。
- 对每个像素分量强制执行最大值 255。
在考虑其他答案时,请添加我的第一个修复。如果您已经放弃了高位,检查最多 255 将无济于事!
推荐阅读
- loadrunner - Javascript 错误的 LoadRunner Replay 问题
- java - 嵌套 RPC 调用的 RpcDispatcher 超时
- javascript - 在 Javascript 中使用外部 TypeScript 脚本
- python - Python 关闭其他用户可能打开的文件
- r - undo str_split 组合单词是一个段落?(右)
- algorithm - 关于量子算法:矩阵乘积算法
- google-api - 未找到 ACL 发布 Google 日历域
- node.js - Firebase 身份验证访问令牌失败,使用身份验证自定义令牌创建令牌
- docker - standard_init_linux.go:211:exec 用户进程在 linux 上运行 Docker 时导致“没有这样的文件或目录”,即使使用 find 命令也是如此
- vb.net - 如何在 Vb.net 中使用函数返回多个值