/*
* Copyright (C) 2012 CyberAgent
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jp.co.cyberagent.android.gpuimage;
/**
* For each pixel, this sets it to the maximum value of the red channel in a rectangular neighborhood extending
* out dilationRadius pixels from the center.
* This extends out bright features, and is most commonly used with black-and-white thresholded images.
*/
public class GPUImageDilationFilter extends GPUImageTwoPassTextureSamplingFilter {
public static final String VERTEX_SHADER_1 =
"attribute vec4 position;\n" +
"attribute vec2 inputTextureCoordinate;\n" +
"\n" +
"uniform float texelWidthOffset; \n" +
"uniform float texelHeightOffset; \n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"\n" +
"void main()\n" +
"{\n" +
"gl_Position = position;\n" +
"\n" +
"vec2 offset = vec2(texelWidthOffset, texelHeightOffset);\n" +
"\n" +
"centerTextureCoordinate = inputTextureCoordinate;\n" +
"oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;\n" +
"oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;\n" +
"}\n";
public static final String VERTEX_SHADER_2 =
"attribute vec4 position;\n" +
"attribute vec2 inputTextureCoordinate;\n" +
"\n" +
"uniform float texelWidthOffset;\n" +
"uniform float texelHeightOffset;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"varying vec2 twoStepsPositiveTextureCoordinate;\n" +
"varying vec2 twoStepsNegativeTextureCoordinate;\n" +
"\n" +
"void main()\n" +
"{\n" +
"gl_Position = position;\n" +
"\n" +
"vec2 offset = vec2(texelWidthOffset, texelHeightOffset);\n" +
"\n" +
"centerTextureCoordinate = inputTextureCoordinate;\n" +
"oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;\n" +
"oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;\n" +
"twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);\n" +
"twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);\n" +
"}\n";
public static final String VERTEX_SHADER_3 =
"attribute vec4 position;\n" +
"attribute vec2 inputTextureCoordinate;\n" +
"\n" +
"uniform float texelWidthOffset;\n" +
"uniform float texelHeightOffset;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"varying vec2 twoStepsPositiveTextureCoordinate;\n" +
"varying vec2 twoStepsNegativeTextureCoordinate;\n" +
"varying vec2 threeStepsPositiveTextureCoordinate;\n" +
"varying vec2 threeStepsNegativeTextureCoordinate;\n" +
"\n" +
"void main()\n" +
"{\n" +
"gl_Position = position;\n" +
"\n" +
"vec2 offset = vec2(texelWidthOffset, texelHeightOffset);\n" +
"\n" +
"centerTextureCoordinate = inputTextureCoordinate;\n" +
"oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;\n" +
"oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;\n" +
"twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);\n" +
"twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);\n" +
"threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0);\n" +
"threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0);\n" +
"}\n";
public static final String VERTEX_SHADER_4 =
"attribute vec4 position;\n" +
"attribute vec2 inputTextureCoordinate;\n" +
"\n" +
"uniform float texelWidthOffset;\n" +
"uniform float texelHeightOffset;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"varying vec2 twoStepsPositiveTextureCoordinate;\n" +
"varying vec2 twoStepsNegativeTextureCoordinate;\n" +
"varying vec2 threeStepsPositiveTextureCoordinate;\n" +
"varying vec2 threeStepsNegativeTextureCoordinate;\n" +
"varying vec2 fourStepsPositiveTextureCoordinate;\n" +
"varying vec2 fourStepsNegativeTextureCoordinate;\n" +
"\n" +
"void main()\n" +
"{\n" +
"gl_Position = position;\n" +
"\n" +
"vec2 offset = vec2(texelWidthOffset, texelHeightOffset);\n" +
"\n" +
"centerTextureCoordinate = inputTextureCoordinate;\n" +
"oneStepNegativeTextureCoordinate = inputTextureCoordinate - offset;\n" +
"oneStepPositiveTextureCoordinate = inputTextureCoordinate + offset;\n" +
"twoStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 2.0);\n" +
"twoStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 2.0);\n" +
"threeStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 3.0);\n" +
"threeStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 3.0);\n" +
"fourStepsNegativeTextureCoordinate = inputTextureCoordinate - (offset * 4.0);\n" +
"fourStepsPositiveTextureCoordinate = inputTextureCoordinate + (offset * 4.0);\n" +
"}\n";
public static final String FRAGMENT_SHADER_1 =
"precision lowp float;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"void main()\n" +
"{\n" +
"float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;\n" +
"float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;\n" +
"float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;\n" +
"\n" +
"lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);\n" +
"maxValue = max(maxValue, oneStepNegativeIntensity);\n" +
"\n" +
"gl_FragColor = vec4(vec3(maxValue), 1.0);\n" +
"}\n";
public static final String FRAGMENT_SHADER_2 =
"precision lowp float;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"varying vec2 twoStepsPositiveTextureCoordinate;\n" +
"varying vec2 twoStepsNegativeTextureCoordinate;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"void main()\n" +
"{\n" +
"float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;\n" +
"float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;\n" +
"float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;\n" +
"float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;\n" +
"float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;\n" +
"\n" +
"lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);\n" +
"maxValue = max(maxValue, oneStepNegativeIntensity);\n" +
"maxValue = max(maxValue, twoStepsPositiveIntensity);\n" +
"maxValue = max(maxValue, twoStepsNegativeIntensity);\n" +
"\n" +
"gl_FragColor = vec4(vec3(maxValue), 1.0);\n" +
"}\n";
public static final String FRAGMENT_SHADER_3 =
"precision lowp float;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"varying vec2 twoStepsPositiveTextureCoordinate;\n" +
"varying vec2 twoStepsNegativeTextureCoordinate;\n" +
"varying vec2 threeStepsPositiveTextureCoordinate;\n" +
"varying vec2 threeStepsNegativeTextureCoordinate;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"void main()\n" +
"{\n" +
"float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;\n" +
"float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;\n" +
"float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;\n" +
"float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;\n" +
"float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;\n" +
"float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;\n" +
"float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;\n" +
"\n" +
"lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);\n" +
"maxValue = max(maxValue, oneStepNegativeIntensity);\n" +
"maxValue = max(maxValue, twoStepsPositiveIntensity);\n" +
"maxValue = max(maxValue, twoStepsNegativeIntensity);\n" +
"maxValue = max(maxValue, threeStepsPositiveIntensity);\n" +
"maxValue = max(maxValue, threeStepsNegativeIntensity);\n" +
"\n" +
"gl_FragColor = vec4(vec3(maxValue), 1.0);\n" +
"}\n";
public static final String FRAGMENT_SHADER_4 =
"precision lowp float;\n" +
"\n" +
"varying vec2 centerTextureCoordinate;\n" +
"varying vec2 oneStepPositiveTextureCoordinate;\n" +
"varying vec2 oneStepNegativeTextureCoordinate;\n" +
"varying vec2 twoStepsPositiveTextureCoordinate;\n" +
"varying vec2 twoStepsNegativeTextureCoordinate;\n" +
"varying vec2 threeStepsPositiveTextureCoordinate;\n" +
"varying vec2 threeStepsNegativeTextureCoordinate;\n" +
"varying vec2 fourStepsPositiveTextureCoordinate;\n" +
"varying vec2 fourStepsNegativeTextureCoordinate;\n" +
"\n" +
"uniform sampler2D inputImageTexture;\n" +
"\n" +
"void main()\n" +
"{\n" +
"float centerIntensity = texture2D(inputImageTexture, centerTextureCoordinate).r;\n" +
"float oneStepPositiveIntensity = texture2D(inputImageTexture, oneStepPositiveTextureCoordinate).r;\n" +
"float oneStepNegativeIntensity = texture2D(inputImageTexture, oneStepNegativeTextureCoordinate).r;\n" +
"float twoStepsPositiveIntensity = texture2D(inputImageTexture, twoStepsPositiveTextureCoordinate).r;\n" +
"float twoStepsNegativeIntensity = texture2D(inputImageTexture, twoStepsNegativeTextureCoordinate).r;\n" +
"float threeStepsPositiveIntensity = texture2D(inputImageTexture, threeStepsPositiveTextureCoordinate).r;\n" +
"float threeStepsNegativeIntensity = texture2D(inputImageTexture, threeStepsNegativeTextureCoordinate).r;\n" +
"float fourStepsPositiveIntensity = texture2D(inputImageTexture, fourStepsPositiveTextureCoordinate).r;\n" +
"float fourStepsNegativeIntensity = texture2D(inputImageTexture, fourStepsNegativeTextureCoordinate).r;\n" +
"\n" +
"lowp float maxValue = max(centerIntensity, oneStepPositiveIntensity);\n" +
"maxValue = max(maxValue, oneStepNegativeIntensity);\n" +
"maxValue = max(maxValue, twoStepsPositiveIntensity);\n" +
"maxValue = max(maxValue, twoStepsNegativeIntensity);\n" +
"maxValue = max(maxValue, threeStepsPositiveIntensity);\n" +
"maxValue = max(maxValue, threeStepsNegativeIntensity);\n" +
"maxValue = max(maxValue, fourStepsPositiveIntensity);\n" +
"maxValue = max(maxValue, fourStepsNegativeIntensity);\n" +
"\n" +
"gl_FragColor = vec4(vec3(maxValue), 1.0);\n" +
"}\n";
public GPUImageDilationFilter() {
this(1);
}
/**
* Acceptable values for dilationRadius, which sets the distance in pixels to sample out from the center,
* are 1, 2, 3, and 4.
*
* @param radius 1, 2, 3 or 4
*/
public GPUImageDilationFilter(int radius) {
this(getVertexShader(radius), getFragmentShader(radius));
}
private GPUImageDilationFilter(String vertexShader, String fragmentShader) {
super(vertexShader, fragmentShader, vertexShader, fragmentShader);
}
private static String getVertexShader(int radius) {
switch (radius) {
case 0:
case 1:
return VERTEX_SHADER_1;
case 2:
return VERTEX_SHADER_2;
case 3:
return VERTEX_SHADER_3;
default:
return VERTEX_SHADER_4;
}
}
private static String getFragmentShader(int radius) {
switch (radius) {
case 0:
case 1:
return FRAGMENT_SHADER_1;
case 2:
return FRAGMENT_SHADER_2;
case 3:
return FRAGMENT_SHADER_3;
default:
return FRAGMENT_SHADER_4;
}
}
}