package com.marshalchen.common.uimodule.imageprocessing.filter.processing; import com.marshalchen.common.uimodule.imageprocessing.filter.TwoPassMultiPixelFilter; import android.opengl.GLES20; /** * A bilateral blur, which tries to blur similar color values while preserving sharp edges * blurSize: A multiplier for the size of the blur, ranging from 0.0 on up * distanceNormalizationFactor: A normalization factor for the distance between central color and sample color * @author Chris Batt */ public class BilateralBlurFilter extends TwoPassMultiPixelFilter { private static final String UNIFORM_DISTANCE_NORMALIZATION = "u_DistanceNormalization"; private int distanceNormalizationHandle; private float distanceNormalization; public BilateralBlurFilter(float distanceNormalizationFactor) { this.distanceNormalization = distanceNormalizationFactor; } @Override protected String getFragmentShader() { return "precision mediump float;\n" +"uniform sampler2D "+UNIFORM_TEXTURE0+";\n" +"varying vec2 "+VARYING_TEXCOORD+";\n" +"uniform float "+UNIFORM_DISTANCE_NORMALIZATION+";\n" +"uniform float "+UNIFORM_TEXELWIDTH+";\n" +"uniform float "+UNIFORM_TEXELHEIGHT+";\n" +"void main(){\n" +" vec2 singleStepOffset = vec2("+UNIFORM_TEXELWIDTH+", "+UNIFORM_TEXELHEIGHT+");\n" +" int multiplier = 0;\n" +" vec2 blurStep = vec2(0,0);\n" +" vec2 blurCoordinates[9];" +" for(int i = 0; i < 9; i++) {\n" +" multiplier = (i - 4);\n" +" blurStep = float(multiplier) * singleStepOffset;\n" +" blurCoordinates[i] = "+VARYING_TEXCOORD+".xy + blurStep;\n" +" }\n" +" vec4 centralColor;\n" +" float gaussianWeightTotal;\n" +" vec4 sum;\n" +" vec4 sampleColor;\n" +" float distanceFromCentralColor;\n" +" float gaussianWeight;\n" +" centralColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[4]);\n" +" gaussianWeightTotal = 0.18;\n" +" sum = centralColor * 0.18;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[0]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[1]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[2]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[3]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[5]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[6]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[7]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" sampleColor = texture2D("+UNIFORM_TEXTURE0+", blurCoordinates[8]);\n" +" distanceFromCentralColor = min(distance(centralColor, sampleColor) * "+UNIFORM_DISTANCE_NORMALIZATION+", 1.0);\n" +" gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" +" gaussianWeightTotal += gaussianWeight;\n" +" sum += sampleColor * gaussianWeight;\n" +" gl_FragColor = sum / gaussianWeightTotal;\n" +"}\n"; } @Override protected void initShaderHandles() { super.initShaderHandles(); distanceNormalizationHandle = GLES20.glGetUniformLocation(programHandle, UNIFORM_DISTANCE_NORMALIZATION); } @Override protected void passShaderValues() { super.passShaderValues(); GLES20.glUniform1f(distanceNormalizationHandle, distanceNormalization); } }