这段时间一直在搞视频格式的转换问题,终于最近将一个图片的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";
</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),每天清晨,我们将为您送上精选历史故事一篇以及点评。
扫描下面二维码即可加关注: