zoukankan      html  css  js  c++  java
  • 图像处理之基础---用Shader实现的YUV到RGB转换:使用3重纹理实现 .

         

    上一篇中,我是用一个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.     }
  • 相关阅读:
    k8s service定义与创建
    k8s service存在的意义
    k8s job控制器-执行一次性任务
    k8s CronJob定时任务
    k8s Daemonset功能
    k8s deployment控制器Replicaset
    k8s deployment删除
    k8s deployment控制器水平扩容
    k8s deployment发布失败回滚
    k8s deployment控制器:滚动升级 平滑过渡 零停机
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/4042126.html
Copyright © 2011-2022 走看看