博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图像处理之基础---用Shader实现的YUV到RGB转换:使用3重纹理实现 .
阅读量:6210 次
发布时间:2019-06-21

本文共 2110 字,大约阅读时间需要 7 分钟。

     

上一篇中,我是用一个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中的程序就要改成:

  1. uniform sampler2D yTexture;
  2. uniform sampler2D uTexture;
  3. uniform sampler2D vTexture;
  4. void main()
  5. {
  6.     float yuv0 = (texture2D(yTexture,gl_TexCoord[0].st)).r;
  7.     float yuv1 = (texture2D(uTexture,gl_TexCoord[0].st)).r;
  8.     float yuv2 = (texture2D(vTexture,gl_TexCoord[0].st)).r;
  9.     vec4 color;
  10.     
  11.     color.r = yuv0 + 1.4022 * yuv2 - 0.7011;
  12.     color.r = (color.r < 0.0) ? 0.0 : ((color.r > 1.0) ? 1.0 : color.r);
  13.     color.g = yuv0 - 0.3456 * yuv1 - 0.7145 * yuv2 + 0.53005;
  14.     color.g = (color.g < 0.0) ? 0.0 : ((color.g > 1.0) ? 1.0 : color.g);
  15.     color.b = yuv0 + 1.771 * yuv1 - 0.8855;
  16.     color.b = (color.b < 0.0) ? 0.0 : ((color.b > 1.0) ? 1.0 : color.b);
  17.     gl_FragColor = color;
  18. }

    其中需要注意的两点是:

    1: uniform的值是要在每次绘制前调用的。

 

  1.     m_loc=glGetUniformLocation(m_Program,"yTexture");
  2.     glUniform1i(m_loc,0);  /* Bind Utex to texture unit 1 */
  3.     m_loc=glGetUniformLocation(m_Program,"uTexture");
  4.     glUniform1i(m_loc,1);  /* Bind Utex to texture unit 1 */
  5.     m_loc=glGetUniformLocation(m_Program,"vTexture");
  6.     glUniform1i(m_loc,2);  /* Bind Utex to texture unit 1 */

    m_Program就是shader的程序。

    2:在使用shader和多重纹理之前,都要进行初始化:glewInit();

  1.     int m = m_FrameWidth * m_FrameHeight;
  2.     int l = (m_FrameWidth / 2) * (m_FrameHeight / 2);
  3.     unsigned char * pyuv = m_y;
  4.     unsigned char * ptemp = cTemp[0];
  5.     __asm
  6.     {
  7.         mov ecx, m
  8.         mov ebx, ptemp
  9.         mov edx, pyuv
  10. label_y:
  11.         mov al, [ebx]
  12.         mov [edx], al
  13.         add ebx, 1
  14.         add edx, 1
  15.         dec ecx
  16.         jnz label_y
  17.     }
  18.     
  19.     pyuv = m_u;
  20.     ptemp = cTemp[1];
  21.     __asm
  22.     {
  23.         mov ecx, l
  24.         mov ebx, ptemp
  25.         mov edx, pyuv
  26. label_u:
  27.         mov ah, [ebx]
  28.         mov [edx], ah
  29.         add ebx, 1
  30.         add edx, 1
  31.         dec ecx
  32.         jnz label_u
  33.     }
  34.     pyuv = m_v;
  35.     ptemp = cTemp[2];
  36.     __asm
  37.     {
  38.         mov ecx, l
  39.         mov ebx, ptemp
  40.         mov edx, pyuv
  41. label_v:
  42.         mov al, [ebx]
  43.         mov [edx], al
  44.         add ebx, 1
  45.         add edx, 1
  46.         dec ecx
  47.         jnz label_v
  48.     }

转载地址:http://nidja.baihongyu.com/

你可能感兴趣的文章
(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)
查看>>
spring security原理图及其解释
查看>>
Redis安全
查看>>
17秋 软件工程 团队第五次作业 Alpha Scrum9
查看>>
DIV和SPAN的区别
查看>>
Jodd
查看>>
处理 Windows 虚拟机的计划内维护通知
查看>>
redis资料收集
查看>>
CNN中的局部连接(Sparse Connectivity)和权值共享
查看>>
UNIX域套接字编程和socketpair 函数
查看>>
[LeetCode] Set Intersection Size At Least Two 设置交集大小至少为2
查看>>
Maven update project...后jdk变成1.5,update project后jdk版本改变
查看>>
Android 关于BottomDialogSheet 与Layout擦出爱的火花?
查看>>
【docker】启动docker连接数据库 出现FATAL: password authentucation failed for user "homestatead"问题...
查看>>
python二维数组初始化
查看>>
eclipse 如何修改maven插件本地仓库jar包默认存储位置
查看>>
Zookeeper浏览器工具和Eclipse插件
查看>>
【WPF】UI虚拟化之------自定义VirtualizingWrapPanel
查看>>
银行卡的三个磁道【转】
查看>>
Linux中添加、修改和删除用户和用户组
查看>>