Skip to content

Commit

Permalink
Merge pull request #188 from wysaid/master
Browse files Browse the repository at this point in the history
Add Bilateral Filter for Andorid-GPUImage
  • Loading branch information
wasabeef committed Sep 4, 2015
2 parents 2e78e97 + 5e7fd6c commit abd3dbe
Show file tree
Hide file tree
Showing 4 changed files with 179 additions and 5 deletions.
6 changes: 3 additions & 3 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ VERSION_NAME=1.2.3
VERSION_CODE=8
GROUP=jp.co.cyberagent.android.gpuimage

COMPILE_SDK_VERSION=21
BUILD_TOOLS_VERSION=21.1.2
TARGET_SDK_VERSION=21
COMPILE_SDK_VERSION=22
BUILD_TOOLS_VERSION=22.0.1
TARGET_SDK_VERSION=22
MIN_SDK_VERSION=8

POM_DESCRIPTION=Image filters for Android with OpenGL (based on GPUImage for iOS)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/**
* @author wysaid
* @mail [email protected]
*
*/

package jp.co.cyberagent.android.gpuimage;

import android.opengl.GLES20;


public class GPUImageBilateralFilter extends GPUImageFilter {
public static final String BILATERAL_VERTEX_SHADER = "" +
"attribute vec4 position;\n" +
"attribute vec4 inputTextureCoordinate;\n" +

"const int GAUSSIAN_SAMPLES = 9;\n" +

"uniform vec2 singleStepOffset;\n" +

"varying vec2 textureCoordinate;\n" +
"varying vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n" +

"void main()\n" +
"{\n" +
" gl_Position = position;\n" +
" textureCoordinate = inputTextureCoordinate.xy;\n" +

" int multiplier = 0;\n" +
" vec2 blurStep;\n" +

" for (int i = 0; i < GAUSSIAN_SAMPLES; i++)\n" +
" {\n" +
" multiplier = (i - ((GAUSSIAN_SAMPLES - 1) / 2));\n" +

" blurStep = float(multiplier) * singleStepOffset;\n" +
" blurCoordinates[i] = inputTextureCoordinate.xy + blurStep;\n" +
" }\n" +
"}";

public static final String BILATERAL_FRAGMENT_SHADER = "" +
"uniform sampler2D inputImageTexture;\n" +

" const lowp int GAUSSIAN_SAMPLES = 9;\n" +

" varying highp vec2 textureCoordinate;\n" +
" varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];\n" +

" uniform mediump float distanceNormalizationFactor;\n" +

" void main()\n" +
" {\n" +
" lowp vec4 centralColor;\n" +
" lowp float gaussianWeightTotal;\n" +
" lowp vec4 sum;\n" +
" lowp vec4 sampleColor;\n" +
" lowp float distanceFromCentralColor;\n" +
" lowp float gaussianWeight;\n" +
" \n" +
" centralColor = texture2D(inputImageTexture, blurCoordinates[4]);\n" +
" gaussianWeightTotal = 0.18;\n" +
" sum = centralColor * 0.18;\n" +
" \n" +
" sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +

" sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);\n" +
" distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);\n" +
" gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);\n" +
" gaussianWeightTotal += gaussianWeight;\n" +
" sum += sampleColor * gaussianWeight;\n" +
" gl_FragColor = sum / gaussianWeightTotal;\n" +
// " gl_FragColor.r = distanceNormalizationFactor / 20.0;" +
" }";

private float mDistanceNormalizationFactor;
private int mDisFactorLocation;
private int mSingleStepOffsetLocation;

public GPUImageBilateralFilter() {
this(8.0f);
}

public GPUImageBilateralFilter(final float distanceNormalizationFactor) {
super(BILATERAL_VERTEX_SHADER, BILATERAL_FRAGMENT_SHADER);
mDistanceNormalizationFactor = distanceNormalizationFactor;
}

@Override
public void onInit() {
super.onInit();
mDisFactorLocation = GLES20.glGetUniformLocation(getProgram(), "distanceNormalizationFactor");
mSingleStepOffsetLocation = GLES20.glGetUniformLocation(getProgram(), "singleStepOffset");
}

@Override
public void onInitialized() {
super.onInitialized();
setDistanceNormalizationFactor(mDistanceNormalizationFactor);
}

public void setDistanceNormalizationFactor(final float newValue) {
mDistanceNormalizationFactor = newValue;
setFloat(mDisFactorLocation, newValue);
}

private void setTexelSize(final float w, final float h) {
setFloatVec2(mSingleStepOffsetLocation, new float[] {1.0f / w, 1.0f / h});
}

@Override
public void onOutputSizeChanged(final int width, final int height) {
super.onOutputSizeChanged(width, height);
setTexelSize(width, height);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ private void convertToBitmap() {
mGL.glReadPixels(0, 0, mWidth, mHeight, GL_RGBA, GL_UNSIGNED_BYTE, ib);
int[] ia = ib.array();

//Stupid !
// Convert upside down mirror-reversed image to right-side up normal
// image.
for (int i = 0; i < mHeight; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ public static void showDialog(final Context context,

filters.addFilter("Levels Min (Mid Adjust)", FilterType.LEVELS_FILTER_MIN);

filters. addFilter("Bilateral Blur", FilterType.BILATERAL_BLUR);


AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle("Choose a filter");
builder.setItems(filters.names.toArray(new String[filters.names.size()]),
Expand Down Expand Up @@ -287,6 +290,9 @@ private static GPUImageFilter createFilterForType(final Context context, final F
levelsFilter.setMin(0.0f, 3.0f, 1.0f);
return levelsFilter;

case BILATERAL_BLUR:
return new GPUImageBilateralFilter();

default:
throw new IllegalStateException("No filter of that type!");
}
Expand Down Expand Up @@ -314,7 +320,7 @@ private enum FilterType {
BLEND_DISSOLVE, BLEND_EXCLUSION, BLEND_SOURCE_OVER, BLEND_HARD_LIGHT, BLEND_LIGHTEN, BLEND_ADD, BLEND_DIVIDE, BLEND_MULTIPLY, BLEND_OVERLAY, BLEND_SCREEN, BLEND_ALPHA,
BLEND_COLOR, BLEND_HUE, BLEND_SATURATION, BLEND_LUMINOSITY, BLEND_LINEAR_BURN, BLEND_SOFT_LIGHT, BLEND_SUBTRACT, BLEND_CHROMA_KEY, BLEND_NORMAL, LOOKUP_AMATORKA,
GAUSSIAN_BLUR, CROSSHATCH, BOX_BLUR, CGA_COLORSPACE, DILATION, KUWAHARA, RGB_DILATION, SKETCH, TOON, SMOOTH_TOON, BULGE_DISTORTION, GLASS_SPHERE, HAZE, LAPLACIAN, NON_MAXIMUM_SUPPRESSION,
SPHERE_REFRACTION, SWIRL, WEAK_PIXEL_INCLUSION, FALSE_COLOR, COLOR_BALANCE, LEVELS_FILTER_MIN
SPHERE_REFRACTION, SWIRL, WEAK_PIXEL_INCLUSION, FALSE_COLOR, COLOR_BALANCE, LEVELS_FILTER_MIN, BILATERAL_BLUR
}

private static class FilterList {
Expand Down Expand Up @@ -389,7 +395,11 @@ public FilterAdjuster(final GPUImageFilter filter) {
adjuster = new ColorBalanceAdjuster().filter(filter);
} else if (filter instanceof GPUImageLevelsFilter) {
adjuster = new LevelsMinMidAdjuster().filter(filter);
} else {
} else if (filter instanceof GPUImageBilateralFilter) {
adjuster = new BilateralAdjuster().filter(filter);
}
else {

adjuster = null;
}
}
Expand Down Expand Up @@ -643,5 +653,13 @@ public void adjust(int percentage) {
getFilter().setMin(0.0f, range(percentage, 0.0f, 1.0f) , 1.0f);
}
}

private class BilateralAdjuster extends Adjuster<GPUImageBilateralFilter> {
@Override
public void adjust(final int percentage) {
getFilter().setDistanceNormalizationFactor(range(percentage, 0.0f, 15.0f));
}
}

}
}

0 comments on commit abd3dbe

Please sign in to comment.