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

这段时间一直在搞视频格式的转换问题,终于最近将一个图片的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),每天清晨,我们将为您送上精选历史故事一篇以及点评。

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


 
 

  • 1
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 27
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值