View Full Version : converttoyuy2
Wilbert
8th March 2015, 19:21
I was looking at Rec2020 support, but i got stuck somewhere. So I hope someone can help me. Somewhere in the code of converttoyuy2 i see the following:
__declspec(align(8)) static const __int64 y1y2_fpix[4] ={0x5033A29E3F74B61E, //=(1/((1-0.299)*255/112)<<15+0.5), (1/((1-0.114)*255/112)<<15+0.5)
...
I see that "(1/((1-0.299)*255/112)<<15+0.5)" is 5033h and "(1/((1-0.114)*255/112)<<15+0.5)" is 3F74h. But where are the other values (A29E and B61E) are coming from?
innocenat
12th March 2015, 14:33
I did not dig into too much detail so I don't know what the number actually is. But here's a general idea:
Those are factor to convert RGB to YCbCr. Basically all the component Y, Cb and Cr can be calculated from linear combination of R, G, and B. But that would mean total of 9 multiplications. It is possible to rewrite Cb into function of B and Y, and Cr into function of R and Y. According to StackOverflow (https://stackoverflow.com/questions/17536417/correct-conversion-from-rec-709-to-srgb) answer (though that is for Rec 709), the coefficient of Y is negative. And the number you don't know about (0xA29E, 0xB61E) are both negative.
Look at code line 728 which actually use this value, it uses pmaddw so I think this theory is correct.
StainlessS
12th March 2015, 16:21
Here is some stuff for rec601 that I was playing with a few years ago (matrix for EigenMath).
REC601Kr=0.299
REC601Kb=0.114
REC601Kg=1.0-(REC601Kr+REC601Kb)
REC601ScaleKb = 0.5/(1-REC601Kb)
REC601ScaleKr = 0.5/(1-REC601Kr)
REC601=(
(REC601Kr, REC601Kg, REC601Kb),
(-REC601Kr*REC601ScaleKb, -REC601Kg*REC601ScaleKb, (1.0-REC601Kb)*REC601ScaleKb),
((1.0-REC601Kr)*REC601ScaleKr, -REC601Kg*REC601ScaleKr, -REC601Kb*REC601ScaleKr)
)
REC709Kr=0.2126
REC709Kb=0.7152
REC709Kg=1.0-(REC709Kr+REC709Kb)
REC709ScaleKb = 0.5/(1-REC709Kb)
REC709ScaleKr = 0.5/(1-REC709Kr)
REC709=(
(REC709Kr, REC709Kg, REC709Kb),
(-REC709Kr*REC709ScaleKb, -REC709Kg*REC709ScaleKb, (1.0-REC709Kb)*REC709ScaleKb),
((1.0-REC709Kr)*REC709ScaleKr, -REC709Kg*REC709ScaleKr, -REC709Kb*REC709ScaleKr)
)
and conversion of the convertToYUY2 CPP to VB
Option Explicit
' -----------------------------------------------------------------
Private Const cyb As Double = 0.114
Private Const cyg As Double = 0.587
Private Const cyr As Double = 0.299
Private Const cbu As Double = 2.018
Private Const crv As Double = 1.596
Private Const cgu As Double = 0.391
Private Const cgv As Double = 0.813
Private Const yDwnScale As Double = (219# / 255#)
Private Const yUpScale As Double = (1# / yDwnScale)
Private Const yOffset As Integer = 16
Private Const uvOffset As Integer = 128
' -----------------------------------------------------------------
Public Sub RGBtoYUY2(r1 As Integer, b1 As Integer, g1 As Integer, _
r2 As Integer, b2 As Integer, g2 As Integer, _
ByRef Y1ref As Integer, ByRef Uref As Integer, _
ByRef Y2Ref As Integer, Vref As Integer)
' Only y is ranged for CCIR NOT u or v (both based on scaled_y)
Dim scaled_y1 As Double, scaled_y2 As Double, b_y As Double, r_y As Double
Dim y As Integer, U As Integer, V As Integer
scaled_y1 = cyr * r1 + cyg * g1 + cyb + b1
scaled_y2 = cyr * r2 + cyg * g2 + cyb + b2
b_y = ((b1 + b2) - (scaled_y1 + scaled_y2)) / 2#
r_y = ((r1 + r2) - (scaled_y1 + scaled_y2)) / 2#
y1 = Round(scaled_y1 * yDwnScale + yOffset) ' CCIR Ranging
y2 = Round(scaled_y2 * yDwnScale + yOffset) ' CCIR Ranging
U = Round(b_y / cbu + uvOffset)
V = Round(r_y / crv + uvOffset)
Y1ref = Min(Max(y1, 0), 255)
Y2Ref = Min(Max(y2, 0), 255)
Uref = Min(Max(U, 0), 255)
Vref = Min(Max(V, 0), 255)
End Sub
Dont know if of use.
StainlessS
12th March 2015, 16:31
A bit more, not sure where I got it,.
Table 1: Coefficients Kry and Kby of color conversion from RGB to YCbCr.
Reference standard Kry Kby [ Kgy ]
ITU601 / ITU-T 709 1250/50/2:1 0.2990 0.1140 [ 0.5870 ]
ITU709 / ITU-T 709 1250/60/2:1 0.2126 0.0722 [ 0.7152 ]
SMPTE 240M (1999) 0.2120 0.0870 [ 0.7010 ]
-----------------------------------------------------------------
YUV color model imitates a human vision. Humans are able to recognize (discern) the
contents of a color RGB (Red / Green / Blue) image presented in the two main forms,
as an original RGB color image or as a gray (black / white) image.
Historically, YUV color space was developed to provide compatibility between color
and black /white analog television systems. YUV color image information transmitted
in the TV signal allows proper reproducing an image contents at the both types of TV
receivers, at the color TV sets as well as at the black / white TV sets.
Term YUV itself is not defined precisely in the technical and scientific literature.
In general it designates a whole family of so called luminance / chrominance color
spaces. The best way to avoid ambiguity associated with the term YUV is to refer to
the concrete variant of YUV colors space well defined in the internationally
recognized standard documents.
YCbCr color space is defined in the ITU-R BT.601-5 [1] and ITU-R BT.709-5 [2] standards
of ITU (International Telecommunication Union). These documents define YCbCr as a color
space for digital television systems. These documents give concrete definitions for
coefficients of conversion between RGB and YCbCr color spaces, for normalization and
quantization of digital signals. A majority of parameters defined for the digital YCbCr
color space remains the same for the YPbPr color space used in the analog television
systems. YCbCr and YPbPr color spaces are closely related.
Individual color components of YCbCr color space are luma Y, chroma Cb and chroma Cr.
Chroma Cb corresponds to the U color component, and chroma Cr corresponds to the V
component of a general YUV color space.
According to the [1], [2] formulae for the direct conversion from RGB to YCbCb are the
following:
Y = Kry * R + Kgy * G + Kby * B
Cb = B – Y
Cr = R – Y
Kry + Kgy + Kby = 1
Y = Kry * R + Kgy * G + Kby * B
Cb = Kru * R + Kgu * G + Kbu * B
Cr = Krv * R + Kgv * G + Kbv * B
Where
Kru = -Kry
Kgu = -Kgy
Kbu = 1-Kby
Krv = 1–Kry
Kgv = -Kgy
Kbv = -Kby
Formulae for inverse conversion from YCbCr to RGB are the following:
R = Y + Cr
G = Y * Kyg – (Kby/Kgy) * Cb – (Kry/Kgy) * Cr
B = Y + Cb
Where
Kyg = 1
Kug = - Kby/Kgy
Kvg = - Kry/Kgy
All coefficients used in the above formulae can be calculated from the just 2 main
coefficients Kry and Kby. These 2 coefficients define a relative contribution of red
and blue color components in the total value of luma Y. These coefficients reflect a
relative sensitivity of human vision to the red and blue portions of a visible light.
At the same time, values of 2 main coefficients take in account colorimetric parameters
of image reproducing devices, such as a gamma function of displays.
-------------------------------------------------------------
Y = (Kry*R) + (Kgy*G) + (Kby*B)
Cb = -Kry*R - Kgy*G + (1-kby)*B
Cr = (1-Kry)*R - Kgy*G - Kby*B
Y = (Kry*R) + (Kgy*G) + (Kby*B)
Cb = -Kry*R/(1.0-Kby) - (Kgy*G/(1-Kby)) + B
Cr = R - (Kgy*G/(1-Kry)) - (Kby*B/(1-Kry))
Y - 16 = (Kry*219/255)*R + (Kgy*219/255)*G + (Kby*219/255)*B
U - 128 = - Kry*112/255*R/(1-Kby) - Kgy*112/255*G/(1-Kby) + 112/255*B
V - 128 = 112/255*R - Kgy*112/255*G/(1-Kry) - Kby*112/255*B/(1-Kry)
R = Y + Cr
G = Y – (Kby/Kgy) * Cb – (Kry/Kgy) * Cr
B = Y + Cb
' -----------------------------------------------------------------
y - 16 = (Kry*219/255)*R + (Kgy*219/255)*G + (Kby*219/255)*B
u - 128 = - Kry*112/255*R/(1-Kby) - Kgy*112/255*G/(1-Kby) + 112/255*B
v - 128 = 112/255*R - Kgy*112/255*G/(1-Kry) - Kby*112/255*B/(1-Kry)
Y = Y = 0.257R´ + 0.504G´ + 0.098B´ + 16
U = Cb = -0.148R´ - 0.291G´ + 0.439B´ + 128
V = Cr = 0.439R´ - 0.368G´ - 0.071B´ + 128
For i = 0 To 255
x(1, i) = 0.257 * i ' 0.299 * 219/255 = 0.25678 = 0.257 'Kry Upscale
x(2, i) = 0.504 * i ' 0.587 * 219/255 = 0.5041 = 0.504 'Kgy Upscale
x(3, i) = 0.098 * i ' 0.114 * 219/255 = 0.0979 = 0.098 'Kby Upscale
x(4, i) = 0.148 * i ' 0.299 * 112/255/(1-0.114) = 0.14822 = 0.148 (-minus)
x(5, i) = 0.291 * i ' 0.587 * 112/255/(1-0.114) = 0.29099 = 0.291 (-minus)
x(6, i) = 0.439 * i ' 112 / 255 = 0.4392 = 0.439
x(7, i) = 0.368 * i ' 0.299 * 112 / 255 / (1-0.299) = 0.3677 = 0.368
x(8, i) = 0.071 * i ' 0.114 * 112 / 255 / (1-0.299) = 0.7142 = 0.071
Next i
y -16 = (Kry * 219# / 255#) * R + (Kgy * 219# / 255#) * G + (Kby * 219# / 255#) * B
Kgy = 1 - Kry - Krb ' 0.587
Kru = -Kry ' -0.299
Kgu = -Kgy ' -0.587
Kbu = 1 - Kby ' 0.886
Krv = 1 - Kry ' 0.701
Kgv = -Kgy ' -0.587
Kbv = -Kby ' -0.114
The image is now converted in YUV and stored in the array.
The backwards process uses the following formulas to convert from YUV to RGB
' 1.164 = 255/219
R = 1.164(Y - 16) + 1.596(Cr - 128)
G = 1.164(Y - 16) - 0.813(Cr - 128) - 0.392(Cb - 128)
B = 1.164(Y - 16) + 2.017(Cb - 128)
Like before, we're going to build tables that will ease the process.
You will maybe notice that I start from 0 instead of 16 (Y,U,V start from 16), this is just to be on
the safe side. We're not trying to make the fastest and most optimized code here.
For i = 0 To 255
x(1, i) = 1.164 * (i - 16)
x(2, i) = 1.596 * (i - 128)
x(3, i) = 0.813 * (i - 128)
x(4, i) = 0.392 * (i - 128)
x(5, i) = 2.017 * (i - 128)
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.