您的位置:首页 > 运维架构

【OpenGL】用OpenGL shader实现将YUV转RGB-(直接调用GPU实现,纯硬件方式,效率高)

2013-03-14 13:42 399 查看
这段时间一直在搞视频格式的转换问题,终于最近将一个图片的YUV格式转RGB格式转换成功了。下面就来介绍一下:

由于我的工程是在vs2008中的,其中包含一些相关头文件和库,所以下面只是列出部分核心代码,并不是全部代码。

1、下载一个包含YUV数据的文件也可以自己制作一个该文件

下载地址:YUV数据文件

2、读入YUV数据文件中的yuv数据:

关键代码如下:

2.1读文件代码

unsigned char * readYUV(char *path)
{

FILE *fp;
unsigned char * buffer;
long size = 1280 * 720 * 3 / 2;

if((fp=fopen(path,"rb"))==NULL)
{
printf("cant open the file");
exit(0);
}

buffer = new unsigned char[size];
memset(buffer,'\0',size);
fread(buffer,size,1,fp);
fclose(fp);
return buffer;
}

2.2读入数据,并将YUV数据分别制作成3个纹理

GLuint texYId;
GLuint texUId;
GLuint texVId;

void loadYUV(){
int width ;
int	height ;

width = 640;
height = 480;

unsigned char *buffer = NULL;
buffer = readYUV("1.yuv");

glGenTextures ( 1, &texYId );
glBindTexture ( GL_TEXTURE_2D, texYId );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

glGenTextures ( 1, &texUId );
glBindTexture ( GL_TEXTURE_2D, texUId );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer + width * height);
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

glGenTextures ( 1, &texVId );
glBindTexture ( GL_TEXTURE_2D, texVId );
glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, width / 2, height / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer + width * height * 5 / 4 );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );

}


上述代码中1.yuv就是YUV数据文件

3、将纹理传入OpenGL shader进行显示

</pre></h1><h2>3.1 顶点shader和片段shader代码</h2><div><pre name="code" class="cpp"> GLbyte vShaderStr[] =
"attribute vec4 vPosition;    \n"
"attribute vec2 a_texCoord;	\n"
"varying vec2 tc;		\n"
"void main()                  \n"
"{                            \n"
"   gl_Position = vPosition;  \n"
"	  tc = a_texCoord;	\n"
"}                            \n";

GLbyte fShaderStr[] =
"precision mediump float;\n"
"uniform sampler2D tex_y;					\n"
"uniform sampler2D tex_u;					\n"
"uniform sampler2D tex_v;					\n"
"varying vec2 tc;							\n"
"void main()                                  \n"
"{                                            \n"
"  vec4 c = vec4((texture2D(tex_y, tc).r - 16./255.) * 1.164);\n"
"  vec4 U = vec4(texture2D(tex_u, tc).r - 128./255.);\n"
"  vec4 V = vec4(texture2D(tex_v, tc).r - 128./255.);\n"
"  c += V * vec4(1.596, -0.813, 0, 0);\n"
"  c += U * vec4(0, -0.392, 2.017, 0);\n"
"  c.a = 1.0;\n"
"  gl_FragColor = c;\n"
"}                                            \n";

上述片段shader中就是根据yuv转rgb的公式得来的。也就是说是在shader中实现转换的。

4、显示结果

结果如下:



注意:该shader是OpenGL ES格式的,与OpenGL格式的shader有一点差别。

欢迎关注我的微信公众号“中华文化精选”(微信号:goto_china),每天清晨,我们将为您送上精选历史故事一篇以及点评。

扫描下面二维码即可加关注:




                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐