I\'ve implemented rgb->ycrcb and ycrcb->rgb conversion using JPEG conversion formulae from
http://www.w3.org/Graphics/JPEG/jfif3.pdf
(the same at: http://en.wikipedia.o
The problem isn't rounding modes.
Even if you converted your floating point constants to ratios and used only integer math, you'd still see different values after the inverse.
To see why, consider a function where I tell you I'm going to shift the numbers 0 through N to the range 0 through N-2. The fact is that this transform is just doesn't have an inverse. You can represent it more or less exactly with a floating point computation (f(x) = x*(N-2)/N
), but some of the neighboring values will map to the same result in integer math (pigeonhole principle!). This is a simplification and "compresses" the range, but the same thing happens in arbitrary affine transforms like this one you are using.
If you had r, g, b in floating point, and kept it that way until you quantized to integer, that would be a different story - but in integers you will necessarily always see some difference between the original and the inverse.
Yes, supposedly JPEG XR defines a color conversion that is reversible. The code is open source if you want to investigate in depth how they're doing it. The method is loosely described on the Wiki-page I linked to.
Also this SO post might give you some insights.
Only about 60% of all RGB values can be represented in YCbCr space when using the same amount of bits for both triplets. This means the most damage happens in RGB->YCbCr when you take a 3*8 bit RGB triplet, convert and round it back to 3*8 bits of precision. The trick is to store the YCbCr triplet at a higher precision until it's time to do forward DCT. There, the data needs to be scaled up anyway, so you can do e.g. 16 bit * 16 bit -> MSB16 multiplies, which are well supported by various SIMD instruction sets.
At the decoder it's the reverse: The results of inverse DCT have to be stored at higher precision until it's time to do the YCbCr->RGB conversion.
This doesn't make the process lossless, but for JPEG, it may buy a few dB of PSNR at the extreme high end of the quality scale, i.e. where the difference can't be seen with a naked eye but can be measured.
Another problem is that there is not a 1 to 1 mapping between rgb and YCbCR. There are YCbCr values with no corresponding RGB value and RBG values with no corresponding YCbCR values.