OpenGL ES:rgb转换yuv

qq群里有兄弟讨论使用gles rgb转换yuv问题,刚刚好前段时间我花了两天时间抄袭修改过,代码简单粗暴,如下:

const GLchar *strVertexShaderRgb2Yuv =
    "attribute vec4 position;\n"
    "attribute vec4 inputTextureCoordinate;\n"
    "\n"
    "varying vec2 textureCoordinate;\n"
    "\n"
    "void main()\n"
    "{\n"
    "    gl_Position = position;\n"
    "    textureCoordinate = inputTextureCoordinate.xy;\n"
    "}\n";

const GLchar *strFragmentShaderRgb2Yuv =
    "precision highp float;\n"
    "\n"
    "varying vec2 textureCoordinate;\n"
    "\n"
    "uniform sampler2D inputImageTexture;\n"
    "uniform float uWidth;\n"
    "uniform float uHeight;\n"
    "\n"
    "float cY(float x, float y)\n"
    "{\n"
    "    vec4 c = texture2D(inputImageTexture, vec2(x, y));\n"
    "    return c.r * 0.257 + c.g * 0.504 + c.b * 0.098 + 0.0625;\n"
    "}\n"
    "\n"
    "vec4 cC(float x, float y, float dx, float dy)\n"
    "{\n"
    "    vec4 c0 = texture2D(inputImageTexture, vec2(x, y));\n"
    "    vec4 c1 = texture2D(inputImageTexture, vec2(x + dx, y));\n"
    "    vec4 c2 = texture2D(inputImageTexture, vec2(x, y + dy));\n"
    "    vec4 c3 = texture2D(inputImageTexture, vec2(x + dx, y + dy));\n"
    "    return (c0 + c1 + c2 + c3) / 4.0;\n"
    "}\n"
    "\n"
    "float cU(float x, float y, float dx, float dy)\n"
    "{\n"
    "    vec4 c = cC(x, y, dx, dy);\n"
    "    return -0.148 * c.r - 0.291 * c.g + 0.439 * c.b + 0.5000;\n"
    "}\n"
    "\n"
    "float cV(float x, float y, float dx, float dy)\n"
    "{\n"
    "    vec4 c = cC(x, y, dx, dy);\n"
    "    return 0.439 * c.r - 0.368 * c.g - 0.071 * c.b + 0.5000;\n"
    "}\n"
    "\n"
    "vec4 calculateY(float x, float y, float dx, float dy)\n"
    "{\n"
    "    vec4 c = vec4(0.0);\n"
    "    c[0] = cY(x, y);\n"
    "    c[1] = cY(x + 1.0 * dx, y);\n"
    "    c[2] = cY(x + 2.0 * dx, y);\n"
    "    c[3] = cY(x + 3.0 * dx, y);\n"
    "    return c;\n"
    "}\n"
    "\n"
    "vec4 calculateU(float x, float y, float dx, float dy)\n"
    "{\n"
    "    vec4 c = vec4(0.0);\n"
    "    c[0] = cU(x, y, dx, dy);\n"
    "    c[1] = cU(x + 2.0 * dx, y, dx, dy);\n"
    "    c[2] = cU(x + 4.0 * dx, y, dx, dy);\n"
    "    c[3] = cU(x + 6.0 * dx, y, dx, dy);\n"
    "    return c;\n"
    "}\n"
    "\n"
    "vec4 calculateV(float x, float y, float dx, float dy)\n"
    "{\n"
    "    vec4 c = vec4(0.0);\n"
    "    c[0] = cV(x, y, dx, dy);\n"
    "    c[1] = cV(x + 2.0 * dx, y, dx, dy);\n"
    "    c[2] = cV(x + 4.0 * dx, y, dx, dy);\n"
    "    c[3] = cV(x + 6.0 * dx, y, dx, dy);\n"
    "    return c;\n"
    "}\n"
    "\n"
    "void main()\n"
    "{\n"
    "    if (textureCoordinate.y > 0.375) {\n"
    "       return;\n"
    "    }\n"
    "\n"
    "    float y4xSum = uWidth * uHeight / 4.0;\n"
    "    float u4xSum = uWidth * uHeight / 16.0;\n"
    "    float v4xSum = uWidth * uHeight / 16.0;\n"
    "    float yuv4xOffset = floor(textureCoordinate.y * uHeight) * uWidth + floor(textureCoordinate.x * uWidth);\n"
    "\n"
    "    if (yuv4xOffset < y4xSum) {\n"
    "        float yOffset = yuv4xOffset * 4.0 + 1.0;\n"
    "        float yX = floor(mod(yOffset, uWidth));\n"
    "        float yY = floor(yOffset / uWidth);\n"
    "        yY = uHeight - yY;\n"
    "        gl_FragColor = calculateY(yX / uWidth, yY / uHeight, 1.0 / uWidth, 1.0 / uHeight);\n"
    "    } else if (yuv4xOffset < (y4xSum + u4xSum)) {\n"
    "        float uOffset = (yuv4xOffset - y4xSum) * 4.0 + 1.0;\n"
    "        float uX = floor(mod(uOffset, uWidth / 2.0)) * 2.0;\n"
    "        float uY = floor(uOffset / (uWidth / 2.0)) * 2.0;\n"
    "        uY = uHeight - uY - 1.0;\n"
    "        gl_FragColor = calculateU(uX / uWidth, uY / uHeight, 1.0 / uWidth, 1.0 / uHeight);\n"
    "    } else if (yuv4xOffset < (y4xSum + u4xSum + v4xSum)) {\n"
    "        float vOffset = (yuv4xOffset - y4xSum - u4xSum) * 4.0 + 1.0;\n"
    "        float vX = floor(mod(vOffset, uWidth / 2.0)) * 2.0;\n"
    "        float vY = floor(vOffset / (uWidth / 2.0)) * 2.0;\n"
    "        vY = uHeight - vY - 1.0;\n"
    "        gl_FragColor = calculateV(vX / uWidth, vY / uHeight, 1.0 / uWidth, 1.0 / uHeight);\n"
    "    }\n"
    "}\n";

缺点

  • 空间浪费:只用了 framebuffer 3/8
  • 分辨率限制为8的倍数
  • rgb到yuv的转换公式写死,不够灵活

参考文章:湖广午王的博客该链接已失效,可见(https://www.jishux.com/p/518a2b6653e09e43)
YUV to RGB Conversion

你可能感兴趣的:(OpenGL ES:rgb转换yuv)