Android基于Shader的图像处理(7)-颜色表LUT
2018-11-15 本文已影响54人
andev009
完整代码查看# AndroidShaderDemo下的LUTActivity
颜色表LUT(LookUp Table)主要用于滤镜,详细原理讲解参考这里《iOS 针对 LUT 滤镜的实现对比》。这里说下应用和注意的地方。
颜色表LUT在这里用上面的图片,加载后当做lut纹理使用,用原本的RGB值去查找这个lut纹理得到最终的RGB值,所以这里有两个纹理,一个是originTexture表示本来图片,一个是lutTexture表示lut纹理。
LUTActivity里面是用LUTRender在GLSurfaceView上绘制。
和普通render不同之处在fragment shader。fragment shader的原理就是根据RGB在lut纹理里查找新的RGB。这里参考GPUImage里代码,位于lut_fragment_shader.glsl:
vec4 lookup(in vec4 textureColor){
mediump float blueColor = textureColor.b * 63.0;
mediump vec2 quad1;
quad1.y = floor(floor(blueColor) / 8.0);
quad1.x = floor(blueColor) - (quad1.y * 8.0);
mediump vec2 quad2;
quad2.y = floor(ceil(blueColor) / 8.0);
quad2.x = ceil(blueColor) - (quad2.y * 8.0);
highp vec2 texPos1;
texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
highp vec2 texPos2;
texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);
texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);
lowp vec4 newColor1 = texture2D(u_TextureUnit1, texPos1);
lowp vec4 newColor2 = texture2D(u_TextureUnit1, texPos2);
lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));
return newColor;
}
以上就是应用,网上很多文章讲解就到此为止。但是值得注意的是LUT纹理生成和普通纹理生成不一样,如果用之前的生成纹理代码,得到的图片会有各种密密麻麻的黑点,这些黑点就是插值出现问题,找不到LUT上的坐标,而查找LUT时我们需要找临近点而不是插值。这里就不贴生成的错误图片了。纹理加载代码是:
originTexture = TextureHelper.loadTexture(context, R.drawable.lena);
lutTexture = TextureHelper.loadLutTexture(context, R.drawable.fairy_tale);
想测试看下错误的图片效果,把下面的loadLutTexture改成loadTexture就行了。这两个方法主要区别在于生成纹理时选择的滤波参数。loadLutTexture用的是:
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
最后结果:
image_lut.png