|
|
@ -1,20 +1,37 @@ |
|
|
|
package com.otaliastudios.cameraview.filters; |
|
|
|
package com.otaliastudios.cameraview.filters; |
|
|
|
|
|
|
|
|
|
|
|
import android.graphics.Color; |
|
|
|
import android.graphics.Color; |
|
|
|
|
|
|
|
import android.opengl.GLES20; |
|
|
|
|
|
|
|
|
|
|
|
import androidx.annotation.ColorInt; |
|
|
|
import androidx.annotation.ColorInt; |
|
|
|
import androidx.annotation.NonNull; |
|
|
|
import androidx.annotation.NonNull; |
|
|
|
|
|
|
|
|
|
|
|
import com.otaliastudios.cameraview.filter.BaseFilter; |
|
|
|
import com.otaliastudios.cameraview.filter.BaseFilter; |
|
|
|
|
|
|
|
import com.otaliastudios.cameraview.internal.GlUtils; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Representation of input frames using only two color tones. |
|
|
|
* Representation of input frames using only two color tones. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class DuotoneFilter extends BaseFilter { |
|
|
|
public class DuotoneFilter extends BaseFilter { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final static String FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n" |
|
|
|
|
|
|
|
+ "precision mediump float;\n" |
|
|
|
|
|
|
|
+ "uniform samplerExternalOES sTexture;\n" |
|
|
|
|
|
|
|
+ "uniform vec3 first;\n" |
|
|
|
|
|
|
|
+ "uniform vec3 second;\n" |
|
|
|
|
|
|
|
+ "varying vec2 vTextureCoord;\n" |
|
|
|
|
|
|
|
+ "void main() {\n" |
|
|
|
|
|
|
|
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n" |
|
|
|
|
|
|
|
+ " float energy = (color.r + color.g + color.b) * 0.3333;\n" |
|
|
|
|
|
|
|
+ " vec3 new_color = (1.0 - energy) * first + energy * second;\n" |
|
|
|
|
|
|
|
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" |
|
|
|
|
|
|
|
+ "}\n"; |
|
|
|
|
|
|
|
|
|
|
|
// Default values
|
|
|
|
// Default values
|
|
|
|
private int mFirstColor = Color.MAGENTA; |
|
|
|
private int mFirstColor = Color.MAGENTA; |
|
|
|
private int mSecondColor = Color.YELLOW; |
|
|
|
private int mSecondColor = Color.YELLOW; |
|
|
|
|
|
|
|
private int mFirstColorLocation = -1; |
|
|
|
|
|
|
|
private int mSecondColorLocation = -1; |
|
|
|
|
|
|
|
|
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
@SuppressWarnings("WeakerAccess") |
|
|
|
public DuotoneFilter() { } |
|
|
|
public DuotoneFilter() { } |
|
|
@ -58,7 +75,7 @@ public class DuotoneFilter extends BaseFilter { |
|
|
|
* @see #setFirstColor(int) |
|
|
|
* @see #setFirstColor(int) |
|
|
|
* @return first |
|
|
|
* @return first |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@SuppressWarnings("unused") |
|
|
|
@SuppressWarnings({"unused", "WeakerAccess"}) |
|
|
|
@ColorInt |
|
|
|
@ColorInt |
|
|
|
public int getFirstColor() { |
|
|
|
public int getFirstColor() { |
|
|
|
return mFirstColor; |
|
|
|
return mFirstColor; |
|
|
@ -70,57 +87,57 @@ public class DuotoneFilter extends BaseFilter { |
|
|
|
* @see #setSecondColor(int) |
|
|
|
* @see #setSecondColor(int) |
|
|
|
* @return second |
|
|
|
* @return second |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
@SuppressWarnings("unused") |
|
|
|
@SuppressWarnings({"unused", "WeakerAccess"}) |
|
|
|
@ColorInt |
|
|
|
@ColorInt |
|
|
|
public int getSecondColor() { |
|
|
|
public int getSecondColor() { |
|
|
|
return mSecondColor; |
|
|
|
return mSecondColor; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
protected BaseFilter onCopy() { |
|
|
|
|
|
|
|
DuotoneFilter filter = new DuotoneFilter(); |
|
|
|
|
|
|
|
filter.setColors(mFirstColor, mSecondColor); |
|
|
|
|
|
|
|
return filter; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@NonNull |
|
|
|
@NonNull |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public String getFragmentShader() { |
|
|
|
public String getFragmentShader() { |
|
|
|
float[] first = {Color.red(mFirstColor) / 255f, |
|
|
|
return FRAGMENT_SHADER; |
|
|
|
Color.green(mFirstColor) / 255f, Color.blue(mFirstColor) / 255f}; |
|
|
|
} |
|
|
|
float[] second = {Color.red(mSecondColor) / 255f, |
|
|
|
|
|
|
|
Color.green(mSecondColor) / 255f, |
|
|
|
|
|
|
|
Color.blue(mSecondColor) / 255f}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String[] firstColorString = new String[3]; |
|
|
|
@Override |
|
|
|
String[] secondColorString = new String[3]; |
|
|
|
public void onCreate(int programHandle) { |
|
|
|
|
|
|
|
super.onCreate(programHandle); |
|
|
|
|
|
|
|
mFirstColorLocation = GLES20.glGetUniformLocation(programHandle, "first"); |
|
|
|
|
|
|
|
GlUtils.checkLocation(mFirstColorLocation, "first"); |
|
|
|
|
|
|
|
mSecondColorLocation = GLES20.glGetUniformLocation(programHandle, "second"); |
|
|
|
|
|
|
|
GlUtils.checkLocation(mSecondColorLocation, "second"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
firstColorString[0] = "first[0] = " + first[0] + ";\n"; |
|
|
|
@Override |
|
|
|
firstColorString[1] = "first[1] = " + first[1] + ";\n"; |
|
|
|
protected void onPreDraw(float[] transformMatrix) { |
|
|
|
firstColorString[2] = "first[2] = " + first[2] + ";\n"; |
|
|
|
super.onPreDraw(transformMatrix); |
|
|
|
|
|
|
|
float[] first = new float[]{ |
|
|
|
|
|
|
|
Color.red(mFirstColor) / 255f, |
|
|
|
|
|
|
|
Color.green(mFirstColor) / 255f, |
|
|
|
|
|
|
|
Color.blue(mFirstColor) / 255f |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
float[] second = new float[]{ |
|
|
|
|
|
|
|
Color.red(mSecondColor) / 255f, |
|
|
|
|
|
|
|
Color.green(mSecondColor) / 255f, |
|
|
|
|
|
|
|
Color.blue(mSecondColor) / 255f |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
GLES20.glUniform3fv(mFirstColorLocation, 1, first, 0); |
|
|
|
|
|
|
|
GLES20.glUniform3fv(mSecondColorLocation, 1, second, 0); |
|
|
|
|
|
|
|
GlUtils.checkError("glUniform3fv"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
secondColorString[0] = "second[0] = " + second[0] + ";\n"; |
|
|
|
@Override |
|
|
|
secondColorString[1] = "second[1] = " + second[1] + ";\n"; |
|
|
|
public void onDestroy() { |
|
|
|
secondColorString[2] = "second[2] = " + second[2] + ";\n"; |
|
|
|
super.onDestroy(); |
|
|
|
|
|
|
|
mFirstColorLocation = -1; |
|
|
|
|
|
|
|
mSecondColorLocation = -1; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return "#extension GL_OES_EGL_image_external : require\n" |
|
|
|
@Override |
|
|
|
+ "precision mediump float;\n" |
|
|
|
protected BaseFilter onCopy() { |
|
|
|
+ "uniform samplerExternalOES sTexture;\n" |
|
|
|
DuotoneFilter filter = new DuotoneFilter(); |
|
|
|
+ "vec3 first;\n" |
|
|
|
filter.setColors(getFirstColor(), getSecondColor()); |
|
|
|
+ "vec3 second;\n" |
|
|
|
return filter; |
|
|
|
+ "varying vec2 vTextureCoord;\n" |
|
|
|
|
|
|
|
+ "void main() {\n" |
|
|
|
|
|
|
|
// Parameters that were created above
|
|
|
|
|
|
|
|
+ firstColorString[0] |
|
|
|
|
|
|
|
+ firstColorString[1] |
|
|
|
|
|
|
|
+ firstColorString[2] |
|
|
|
|
|
|
|
+ secondColorString[0] |
|
|
|
|
|
|
|
+ secondColorString[1] |
|
|
|
|
|
|
|
+ secondColorString[2] |
|
|
|
|
|
|
|
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n" |
|
|
|
|
|
|
|
+ " float energy = (color.r + color.g + color.b) * 0.3333;\n" |
|
|
|
|
|
|
|
+ " vec3 new_color = (1.0 - energy) * first + energy * second;\n" |
|
|
|
|
|
|
|
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" |
|
|
|
|
|
|
|
+ "}\n"; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|