Update all filters with onPreDraw

pull/535/head
Mattia Iavarone 6 years ago
parent c4118ab3f9
commit fce6597364
  1. 113
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/SharpnessFilter.java
  2. 77
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/TemperatureFilter.java
  3. 89
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/TintFilter.java
  4. 132
      cameraview/src/main/java/com/otaliastudios/cameraview/filters/VignetteFilter.java

@ -1,17 +1,49 @@
package com.otaliastudios.cameraview.filters;
import android.opengl.GLES20;
import androidx.annotation.NonNull;
import com.otaliastudios.cameraview.filter.BaseFilter;
import com.otaliastudios.cameraview.internal.GlUtils;
/**
* Sharpens the input frames.
*/
public class SharpnessFilter 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 float scale;\n"
+ "uniform float stepsizeX;\n"
+ "uniform float stepsizeY;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " vec3 nbr_color = vec3(0.0, 0.0, 0.0);\n"
+ " vec2 coord;\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " coord.x = vTextureCoord.x - 0.5 * stepsizeX;\n"
+ " coord.y = vTextureCoord.y - stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x - stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y - 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " gl_FragColor = vec4(color.rgb - 2.0 * scale * nbr_color, color.a);\n"
+ "}\n";
private float scale = 0.5f;
private int mOutputWidth = 1;
private int mOutputHeight = 1;
private int width = 1;
private int height = 1;
private int scaleLocation = -1;
private int stepSizeXLocation = -1;
private int stepSizeYLocation = -1;
@SuppressWarnings("WeakerAccess")
public SharpnessFilter() { }
@ -19,8 +51,8 @@ public class SharpnessFilter extends BaseFilter {
@Override
public void setSize(int width, int height) {
super.setSize(width, height);
mOutputWidth = width;
mOutputHeight = height;
this.width = width;
this.height = height;
}
/**
@ -48,50 +80,45 @@ public class SharpnessFilter extends BaseFilter {
return scale;
}
@Override
protected BaseFilter onCopy() {
SharpnessFilter filter = new SharpnessFilter();
filter.setSharpness(getSharpness());
return filter;
}
@NonNull
@Override
public String getFragmentShader() {
String stepsizeXString = "stepsizeX = " + 1.0f / mOutputWidth + ";\n";
String stepsizeYString = "stepsizeY = " + 1.0f / mOutputHeight + ";\n";
String scaleString = "scale = " + scale + ";\n";
return FRAGMENT_SHADER;
}
return "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float scale;\n"
+ " float stepsizeX;\n"
+ " float stepsizeY;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ stepsizeXString
+ stepsizeYString
+ scaleString
+ " vec3 nbr_color = vec3(0.0, 0.0, 0.0);\n"
+ " vec2 coord;\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " coord.x = vTextureCoord.x - 0.5 * stepsizeX;\n"
+ " coord.y = vTextureCoord.y - stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x - stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y - 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " coord.x = vTextureCoord.x + stepsizeX;\n"
+ " coord.y = vTextureCoord.y + 0.5 * stepsizeY;\n"
+ " nbr_color += texture2D(sTexture, coord).rgb - color.rgb;\n"
+ " gl_FragColor = vec4(color.rgb - 2.0 * scale * nbr_color, color.a);\n"
+ "}\n";
@Override
public void onCreate(int programHandle) {
super.onCreate(programHandle);
scaleLocation = GLES20.glGetUniformLocation(programHandle, "scale");
GlUtils.checkLocation(scaleLocation, "scale");
stepSizeXLocation = GLES20.glGetUniformLocation(programHandle, "stepsizeX");
GlUtils.checkLocation(stepSizeXLocation, "stepsizeX");
stepSizeYLocation = GLES20.glGetUniformLocation(programHandle, "stepsizeY");
GlUtils.checkLocation(stepSizeYLocation, "stepsizeY");
}
@Override
public void onDestroy() {
super.onDestroy();
scaleLocation = -1;
stepSizeXLocation = -1;
stepSizeYLocation = -1;
}
@Override
protected void onPreDraw(float[] transformMatrix) {
super.onPreDraw(transformMatrix);
GLES20.glUniform1f(scaleLocation, scale);
GlUtils.checkError("glUniform1f");
GLES20.glUniform1f(stepSizeXLocation, 1.0F / width);
GlUtils.checkError("glUniform1f");
GLES20.glUniform1f(stepSizeYLocation, 1.0F / height);
GlUtils.checkError("glUniform1f");
}
@Override
protected BaseFilter onCopy() {
SharpnessFilter filter = new SharpnessFilter();
filter.setSharpness(getSharpness());
return filter;
}
}

@ -1,15 +1,39 @@
package com.otaliastudios.cameraview.filters;
import android.opengl.GLES20;
import androidx.annotation.NonNull;
import com.otaliastudios.cameraview.filter.BaseFilter;
import com.otaliastudios.cameraview.internal.GlUtils;
/**
* Adjusts color temperature.
*/
public class TemperatureFilter 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 float scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " vec3 new_color = color.rgb;\n"
+ " new_color.r = color.r + color.r * ( 1.0 - color.r) * scale;\n"
+ " new_color.b = color.b - color.b * ( 1.0 - color.b) * scale;\n"
+ " if (scale > 0.0) { \n"
+ " new_color.g = color.g + color.g * ( 1.0 - color.g) * scale * 0.25;\n"
+ " }\n"
+ " float max_value = max(new_color.r, max(new_color.g, new_color.b));\n"
+ " if (max_value > 1.0) { \n"
+ " new_color /= max_value;\n"
+ " } \n"
+ " gl_FragColor = vec4(new_color, color.a);\n"
+ "}\n";
private float scale = 0f;
private int scaleLocation = -1;
@SuppressWarnings("WeakerAccess")
public TemperatureFilter() { }
@ -40,37 +64,36 @@ public class TemperatureFilter extends BaseFilter {
return scale;
}
@NonNull
@Override
protected BaseFilter onCopy() {
TemperatureFilter filter = new TemperatureFilter();
filter.setTemperature(getTemperature());
return filter;
public String getFragmentShader() {
return FRAGMENT_SHADER;
}
@NonNull
@Override
public String getFragmentShader() {
String scaleString = "scale = " + (2.0f * scale - 1.0f) + ";\n";
return "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "float scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n" // Parameters that were created above
+ scaleString
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " vec3 new_color = color.rgb;\n"
+ " new_color.r = color.r + color.r * ( 1.0 - color.r) * scale;\n"
+ " new_color.b = color.b - color.b * ( 1.0 - color.b) * scale;\n"
+ " if (scale > 0.0) { \n"
+ " new_color.g = color.g + color.g * ( 1.0 - color.g) * scale * 0.25;\n"
+ " }\n"
+ " float max_value = max(new_color.r, max(new_color.g, new_color.b));\n"
+ " if (max_value > 1.0) { \n"
+ " new_color /= max_value;\n"
+ " } \n"
+ " gl_FragColor = vec4(new_color, color.a);\n"
+ "}\n";
public void onCreate(int programHandle) {
super.onCreate(programHandle);
scaleLocation = GLES20.glGetUniformLocation(programHandle, "scale");
GlUtils.checkLocation(scaleLocation, "scale");
}
@Override
public void onDestroy() {
super.onDestroy();
scaleLocation = -1;
}
@Override
protected void onPreDraw(float[] transformMatrix) {
super.onPreDraw(transformMatrix);
GLES20.glUniform1f(scaleLocation, (2.0f * scale - 1.0f));
GlUtils.checkError("glUniform1f");
}
@Override
protected BaseFilter onCopy() {
TemperatureFilter filter = new TemperatureFilter();
filter.setTemperature(getTemperature());
return filter;
}
}

@ -1,18 +1,37 @@
package com.otaliastudios.cameraview.filters;
import android.graphics.Color;
import android.opengl.GLES20;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import com.otaliastudios.cameraview.filter.BaseFilter;
import com.otaliastudios.cameraview.internal.GlUtils;
/**
* Tints the frames with specified color.
*/
public class TintFilter extends BaseFilter {
private int mTint = 0xFFFF0000;
private final static String FRAGMENT_SHADER = "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ "uniform vec3 tint;\n"
+ "vec3 color_ratio;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " color_ratio[0] = " + 0.21f + ";\n"
+ " color_ratio[1] = " + 0.71f + ";\n"
+ " color_ratio[2] = " + 0.07f + ";\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float avg_color = dot(color_ratio, color.rgb);\n"
+ " vec3 new_color = min(0.8 * avg_color + 0.2 * tint, 1.0);\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" + "}\n";
private int tint = Color.RED;
private int tintLocation = -1;
@SuppressWarnings("WeakerAccess")
public TintFilter() { }
@ -23,7 +42,7 @@ public class TintFilter extends BaseFilter {
*/
@SuppressWarnings("WeakerAccess")
public void setTint(@ColorInt int color) {
this.mTint = color;
this.tint = color;
}
/**
@ -35,50 +54,44 @@ public class TintFilter extends BaseFilter {
@SuppressWarnings("WeakerAccess")
@ColorInt
public int getTint() {
return mTint;
return tint;
}
@NonNull
@Override
protected BaseFilter onCopy() {
TintFilter filter = new TintFilter();
filter.setTint(getTint());
return filter;
public String getFragmentShader() {
return FRAGMENT_SHADER;
}
@NonNull
@Override
public String getFragmentShader() {
float[] color_ratio = {0.21f, 0.71f, 0.07f};
String[] color_ratioString = new String[3];
color_ratioString[0] = "color_ratio[0] = " + color_ratio[0] + ";\n";
color_ratioString[1] = "color_ratio[1] = " + color_ratio[1] + ";\n";
color_ratioString[2] = "color_ratio[2] = " + color_ratio[2] + ";\n";
public void onCreate(int programHandle) {
super.onCreate(programHandle);
tintLocation = GLES20.glGetUniformLocation(programHandle, "tint");
GlUtils.checkLocation(tintLocation, "tint");
}
float[] tint_color = {Color.red(mTint) / 255f,
Color.green(mTint) / 255f, Color.blue(mTint) / 255f};
@Override
public void onDestroy() {
super.onDestroy();
tintLocation = -1;
}
String[] tintString = new String[3];
tintString[0] = "tint[0] = " + tint_color[0] + ";\n";
tintString[1] = "tint[1] = " + tint_color[1] + ";\n";
tintString[2] = "tint[2] = " + tint_color[2] + ";\n";
@Override
protected void onPreDraw(float[] transformMatrix) {
super.onPreDraw(transformMatrix);
float[] channels = new float[]{
Color.red(tint) / 255f,
Color.green(tint) / 255f,
Color.blue(tint) / 255f
};
GLES20.glUniform3fv(tintLocation, 1, channels, 0);
GlUtils.checkError("glUniform3fv");
}
return "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " vec3 tint;\n"
+ " vec3 color_ratio;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ color_ratioString[0]
+ color_ratioString[1]
+ color_ratioString[2]
+ tintString[0]
+ tintString[1]
+ tintString[2]
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " float avg_color = dot(color_ratio, color.rgb);\n"
+ " vec3 new_color = min(0.8 * avg_color + 0.2 * tint, 1.0);\n"
+ " gl_FragColor = vec4(new_color.rgb, color.a);\n" + "}\n";
@Override
protected BaseFilter onCopy() {
TintFilter filter = new TintFilter();
filter.setTint(getTint());
return filter;
}
}

@ -1,8 +1,11 @@
package com.otaliastudios.cameraview.filters;
import android.opengl.GLES20;
import androidx.annotation.NonNull;
import com.otaliastudios.cameraview.filter.BaseFilter;
import com.otaliastudios.cameraview.internal.GlUtils;
/**
@ -10,10 +13,32 @@ import com.otaliastudios.cameraview.filter.BaseFilter;
*/
public class VignetteFilter 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 float range;\n"
+ "uniform float inv_max_dist;\n"
+ "uniform float shade;\n"
+ "uniform vec2 scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
+ " const float slope = 20.0;\n"
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = shade / (1.0 + exp((dist * inv_max_dist - range) * slope)) + (1.0 - shade);\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " gl_FragColor = vec4(color.rgb * lumen, color.a);\n"
+ "}\n";
private float mScale = 0.85f;
private float mShade = 0.5f;
private int mOutputWidth = 1;
private int mOutputHeight = 1;
private int mWidth = 1;
private int mHeight = 1;
private int mRangeLocation = -1;
private int mMaxDistLocation = -1;
private int mShadeLocation = -1;
private int mScaleLocation = -1;
@SuppressWarnings("WeakerAccess")
public VignetteFilter() { }
@ -21,8 +46,8 @@ public class VignetteFilter extends BaseFilter {
@Override
public void setSize(int width, int height) {
super.setSize(width, height);
mOutputWidth = width;
mOutputHeight = height;
mWidth = width;
mHeight = height;
}
/**
@ -31,11 +56,9 @@ public class VignetteFilter extends BaseFilter {
*/
@SuppressWarnings("WeakerAccess")
public void setVignetteScale(float scale) {
if (scale < 0.0f)
scale = 0.0f;
else if (scale > 1.0f)
scale = 1.0f;
this.mScale = scale;
if (scale < 0.0f) scale = 0.0f;
if (scale > 1.0f) scale = 1.0f;
mScale = scale;
}
/**
@ -71,61 +94,68 @@ public class VignetteFilter extends BaseFilter {
return mShade;
}
@NonNull
@Override
protected BaseFilter onCopy() {
VignetteFilter filter = new VignetteFilter();
filter.setVignetteScale(getVignetteScale());
filter.setVignetteShade(getVignetteShade());
return filter;
public String getFragmentShader() {
return FRAGMENT_SHADER;
}
@NonNull
@Override
public String getFragmentShader() {
public void onCreate(int programHandle) {
super.onCreate(programHandle);
mRangeLocation = GLES20.glGetUniformLocation(programHandle, "range");
GlUtils.checkLocation(mRangeLocation, "range");
mMaxDistLocation = GLES20.glGetUniformLocation(programHandle, "inv_max_dist");
GlUtils.checkLocation(mMaxDistLocation, "inv_max_dist");
mShadeLocation = GLES20.glGetUniformLocation(programHandle, "shade");
GlUtils.checkLocation(mShadeLocation, "shade");
mScaleLocation = GLES20.glGetUniformLocation(programHandle, "scale");
GlUtils.checkLocation(mScaleLocation, "scale");
}
@Override
public void onDestroy() {
super.onDestroy();
mRangeLocation = -1;
mMaxDistLocation = -1;
mShadeLocation = -1;
mScaleLocation = -1;
}
@Override
protected void onPreDraw(float[] transformMatrix) {
super.onPreDraw(transformMatrix);
float[] scale = new float[2];
if (mOutputWidth > mOutputHeight) {
if (mWidth > mHeight) {
scale[0] = 1f;
scale[1] = ((float) mOutputHeight) / mOutputWidth;
scale[1] = ((float) mHeight) / mWidth;
} else {
scale[0] = ((float) mOutputWidth) / mOutputHeight;
scale[0] = ((float) mWidth) / mHeight;
scale[1] = 1f;
}
float max_dist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1]
* scale[1])) * 0.5f;
GLES20.glUniform2fv(mScaleLocation, 1, scale, 0);
GlUtils.checkError("glUniform2fv");
String[] scaleString = new String[2];
scaleString[0] = "scale[0] = " + scale[0] + ";\n";
scaleString[1] = "scale[1] = " + scale[1] + ";\n";
String inv_max_distString = "inv_max_dist = " + 1.0f / max_dist + ";\n";
String shadeString = "shade = " + mShade + ";\n";
float maxDist = ((float) Math.sqrt(scale[0] * scale[0] + scale[1] * scale[1])) * 0.5f;
GLES20.glUniform1f(mMaxDistLocation, 1F / maxDist);
GlUtils.checkError("glUniform1f");
GLES20.glUniform1f(mShadeLocation, mShade);
GlUtils.checkError("glUniform1f");
// The 'range' is between 1.3 to 0.6. When scale is zero then range is 1.3
// which means no vignette at all because the luminousity difference is
// less than 1/256 and will cause nothing.
String rangeString = "range = "
+ (1.30f - (float) Math.sqrt(mScale) * 0.7f) + ";\n";
return "#extension GL_OES_EGL_image_external : require\n"
+ "precision mediump float;\n"
+ "uniform samplerExternalOES sTexture;\n"
+ " float range;\n"
+ " float inv_max_dist;\n"
+ " float shade;\n"
+ " vec2 scale;\n"
+ "varying vec2 vTextureCoord;\n"
+ "void main() {\n"
// Parameters that were created above
+ scaleString[0]
+ scaleString[1]
+ inv_max_distString
+ shadeString
+ rangeString
+ " const float slope = 20.0;\n"
+ " vec2 coord = vTextureCoord - vec2(0.5, 0.5);\n"
+ " float dist = length(coord * scale);\n"
+ " float lumen = shade / (1.0 + exp((dist * inv_max_dist - range) * slope)) + (1.0 - shade);\n"
+ " vec4 color = texture2D(sTexture, vTextureCoord);\n"
+ " gl_FragColor = vec4(color.rgb * lumen, color.a);\n"
+ "}\n";
float range = (1.30f - (float) Math.sqrt(mScale) * 0.7f);
GLES20.glUniform1f(mRangeLocation, range);
GlUtils.checkError("glUniform1f");
}
@Override
protected BaseFilter onCopy() {
VignetteFilter filter = new VignetteFilter();
filter.setVignetteScale(getVignetteScale());
filter.setVignetteShade(getVignetteShade());
return filter;
}
}

Loading…
Cancel
Save