我该如何解决这个YCrCb – > RBG转换公式?
我使用这个问题的公式:
uint8_t *rgbBuffer = malloc(imageWidth * imageHeight * 3); // .. iterate over height and width // from ITU-R BT.601, rounded to integers rgbOutput[0] = (298 * (y - 16) + 409 * cr - 223) >> 8; rgbOutput[1] = (298 * (y - 16) + 100 * cb + 208 * cr + 136) >> 8; rgbOutput[2] = (298 * (y - 16) + 516 * cb - 277) >> 8;
我认为这是基于维基文章中的ITU-R_BT.601公式 。
但是我认为这个公式并不完全正确,因为输出图像如下所示:
我如何修复这个公式?
假设第一次计算的最大值( y == 255
和cr == 255
):
rgbOutput[0] = (298 * (255 - 16) + 409 * 255 - 223) >> 8; rgbOutput[0] = (298 * 239 + 104295 - 223) >> 8; rgbOutput[0] = (71222 + 104295 - 223) >> 8; rgbOutput[0] = 175294 >> 8; // 175294 == 0x2ACBE rgbOutput[0] = 684; // 684 == 0x2AC
rgbOutput[0]
可容纳的最大值是255
。 您正试图将684
分配给它,导致截断。 分配给它的实际值是172
( 0xAC
)。
编辑1
根据你公布的公式,你的第一个计算应该如下:
rgbOutput[0] = ((298 * y) >> 8) + ((409 * cr) >> 8) - 223;
这导致(假设y
和cr
最大值)为480
,这也导致截断。
编辑2
据说build议使用以下等式:
用这个代替,你的第一个计算应该是这样的:
rgbOutput[0] = ((255 * (y - 16)) / 219) + ((179 * (cr - 128)) / 112;
这导致(假定y
和cr
最大值)为480
(在编辑1中相同的答案)的值,这也导致截断。
编辑3
查看@Robert的答案以获得完整的解决scheme。
编辑4
当y == 0
和cr == 0
,写入y
的值也会导致截断,除非执行钳位。
在@Fiddling位帮助。 更正后的代码如下所示:
uint8_t ClampIntToByte(int n) { n = n > 255 ? 255 : n; return n < 0 ? 0 : n; } rgbOutput[0] = ClampIntToByte(((298 * (y - 16) + 409 * cr) >> 8) - 223); rgbOutput[1] = ClampIntToByte(((298 * (y - 16) - 100 * cb - 208 * cr) >> 8) + 136); rgbOutput[2] = ClampIntToByte(((298 * (y - 16) + 516 * cb) >> 8) - 277);