Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion. Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules. |
26th January 2024, 07:34 | #1 | Link |
Registered User
Join Date: Jul 2011
Posts: 1,121
|
Converting YUV to RGB formulas?
This is off topic as it's not really for avisynth development,
but hopefully it's close enough for a pass, otherwise I can be taken down of course. I'm trying to figure out the correct formula for converting YUV to RGB, both Rec601/Rec709 with Limited/Full range. The ones I have found doesn't seem to match what avisynth produces, apart from one which is this: Code:
R = 1.164 * (Y - 16) + 1.793 * (U - 128); G = 1.164 * (Y - 16) - 0.534 * (U - 128) - 0.213 * (V- 128); B = 1.164 * (Y - 16) + 2.115 * (V - 128); This produces as far as i can tell the same results Rec709 Limited. But it doesn't really match the formula shown here: https://en.wikipedia.org/wiki/Y%E2%80%B2UV And i also don't know how to make it full range, except for the Y part. I tried looking at the avisynth code to figure this out, but it was harder than I thought. So was hoping to get some help here if possible |
26th January 2024, 08:26 | #2 | Link |
Registered User
Join Date: May 2006
Posts: 3,997
|
Your matrix above applies for Rec709 limited range Y'CbCr -> Full range RGB conversion. (You may have mixed up U an V though, please double check)
U and V are from the analog realm; one should actually be using Cb and Cr in the digital realm. Sometimes interchangeably used, unfortunately. For conversions you may want to take a look here: https://web.archive.org/web/20120403...rmatConversion or check out the tool here: https://res18h39.netlify.app/color Last edited by Sharc; 26th January 2024 at 11:13. Reason: Link added |
26th January 2024, 13:57 | #3 | Link |
Avisynth language lover
Join Date: Dec 2007
Location: Spain
Posts: 3,431
|
See also here: http://avisynth.nl/index.php/Color_conversions
|
26th January 2024, 15:41 | #4 | Link |
Registered User
Join Date: Jul 2018
Posts: 1,063
|
Correct equations are in the free available ITU documents (601/709/2020) .
AVS+ narrow range in current builds is not completely correct (waiting for pinterf patch merging). There possible very many forms of simplified equations for each use case and it is not easy to check the result. So if current ready to use simplified equations not provide correct/expected values - it is good to start from official documents from ITU. Simple C-form (reference) in the decodeYUVtoRGB plugin - https://github.com/DTL2020/ConvertYU...eYV12toRGB.cpp iY = *l_srcp_Y + Ybias; // Ybias = -16 iU = *l_srcp_U + UVbias; // UVbias=-128 iV = *l_srcp_V + UVbias; // UVbias=-128 int iR = iY + ((iV * Kr) >> 13); int iB = iY + ((iU * Kb) >> 13); int iG = iY - ((iU * Kgu) >> 13) - ((iV * Kgv) >> 13); and Kr, Kgu, Kgb, Kb /* Computing of (Kr, Kgu, Kgv, Kb) from (Yr and Yb) coefficients of YUV colour system: Yr Yg = 1.0 - (Yr + Yb) Yb Kb = (1.0 - Yb) * 2 Kr = (1.0 - Yr) * 2 Kgu = (Yb * Kb) / Yg Kgv = (Yr * Kr) / Yg for Digital UV (601/709/2020): RatioUVtoY = 219.0/224.0 Kr,Kb,Kgu,Kgv *= RatioUVtoY */ if (Matrix == 0) // 601 { fYr = 0.299f; fYb = 0.114f; } else if (Matrix == 1) // 709 { fYr = 0.2126f; fYb = 0.0722f; } else if (Matrix == 2) // 2020 (ncl ?) { fYr = 0.2627f; fYb = 0.0593f; } float fKb = (1.0f - fYb) * 2.0f; float fKr = (1.0f - fYr) * 2.0f; float fYg = 1.0f - (fYr + fYb); Kr = (short)(fKr * fRatioUVtoY * UVgain * mulfac + 0.5f); Kb = (short)(fKb * fRatioUVtoY * UVgain * mulfac + 0.5f); Kgu = (short)(((fYb * fKb) / fYg) * fRatioUVtoY * UVgain * mulfac + 0.5f); Kgv = (short)(((fYr * fKr) / fYg) * fRatioUVtoY * UVgain * mulfac + 0.5f); UVgain=1.0, mulfac = double(1 << int_arith_shift); // integer aritmetic precision scale Last edited by DTL; 27th January 2024 at 22:28. |
27th January 2024, 08:21 | #6 | Link | |
Registered User
Join Date: Jul 2011
Posts: 1,121
|
Quote:
Thought Y'CbCr was "Component Video" and YUV was, well the normal stuff, both Digital and Analogue where it's Y, U and V. @DTV Will try it out, was more steps there than "usual", will try to find the ITU documentations as well for the equations. Last edited by zerowalker; 27th January 2024 at 08:24. |
|
27th January 2024, 12:31 | #7 | Link | |
Registered User
Join Date: May 2006
Posts: 3,997
|
Quote:
The symbols U and V are sometimes used quite loosely. Avisynth adopted U and V for the digital realm (probably for convenience and historic reasons) rather than Cb and Cr. For the discussion here you can assume U=Cb and V=Cr. |
|
27th January 2024, 18:04 | #8 | Link |
Registered User
Join Date: Jul 2018
Posts: 1,063
|
"Thought Y'CbCr was "Component Video""
Most important difference between Analog (abstract YUV or defined in 0..XXX mV voltage range typically with zero black and zero UV for math zero value) and Digital YUV (CbCr for Coded B-Y and R-Y?) in storage and transfer domains data form. The 601/709/2020 recs are about digital exchange formats for motion pictures - not only abstract YUV-descriptions. Analog YUV looks like exist in the equal scale Y and UV signals (as provided from RGB->YUV matrix). Digital YUV uses quantization and some Digital YUV systems uses non-equal scale for Y and UV data in the output (storage and transfer/distribution/interfacing) form. For performance of processing in lowest possibe steps number real YUV<->RGB equations are significantly compacted. Real steps are: 1. Decode YUV from Digital YUV storage domain into abstract YUV 0..1 float domain. 2. Apply YUV->RGB matrix conversion in abstract 0..1 float domain. 3. Convert (encode) RGB into output digital domain (or other required at output). Some designers with good understanding in math can warp 1+2+3 in the single step processing by some compute engine. It make best processing performance but may suffer from issues if something important is missing. And also harder or impossible to debug in steps. The 601/709/2020 recs define Digital (quantized form) YUV domain as having non-equal scale for Y and UV data (219 for Y and 224 for UV/CbCr). It may be designed to have a bit less quantization noise in UV low-bit data with natural colour gamuts for these systems (or for YUV as having larger colour gamut in compare with RGB). So the very typical error for convertor designers is missing Y and UV input data normalization to equal scale. It is 219/224 ratio in the math displayed. The resulted error is not very big but visible even in 8bit samples. Last edited by DTL; 27th January 2024 at 22:30. |
29th January 2024, 07:32 | #9 | Link |
Registered User
Join Date: Jul 2011
Posts: 1,121
|
Thanks for the explanation
When doing the y offset (Y-16) in float (0-1). Isn't it (Y-(16/255))? Cause when I do this Rec709 is valid, but Rec601 is wrong by a tiny amount, but (Y-(16/256)) makes it valid. (valid as in, identical to avisynth). EDIT: Okay even PC.601 becomes a tiny bit wrong. EDIT 2: Okay it seems this happens even with ffmpeg, is it cause some small math error in avisynths conversion? Last edited by zerowalker; 29th January 2024 at 16:58. |
29th January 2024, 17:20 | #10 | Link |
Registered User
Join Date: Jul 2018
Posts: 1,063
|
"When doing the y offset (Y-16) in float (0-1).
Isn't it (Y-(16/255))?" 0..1 range in float is 16 to 235 code values in 8bit Digital YUV (scaled + shifted/offsetted). 235-19=219. Typically we subtract 16 and maps result of 0..219 to 0..1 float (so divide by 219.0). The range above 235 code values in storage Digital YUV 8bit is for super-whites (above nominal 100% white for SDR). If you first convert 0..255 integer to float 0.0..255.0 it maybe also easy to subtract 16.0 and divide result to 219.0 (for performance - multiply to 1/219.0 constant). You will got black and nominal white in 0.0..1.0 range and negative under-blacks and 1.0+ super-whites. For UV it is subtract 128 and divide by 224. See https://www.itu.int/dms_pubrec/itu-r...3-I!!PDF-E.pdf 2.5.3 and 2.5.4 "it seems this happens even with ffmpeg, is it cause some small math error in avisynths conversion?" AVS and ffmpeg may use integer computing with less precision for performance. Try ConvertBits(32) before ConvertToRGB and check output float32 RGB values. See also some posts around https://forum.doom9.org/showthread.p...20#post1987720 about YUV to RGB decoding in AVS. Some +-1 rounding/computing errors still visible in 8bits. As fix maybe used 10bits (12..16) computing and rounding to 8bits with ConvertBits(8). So it is possible to get exactly 16/180 8bit RGB narrow code values for all colours of ColorBarsHD YUV output. Last edited by DTL; 29th January 2024 at 17:49. |
Thread Tools | Search this Thread |
Display Modes | |
|
|