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);
}
}