/*
* 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;
/**
* Converts the image to a single-color version, based on the luminance of each pixel
* intensity: The degree to which the specific color replaces the normal image color (0.0 - 1.0, with 1.0 as the default)
* color: The color to use as the basis for the effect, with (0.6, 0.45, 0.3, 1.0) as the default.
*/
public class GPUImageMonochromeFilter extends GPUImageFilter {
public static final String MONOCHROME_FRAGMENT_SHADER = "" +
" precision lowp float;\n" +
" \n" +
" varying highp vec2 textureCoordinate;\n" +
" \n" +
" uniform sampler2D inputImageTexture;\n" +
" uniform float intensity;\n" +
" uniform vec3 filterColor;\n" +
" \n" +
" const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);\n" +
" \n" +
" void main()\n" +
" {\n" +
" //desat, then apply overlay blend\n" +
" lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);\n" +
" float luminance = dot(textureColor.rgb, luminanceWeighting);\n" +
" \n" +
" lowp vec4 desat = vec4(vec3(luminance), 1.0);\n" +
" \n" +
" //overlay\n" +
" lowp vec4 outputColor = vec4(\n" +
" (desat.r < 0.5 ? (2.0 * desat.r * filterColor.r) : (1.0 - 2.0 * (1.0 - desat.r) * (1.0 - filterColor.r))),\n" +
" (desat.g < 0.5 ? (2.0 * desat.g * filterColor.g) : (1.0 - 2.0 * (1.0 - desat.g) * (1.0 - filterColor.g))),\n" +
" (desat.b < 0.5 ? (2.0 * desat.b * filterColor.b) : (1.0 - 2.0 * (1.0 - desat.b) * (1.0 - filterColor.b))),\n" +
" 1.0\n" +
" );\n" +
" \n" +
" //which is better, or are they equal?\n" +
" gl_FragColor = vec4( mix(textureColor.rgb, outputColor.rgb, intensity), textureColor.a);\n" +
" }";
private int mIntensityLocation;
private float mIntensity;
private int mFilterColorLocation;
private float[] mColor;
public GPUImageMonochromeFilter() {
this(1.0f, new float[] {0.6f, 0.45f, 0.3f, 1.0f});
}
public GPUImageMonochromeFilter(final float intensity, final float[] color) {
super(NO_FILTER_VERTEX_SHADER, MONOCHROME_FRAGMENT_SHADER);
mIntensity = intensity;
mColor = color;
}
@Override
public void onInit() {
super.onInit();
mIntensityLocation = GLES20.glGetUniformLocation(getProgram(), "intensity");
mFilterColorLocation = GLES20.glGetUniformLocation(getProgram(), "filterColor");
}
@Override
public void onInitialized() {
super.onInitialized();
setIntensity(1.0f);
setColor(new float[]{ 0.6f, 0.45f, 0.3f, 1.f });
}
public void setIntensity(final float intensity) {
mIntensity = intensity;
setFloat(mIntensityLocation, mIntensity);
}
public void setColor(final float[] color) {
mColor = color;
setColorRed(mColor[0], mColor[1], mColor[2]);
}
public void setColorRed(final float red, final float green, final float blue) {
setFloatVec3(mFilterColorLocation, new float[]{ red, green, blue });
}
}