android-gpuimage里給出了很多濾鏡效果啥供,本質(zhì)都是用shader處理圖像囱桨。這里分析幾個(gè)比較有特點(diǎn)的谎亩。
完整代碼查看https://github.com/andev009/AndroidShaderDemo中的SharpRender 。
1、灰度圖像
通過改變亮度將一副彩色圖像變成灰色圖像。根據(jù)sRGB規(guī)范,亮度被定義成紅,綠握牧,藍(lán)的線性組合,sRGB中基于亮度值的權(quán)值向量為
vec3(0.2125, 0.7154, 0.0721),向量rgb與權(quán)值向量的點(diǎn)積就是亮度值娩梨。
灰度圖像的rgb值都為亮度值沿腰。在圖像處理的過程中,如果要先取得灰度圖像狈定,都是先這樣處理颂龙。
void main()
{
mediump vec3 textureColor = texture2D(u_TextureUnit0, v_TextureCoordinates).rgb;
float luminance = dot(textureColor.rgb, W);
gl_FragColor = vec4(vec3(luminance), 1.0);
}
2、圖像卷積(圖像銳化)
卷積的作用很多纽什,可以做銳化措嵌,模糊等。卷積最好的理解就是一個(gè)3X3矩陣和圖像上的像素點(diǎn)點(diǎn)積,當(dāng)然也可以定義5X5這些矩陣稿湿。卷積具體的概念就不解釋了铅匹,重點(diǎn)看如何應(yīng)用押赊,這里分析圖像銳化饺藤,gpuimage銳化(sharp filter)的3X3矩陣沒有明確定義,不過分析下shader流礁,可知矩陣如下:
float kernelValues[9]=float[9] (
0, -2, 0,
-2, 9, -2,
0, -2, 0
);
知道了卷積矩陣后涕俗,還需要取得當(dāng)前像素的上下左右像素的rgb值,這樣才能和矩陣點(diǎn)積神帅。要取得上下左右的像素rgb值再姑,就要取得上下左右的像素的紋理坐標(biāo)。紋理坐標(biāo)在shader里的取值范圍是[0 ,1]找御,因此紋理坐標(biāo)的長(zhǎng)寬步長(zhǎng)分別為:
widthFactor = 1.0f / width//width就是顯示圖像控件GLSurfaceView的寬度
heightFactor = 1.0f / height//height就是顯示圖像控件GLSurfaceView的高度
將widthFactor元镀,和heightFactor傳到vertex shader里绍填,在vertex shader里u_imageWidthFactor,u_imageHeightFactor就是長(zhǎng)寬步長(zhǎng)栖疑。
這樣就可以在vertex shader里取得上下左右的紋理坐標(biāo)值:
v_TextureCoordinates = a_TextureCoordinates;//當(dāng)前紋理坐標(biāo)
mediump vec2 widthHeightStep = vec2(u_imageWidthFactor, u_imageHeightFactor);
mediump vec2 widthNegativeHeightStep = vec2(u_imageWidthFactor, -u_imageHeightFactor);
v_leftTextureCoordinate = a_TextureCoordinates - widthStep;
v_rightTextureCoordinate = a_TextureCoordinates + widthStep;
v_topTextureCoordinate = a_TextureCoordinates + heightStep;
v_bottomTextureCoordinate = a_TextureCoordinates - heightStep;
將上下左右紋理坐標(biāo)傳到fragment shader里讨永,就能取得上下左右像素的rgb值了。
mediump vec3 textureColor = texture2D(u_TextureUnit0, v_TextureCoordinates).rgb;//當(dāng)前像素rgb
mediump vec3 leftTextureColor = texture2D(u_TextureUnit0, v_leftTextureCoordinate).rgb;
mediump vec3 rightTextureColor = texture2D(u_TextureUnit0, v_rightTextureCoordinate).rgb;
mediump vec3 topTextureColor = texture2D(u_TextureUnit0, v_topTextureCoordinate).rgb;
mediump vec3 bottomTextureColor = texture2D(u_TextureUnit0, v_bottomTextureCoordinate).rgb;
最后用卷積矩陣點(diǎn)積計(jì)算最終rgb值
mediump vec3 aroundColor = leftTextureColor * 2.0 + rightTextureColor * 2.0 +
topTextureColor * 2.0 + bottomTextureColor * 2.0;
mediump vec3 finalColor = textureColor * 9.0 - aroundColor;