Skip to content
Advertisement

PIL’s colour space conversion YCbCr -> RGB

The algorithm used by PIL v1.1.7 gives ‘washed out’ looking results. When converting the same source data using ffmpeg it looks correct. Using mplayer gives identical results to ffmpeg (perhaps they use the same library underneath). This leads me to believe PIL may be stuffing up the colour space conversions. The conversion seems to be sourced in libImaging/ConvertYCbCr.c:

JavaScript

This is just a comment in the source, of course it’s C code and the actual function is implemented with lookup tables not matrix multiplication (the static INT16 R_Cr etc. snipped for brevity):

JavaScript

I have googled but there seems to be a lot of confusion about the ‘right’ way to do this colour space conversion. So my question is, is the above correct – and if not what is a better way?


edit: After reading the links provided by Mark Ransom, I discovered that conflicting definitions exist depending on whether you use the full range of YCbCr or clamp out to the valid range. See links below for more info:

It seems the PIL version is using the incorrect algorithm, so I’ve rolled my own function for the conversion which gives the correct looking results (“SDTV” version). Code included below, for future readers to use:

JavaScript

Advertisement

Answer

If you look at Wikipedia’s definitions, you can see that there are two conflicting definitions for YCbCr. The ITU-R BT.601 definition compresses the values to the range 16-235 to provide footroom and headroom, while the JPEG version uses the full range 0-255. If you were to decode values in the BT.601 space using the formula for JPEG, the result would definitely look washed out.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement