用Shader实现的YUV到RGB转换:使用3重纹理实现
2008-12-22 13:06
465 查看
上一篇中,我是用一个RGB格式的纹理来存储每一帧的画面,其中纹理为m_FrameWidth * m_FrameHeight大小,这样,在内存中,就必须要先对YUV的数据进行排序,然后才能当做RGB的数据格式传给纹理内存。我们发现对一个很大帧的图片进行数据重新排序会花费很多时间,为了减少这个时间,当然可以用汇编语言来进行这个排序的操作。然而,有一种更好的方法。
我们发现在上一次所用到的YUV420数据格式是一种平面格式,他的数据排列十分有规律,这里,考虑用3重纹理来实现他的转换。
先定义3个纹理,格式都为GL_LUMINANCE格式,其中一个纹理的大小为m_FrameWidth * m_FrameHeight,这是用来存放Y数据的,另两个纹理的大小为(m_FrameWidth / 2) * (m_FrameHeight / 2),分别用来存放U和V数据。好啦,我们可以直接使用内存拷贝memcpy()函数分别将YUV的数据拷出来,再生成纹理。
那么frame shader中的程序就要改成:
uniform sampler2D yTexture;
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main()
{
float yuv0 = (texture2D(yTexture,gl_TexCoord[0].st)).r;
float yuv1 = (texture2D(uTexture,gl_TexCoord[0].st)).r;
float yuv2 = (texture2D(vTexture,gl_TexCoord[0].st)).r;
vec4 color;
color.r = yuv0 + 1.4022 * yuv2 - 0.7011;
color.r = (color.r < 0.0) ? 0.0 : ((color.r > 1.0) ? 1.0 : color.r);
color.g = yuv0 - 0.3456 * yuv1 - 0.7145 * yuv2 + 0.53005;
color.g = (color.g < 0.0) ? 0.0 : ((color.g > 1.0) ? 1.0 : color.g);
color.b = yuv0 + 1.771 * yuv1 - 0.8855;
color.b = (color.b < 0.0) ? 0.0 : ((color.b > 1.0) ? 1.0 : color.b);
gl_FragColor = color;
}
其中需要注意的两点是:
1: uniform的值是要在每次绘制前调用的。
m_loc=glGetUniformLocation(m_Program,"yTexture");
glUniform1i(m_loc,0); /* Bind Utex to texture unit 1 */
m_loc=glGetUniformLocation(m_Program,"uTexture");
glUniform1i(m_loc,1); /* Bind Utex to texture unit 1 */
m_loc=glGetUniformLocation(m_Program,"vTexture");
glUniform1i(m_loc,2); /* Bind Utex to texture unit 1 */
m_Program就是shader的程序。
2:在使用shader和多重纹理之前,都要进行初始化:glewInit();
另外补上用汇编语言实现重排序的代码:
int m = m_FrameWidth * m_FrameHeight;
int l = (m_FrameWidth / 2) * (m_FrameHeight / 2);
unsigned char * pyuv = m_y;
unsigned char * ptemp = cTemp[0];
__asm
{
mov ecx, m
mov ebx, ptemp
mov edx, pyuv
label_y:
mov al, [ebx]
mov [edx], al
add ebx, 1
add edx, 1
dec ecx
jnz label_y
}
pyuv = m_u;
ptemp = cTemp[1];
__asm
{
mov ecx, l
mov ebx, ptemp
mov edx, pyuv
label_u:
mov ah, [ebx]
mov [edx], ah
add ebx, 1
add edx, 1
dec ecx
jnz label_u
}
pyuv = m_v;
ptemp = cTemp[2];
__asm
{
mov ecx, l
mov ebx, ptemp
mov edx, pyuv
label_v:
mov al, [ebx]
mov [edx], al
add ebx, 1
add edx, 1
dec ecx
jnz label_v
}
我们发现在上一次所用到的YUV420数据格式是一种平面格式,他的数据排列十分有规律,这里,考虑用3重纹理来实现他的转换。
先定义3个纹理,格式都为GL_LUMINANCE格式,其中一个纹理的大小为m_FrameWidth * m_FrameHeight,这是用来存放Y数据的,另两个纹理的大小为(m_FrameWidth / 2) * (m_FrameHeight / 2),分别用来存放U和V数据。好啦,我们可以直接使用内存拷贝memcpy()函数分别将YUV的数据拷出来,再生成纹理。
那么frame shader中的程序就要改成:
uniform sampler2D yTexture;
uniform sampler2D uTexture;
uniform sampler2D vTexture;
void main()
{
float yuv0 = (texture2D(yTexture,gl_TexCoord[0].st)).r;
float yuv1 = (texture2D(uTexture,gl_TexCoord[0].st)).r;
float yuv2 = (texture2D(vTexture,gl_TexCoord[0].st)).r;
vec4 color;
color.r = yuv0 + 1.4022 * yuv2 - 0.7011;
color.r = (color.r < 0.0) ? 0.0 : ((color.r > 1.0) ? 1.0 : color.r);
color.g = yuv0 - 0.3456 * yuv1 - 0.7145 * yuv2 + 0.53005;
color.g = (color.g < 0.0) ? 0.0 : ((color.g > 1.0) ? 1.0 : color.g);
color.b = yuv0 + 1.771 * yuv1 - 0.8855;
color.b = (color.b < 0.0) ? 0.0 : ((color.b > 1.0) ? 1.0 : color.b);
gl_FragColor = color;
}
其中需要注意的两点是:
1: uniform的值是要在每次绘制前调用的。
m_loc=glGetUniformLocation(m_Program,"yTexture");
glUniform1i(m_loc,0); /* Bind Utex to texture unit 1 */
m_loc=glGetUniformLocation(m_Program,"uTexture");
glUniform1i(m_loc,1); /* Bind Utex to texture unit 1 */
m_loc=glGetUniformLocation(m_Program,"vTexture");
glUniform1i(m_loc,2); /* Bind Utex to texture unit 1 */
m_Program就是shader的程序。
2:在使用shader和多重纹理之前,都要进行初始化:glewInit();
另外补上用汇编语言实现重排序的代码:
int m = m_FrameWidth * m_FrameHeight;
int l = (m_FrameWidth / 2) * (m_FrameHeight / 2);
unsigned char * pyuv = m_y;
unsigned char * ptemp = cTemp[0];
__asm
{
mov ecx, m
mov ebx, ptemp
mov edx, pyuv
label_y:
mov al, [ebx]
mov [edx], al
add ebx, 1
add edx, 1
dec ecx
jnz label_y
}
pyuv = m_u;
ptemp = cTemp[1];
__asm
{
mov ecx, l
mov ebx, ptemp
mov edx, pyuv
label_u:
mov ah, [ebx]
mov [edx], ah
add ebx, 1
add edx, 1
dec ecx
jnz label_u
}
pyuv = m_v;
ptemp = cTemp[2];
__asm
{
mov ecx, l
mov ebx, ptemp
mov edx, pyuv
label_v:
mov al, [ebx]
mov [edx], al
add ebx, 1
add edx, 1
dec ecx
jnz label_v
}
相关文章推荐
- 图像处理之基础---用Shader实现的YUV到RGB转换:使用3重纹理实现 .
- 使用Shader实现YUV到RGB的转换
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 如何做YUV的分辨率转换 - FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- OpenCV提供的转换函数实现YUV到RGB的转换
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- DSP48E1的使用,实现RGB转YUV空间(1)---一步一步做图像拼接
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- RGB,CMY(K),YUV,YIQ,YCbCr颜色的转换算法(java实现)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- 视频教程:YUV和RGB相互转换--MATLAB实现(一)
- 图片颜色处理/ 关于RGB转换YUV的探讨与实现
- 【OpenGL】用OpenGL shader实现将YUV(YUV420,YV12)转RGB-(直接调用GPU实现,纯硬件方式,效率高) 这段时间一直在搞视频格式的转换问题,终于最近将一个图片的YUV
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)
- OpenCV实现RGB与YUV的转换
- ffmpeg命令行实现YUV和RGB之间格式的转换
- (原创)用verilog实现RGB格式图像到YCbCr或YUV格式的转换及其验证方法 (RGB2YCrCb)(RGB2YUV)
- FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)