I was playing around with some different image formats and ran across something I found odd. When converting from RGB to YCbCr and then back to RGB, the results are very similar to what I started with (the difference in pixels values is almost always less than 4). However, when I convert from YCbCr to RGB and then back to YCbCr, I often get vastly different values. Sometimes a values will differ by over 40.
I'm not sure why this is. I was under the impression that the colors which could be expressed through YCbCr were a subset of those in RGB, but it looks like this is completely wrong. Is there some known subset of colors in YCbCr that can be converted to RGB and then back to their original values?
The code I'm using to convert (based on this site):
def yuv2rgb(yuv):
ret = []
for rows in yuv:
row = []
for y, u, v in rows:
c = y - 16
d = u - 128
e = v - 128
r = clamp(1.164*c + 1.596*e, 16, 235)
g = clamp(1.164*c - 0.392*d - 0.813*e, 16, 240)
b = clamp(1.164*c + 2.017*d , 16, 240)
row.append([r, g, b])
ret.append(row)
return ret
def rgb2yuv(rgb):
ret = []
for rows in rgb:
row = []
for r, g, b in rows:
y = int( 0.257*r + 0.504*g + 0.098*b + 16)
u = int(-0.148*r - 0.291*g + 0.439*b + 128)
v = int( 0.439*r - 0.368*g - 0.071*b + 128)
row.append([y, u, v])
ret.append(row)
return ret
EDIT:
I created a rudimentary 3D graph of this issue. All the points are spots with a value difference less than 10. It makes a pretty interesting shape. X is Cb, Y is Cr, and Z is Y.