VideoHelp Forum
+ Reply to Thread
Page 2 of 2
FirstFirst 1 2
Results 31 to 42 of 42
Thread
  1. Again, nice work, Sharc.
    Quote Quote  
  2. Originally Posted by Sharc View Post
    I took the matrix coefficients for R'G'B' -> Y'CbCr conversion from ITU-R BT.709-6, formula 3.5. For 8bit n=8.
    There is issue with this formula - normally you should use 10 bit (8.2 code) and in 10 bit apply mentioned error rounding - conversion to 8 bit values is performed by truncation of fractional part i.e. 8 bit values without fraction - there is no error rounding there - this is subtle but important difference (if you work with broadcast equipment and sources then those differences begin to be obvious).
    Not sure why there is many errors in standards and recommendations...
    Quote Quote  
  3. Here is an interesting tidbit to add to this discussion. Fortunately the calculation results agree with Sharc's calculations for 709.

    https://www.silicondust.com/yuv-to-rgb-conversion-for-tv-video/
    Quote Quote  
  4. Here is the ffmpeg code I use to encode to Y,Cb,Cr 709:

    Code:
    ffmpeg -y   -loop 1 -t 60  -i "color_bars.bmp"  -pix_fmt yuv420p  -c:v  libx265  -c:a  none  -crf 0  -vf scale=w=1280:h=720:out_color_matrix=bt709:out_range=limited  -color_primaries bt709  -color_trc bt709  -colorspace bt709  -r 59.94    bars.mp4
    Quote Quote  
  5. Sharc: would you be willing to work out the conversion equation for BT.2020 / BT.2100?

    Thanks.
    Quote Quote  
  6. Originally Posted by chris319 View Post
    Sharc: would you be willing to work out the conversion equation for BT.2020 / BT.2100?

    Thanks.
    Do you mean doing the matrix inversions? I have really no experience at all with BT.2020, I am not even sure whether the matrix conversion principle still applies for BT.2020 similar as for 601/709.
    Maybe someone else will chime in .....
    Quote Quote  
  7. Do you mean doing the matrix inversions? I have really no experience at all with BT.2020, I am not even sure whether the matrix conversion principle still applies for BT.2020 similar as for 601/709.
    Yes. The math is way over my head.

    Page 4:

    https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.2020-2-201510-I!!PDF-E.pdf
    Quote Quote  
  8. https://github.com/sekrit-twc/zimg
    conversion library between colorspaces, bitdepths, resolutions ... so while avoiding apps that use it, maybe you can use it directly, there is some API examples
    Quote Quote  
  9. Originally Posted by jagabo View Post
    I hate it when people give only the final matrix equations for complex conversions. They're are nice for coding but do not elucidate where all the coefficients come from.

    Originally Posted by chris319 View Post
    This code gets me close but is not very accurate:

    Code:
    Kr = 0.299
    Kg = 0.587
    Kb = 0.114 
    
    r = y + 2*(v-128)*(1-Kr) 
    g = y - 2*(u-128)*(1-Kb)*Kb/Kg - 2*(v-128)*(1-Kr)*Kr/Kg
    b = y + 2*(u-128)*(1-Kb)
    75% yellow: Y=168, Pb=44, Pr=136
    The Kr, Kg, Kb coefficients are for rec.601 but your "YPbPr" values are for limited range rec.709 YCbCr. And they are rounded to the nearest integer. If you use the reciprocal equation and floating point for all the calculations you'll see that the actual limited range values for R=191, G=191, B=0 are Y=168.192, U=44.110, V=135.692. The quoted conversion equation is for converting full range YUV to full range RGB.

    The correct coefficients and equations for converting full range RGB to limited range YUV (YCbCr), and full range RGB to full range YUV are given at the aviSynth.nl:

    http://avisynth.nl/index.php/Color_conversions

    The correct way convert studio (limited range) RGB to limited range YUV is to first convert the studio RGB to full range RGB then convert to limited range YUV using those equations. To reverse the operation convert the YUV to full range RGB then convert the full range RGB back to limited range RGB.

    Code:
    sRGB = each studio RGB component
    fRGB = each full range RGB component
    
    sRGB = fRGB * 219 / 255 + 16
    fRGB = (sRGB-16) * 255 / 219
    Where do the 255 and 219 values come from? Those are the ranges between the defined full black and full white. 255 = 255-0, 219 = 235-16. They should be familiar from the limited range YUV conversion equations.

    Given those sRGB to fRGB equations and full range RGB to limited range YUV equations from from the AviSynth docs:

    Code:
    Kr = 0.2126
    Kg = 0.7152
    Kb = 0.0722
    
    y - 16 = (Kr*219/255)*r + (Kg*219/255)*g + (Kb*219/255)*b 
    v - 128 = 112/255*r - Kg*112/255*g/(1-Kr) - Kb*112/255*b/(1-Kr) 
    u - 128 = - Kr*112/255*r/(1-Kb) - Kg*112/255*g/(1-Kb) + 112/255*b 
    
    r = (255/219)*y + (255/112)*v*(1-Kr) - (255*16/219 + 255*128/112*(1-Kr)) 
    g = (255/219)*y - (255/112)*u*(1-Kb)*Kb/Kg - (255/112)*v*(1-Kr)*Kr/Kg
        - (255*16/219 - 255/112*128*(1-Kb)*Kb/Kg - 255/112*128*(1-Kr)*Kr/Kg) 
    b = (255/219)*y + (255/112)*u*(1-Kb) - (255*16/219 + 255*128/112*(1-Kb))
    You do the following:

    First convert the sRGB to fRGB:

    Code:
    R = (180-16) * 255 / 235 ~= 191
    G = (180-16) * 255 / 235 ~= 191
    B = (16-16) * 255 / 235 = 0
    Then plugging those values in the YUV conversion gives you limited range YUV components (rounded to the nearest integer) Y=168, U=44, V=136. Look familiar? Using the inverse conversion (and rounding) gives you back the r=191, g=191, b=0. And converting that fRGB back to sRGB gives you 180, 180, 16. With some other colors the round trip will be off by 1 or 2 units per component -- from the multiple rounding operations. If you run the equations in floating point (with no rounding) you'll find the conversions are accurate to within the accuracy of the floating point operations (roughly 1 in 10^7 with single precision fp, 1 in 10^16 with double precision fp).
    This code returns R=181, G=180, B=12
    Code:
     
    Kr = 0.2126
    Kg = 0.7152
    Kb = 0.0722
    
    y.f = 168
    u.f = 44
    v.f = 136
    
    r = y + 2*(v-128)*(1-Kr)
    g = y - 2*(u-128)*(1-Kb)*Kb/Kg - 2*(v-128)*(1-Kr)*Kr/Kg
    b = y + 2*(u-128)*(1-Kb)
    The YUV values in RP-219 are full range, apparently. No conversion to limited range is needed. The RP-219 spec was devised long before the 16 - 235 provision.
    Quote Quote  
  10. Originally Posted by chris319 View Post
    The YUV values in RP-219 are full range, apparently.
    Limited range

    75% W is listed as Y 180 in rp219 . 0.75*235 = 180 for limited range.

    You would excpect 0.75*255 = 191 for full range 75% white
    Quote Quote  
  11. Originally Posted by poisondeathray View Post
    Originally Posted by chris319 View Post
    The YUV values in RP-219 are full range, apparently.
    Limited range

    75% W is listed as Y 180 in rp219 . 0.75*235 = 180 for limited range.
    OK

    You would excpect 0.75*255 = 191 for full range 75% white
    There could be excursions above 235 on actual video content, not just test signals. These can be clipped off because they are theoretically not important video content.

    0 and 255 are reserved for sync.

    Here is the broadcast legalizer which works great with lossless libx264 (crf 0). libx265 leaves too many artifacts and is slower than a glacier.

    Code:
    ffmpeg -y  -hide_banner  -i "C0015.mp4" -vf  scale=width=1280:height=720:flags='lanczos',limiter=16:235:1,limiter=16:240:6,setparams=range="tv"  -codec:v libx264  -crf 0  -pix_fmt:v yuv422p  -color_range "tv"  -color_primaries bt709  -color_trc bt709 -colorspace bt709  -movflags +write_colr  -r 59.94  -c:a copy  limited.mov
    Quote Quote  
  12. Originally Posted by chris319 View Post
    This code returns R=181, G=180, B=12
    Avisynth docs equations and internal convertion like ConvertToRGB/YUV() are not completely correct for narrow (limited) RGB<->YUV - they may miss 224/219 different scaling domains of Y and Cb/Cr data in digital form (equal for all current typical digital colour standards 601/709/2020). At least up to 3.7.3 release. As I understand Pinterf first promises to make small fix but later looks like decide to make big redesign of many internal conversion functions for correct precision and performance but lost before 3.7.3 release.

    The typically available in the Internet search equations for RGB<->YUV designed to work with all 3 channels data in equal scale. So when user operates with YUV data (encoded in 601/709/2020 standards) in storage/distribution domain - he need to take into math equations equalizing of Y and UV scaling (using pre-computed float coefficients for better precision) before applying standard RGB<->YUV equations. Also after computing YUV from RGB - the UV must be quantized in 224-scale while Y in 219-scale. The idea of different scale domains (before quantization) may be designed to have a bit lower quantization noise in 8 and 10 bit digital UV data in storage/distributuion.

    Also typical equations works in range 0..max RGB and YUV - so user typically need to subtrack black offset from Y and 'zero' offset from UV before apply RGB<->YUV equations.
    So 'standard digital' storage domain for YUV data includes:
    1. 224 scale for UV and 219 scale for Y
    2. 16 offset for Y and 128 offset for UV
    And 1 + 2 must be reversed before applying YUV->RGB transform. And result produced with zero black RGB (bipolar with negative under-blacks). To encode into digital narrow range RGB - add +16 offset (all in 8bit).

    So in AVS currently for correct YUV->RGB (narrow/limited) only external plugins are completely correct or user need to apply 224/219 (or back 219/224) additional UV gain before conversion with internal functions.

    Also as many modern EBU docs call non-full datarange as 'narrow' it may be named nRGB (to be different from sRGB).

    Also note about better thread naming (coded or analog R and B colour difference data) may be important because that different scaling domains (analog gain in analog form) may be also different between digital and analog Y and RB colour difference data (or signalling).
    Last edited by DTL2023; 22nd Sep 2023 at 02:53.
    Quote Quote  



Similar Threads

Visit our sponsor! Try DVDFab and backup Blu-rays!