使用opengl繪製yuv

weixin_30278311發表於2019-01-15

首先提出一個公式,yuv轉換為rgb的公式:

如果把 RGB 和YUV 的範圍都放縮到 [0,255][0,255],那麼常用的轉換公式是這樣的。 

R=Y+1.403x(V-128)
G=Y-0.343x(U-128)-0.714x(V-128)
B=Y+1.770x(U-128)
 
如果把RGB和YUV的範圍都放縮到[0,1][0,1],則公式為
R=Y+1.403x(V-0.5)
G=Y-0.343x(U-0.5)-0.714x(V-0.5)
B=Y+1.770x(U-0.5)
 
有一些誤差,從網上找了一個調整過的公式:
R=Y+1.13983*(V-0.5)
G=Y-0.39465*(U-0.5)-0.58060*(V-0.5)
B=Y+2.03211*(U-0.5)
 
如果源的格式為YUV420,YUV422,YUV444。因為Y,U,V都是集中儲存,當將Y,U,V對映為原始影像寬高的二維圖片時,每個圖片的r,g,b,a的值與Y,U,V的值相同,故取出r值組成向量,則為寬x高的大小。
比如1920x1080,則通過texture2D方法後,我們得到的點陣圖均為1920x1080,相應的y被擴充4倍,u和v被擴充16倍,由於u和v本身是y的1/4,所以u和v的資料量擴充的和y相同。
通過texture2D函式,我們可以得到每個畫素的Y,U,V,他們的長度是相等的。再根據YUV轉RGB的公式,就可以得到RGB的值,設定透明度返回,則交給opengl繪製出影像
opengl的shader設定為:

static const char* S_f_shader_yuv4xx1 =
"varying lowp vec2 v_texCoord;\
uniform sampler2D tex_y;\
uniform sampler2D tex_u;\
uniform sampler2D tex_v;\
void main(void)\
{\
float r, g, b, y, u, v;\
y = texture2D(tex_y, v_texCoord).r;\
u = texture2D(tex_u, v_texCoord).r - 0.5;\
v = texture2D(tex_v, v_texCoord).r - 0.5;\
r = y + 1.13983*v;\
g = y - 0.39465*u - 0.58060*v;\
b = y + 2.03211*u;\
gl_FragColor = vec4(r, g, b, 1.0);\
}";

 

如果為NV12,其排列方式為Y集中排列,UV交錯排列

YYYYUVUV

根據這種交錯的性質,UV當成一個整體來看,則恰好是Y的1/2,讓其寬度增大2倍,則恰好模擬情形應該如下:

A    R   G   B

U0 V0 U0 V0

所以需要將UV作為一個整體,給OpenGL,設定寬度為width/2,高度為height,則R為V0,A為U0

static const char* S_f_shader_nv12 =
"precision highp float;\
varying vec2 v_texCoord;\
uniform sampler2D tex_y;\
uniform sampler2D tex_u;\
void main (void){\
float r, g, b, y, u, v;\
y = texture2D(tex_y, v_texCoord).r;\
u = texture2D(tex_u, v_texCoord).a - 0.5;\
v = texture2D(tex_u, v_texCoord).r - 0.5;\
r = y + 1.13983*v;\
g = y - 0.39465*u - 0.58060*v;\
b = y + 2.03211*u;\
gl_FragColor = vec4(r, g, b, 1.0);\
}";

 

 

 

轉載於:https://www.cnblogs.com/limedia/p/opengl_draw_yuv.html

相關文章