/* * 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; import android.opengl.GLES20; /** * This uses Sobel edge detection to place a black border around objects, * and then it quantizes the colors present in the image to give a cartoon-like quality to the image. */ public class GPUImageToonFilter extends GPUImage3x3TextureSamplingFilter { public static final String TOON_FRAGMENT_SHADER = "" + "precision highp float;\n" + "\n" + "varying vec2 textureCoordinate;\n" + "varying vec2 leftTextureCoordinate;\n" + "varying vec2 rightTextureCoordinate;\n" + "\n" + "varying vec2 topTextureCoordinate;\n" + "varying vec2 topLeftTextureCoordinate;\n" + "varying vec2 topRightTextureCoordinate;\n" + "\n" + "varying vec2 bottomTextureCoordinate;\n" + "varying vec2 bottomLeftTextureCoordinate;\n" + "varying vec2 bottomRightTextureCoordinate;\n" + "\n" + "uniform sampler2D inputImageTexture;\n" + "\n" + "uniform highp float intensity;\n" + "uniform highp float threshold;\n" + "uniform highp float quantizationLevels;\n" + "\n" + "const highp vec3 W = vec3(0.2125, 0.7154, 0.0721);\n" + "\n" + "void main()\n" + "{\n" + "vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" + "\n" + "float bottomLeftIntensity = texture2D(inputImageTexture, bottomLeftTextureCoordinate).r;\n" + "float topRightIntensity = texture2D(inputImageTexture, topRightTextureCoordinate).r;\n" + "float topLeftIntensity = texture2D(inputImageTexture, topLeftTextureCoordinate).r;\n" + "float bottomRightIntensity = texture2D(inputImageTexture, bottomRightTextureCoordinate).r;\n" + "float leftIntensity = texture2D(inputImageTexture, leftTextureCoordinate).r;\n" + "float rightIntensity = texture2D(inputImageTexture, rightTextureCoordinate).r;\n" + "float bottomIntensity = texture2D(inputImageTexture, bottomTextureCoordinate).r;\n" + "float topIntensity = texture2D(inputImageTexture, topTextureCoordinate).r;\n" + "float h = -topLeftIntensity - 2.0 * topIntensity - topRightIntensity + bottomLeftIntensity + 2.0 * bottomIntensity + bottomRightIntensity;\n" + "float v = -bottomLeftIntensity - 2.0 * leftIntensity - topLeftIntensity + bottomRightIntensity + 2.0 * rightIntensity + topRightIntensity;\n" + "\n" + "float mag = length(vec2(h, v));\n" + "\n" + "vec3 posterizedImageColor = floor((textureColor.rgb * quantizationLevels) + 0.5) / quantizationLevels;\n" + "\n" + "float thresholdTest = 1.0 - step(threshold, mag);\n" + "\n" + "gl_FragColor = vec4(posterizedImageColor * thresholdTest, textureColor.a);\n" + "}\n"; float mThreshold; int mThresholdLocation; float mQuantizationLevels; int mQuantizationLevelsLocation; public GPUImageToonFilter() { this(0.2f, 10.0f); } public GPUImageToonFilter(float threshold, float quantizationLevels) { super(TOON_FRAGMENT_SHADER); mThreshold = threshold; mQuantizationLevels = quantizationLevels; } @Override public void onInit() { super.onInit(); mThresholdLocation = GLES20.glGetUniformLocation(getProgram(), "threshold"); mQuantizationLevelsLocation = GLES20.glGetUniformLocation(getProgram(), "quantizationLevels"); } @Override public void onInitialized() { super.onInitialized(); setThreshold(mThreshold); setQuantizationLevels(mQuantizationLevels); } /** * The threshold at which to apply the edges, default of 0.2. * * @param threshold default 0.2 */ public void setThreshold(final float threshold) { mThreshold = threshold; setFloat(mThresholdLocation, threshold); } /** * The levels of quantization for the posterization of colors within the scene, with a default of 10.0. * * @param quantizationLevels default 10.0 */ public void setQuantizationLevels(final float quantizationLevels) { mQuantizationLevels = quantizationLevels; setFloat(mQuantizationLevelsLocation, quantizationLevels); } }