Feature: add hue adjust

pull/221/head
xufuji456 2 years ago
parent 6055af2d8b
commit 605e60e744
  1. 6
      CameraFilter/src/main/java/com/frank/camerafilter/factory/BeautyFilterFactory.java
  2. 2
      CameraFilter/src/main/java/com/frank/camerafilter/factory/BeautyFilterType.java
  3. 42
      CameraFilter/src/main/java/com/frank/camerafilter/filter/advance/BeautyCrayonFilter.java
  4. 33
      CameraFilter/src/main/java/com/frank/camerafilter/filter/advance/BeautyHueFilter.java
  5. 53
      CameraFilter/src/main/res/raw/crayon.glsl
  6. 43
      CameraFilter/src/main/res/raw/hue.glsl
  7. 23
      CameraFilter/src/main/res/raw/sketch.glsl

@ -2,7 +2,7 @@ package com.frank.camerafilter.factory;
import android.content.Context; import android.content.Context;
import com.frank.camerafilter.filter.advance.BeautyCrayonFilter; import com.frank.camerafilter.filter.advance.BeautyHueFilter;
import com.frank.camerafilter.filter.advance.BeautySketchFilter; import com.frank.camerafilter.filter.advance.BeautySketchFilter;
import com.frank.camerafilter.filter.BaseFilter; import com.frank.camerafilter.filter.BaseFilter;
@ -15,8 +15,8 @@ public class BeautyFilterFactory {
switch (type) { switch (type) {
case SKETCH: case SKETCH:
return new BeautySketchFilter(context); return new BeautySketchFilter(context);
case CRAYON: case HUE:
return new BeautyCrayonFilter(context); return new BeautyHueFilter(context);
default: default:
return null; return null;
} }

@ -2,6 +2,6 @@ package com.frank.camerafilter.factory;
public enum BeautyFilterType { public enum BeautyFilterType {
NONE, NONE,
CRAYON, HUE,
SKETCH SKETCH
} }

@ -1,42 +0,0 @@
package com.frank.camerafilter.filter.advance;
import android.content.Context;
import android.opengl.GLES20;
import com.frank.camerafilter.R;
import com.frank.camerafilter.filter.BaseFilter;
import com.frank.camerafilter.util.OpenGLUtil;
public class BeautyCrayonFilter extends BaseFilter {
// 1.0--5.0
private int mStrengthLocation;
private int mStepOffsetLocation;
public BeautyCrayonFilter(Context context) {
super(NORMAL_VERTEX_SHADER, OpenGLUtil.readShaderFromSource(context, R.raw.crayon));
}
protected void onInit() {
super.onInit();
mStrengthLocation = GLES20.glGetUniformLocation(getProgramId(), "strength");
mStepOffsetLocation = GLES20.glGetUniformLocation(getProgramId(), "singleStepOffset");
}
protected void onInitialized() {
super.onInitialized();
setFloat(mStrengthLocation, 2.0f);
}
@Override
public void onInputSizeChanged(int width, int height) {
super.onInputSizeChanged(width, height);
setFloatVec2(mStepOffsetLocation, new float[] {1.0f / width, 1.0f / height});
}
protected void onDestroy() {
super.onDestroy();
}
}

@ -0,0 +1,33 @@
package com.frank.camerafilter.filter.advance;
import android.content.Context;
import android.opengl.GLES30;
import com.frank.camerafilter.R;
import com.frank.camerafilter.filter.BaseFilter;
import com.frank.camerafilter.util.OpenGLUtil;
public class BeautyHueFilter extends BaseFilter {
private int hueAdjust;
public BeautyHueFilter(Context context) {
super(NORMAL_VERTEX_SHADER, OpenGLUtil.readShaderFromSource(context, R.raw.hue));
}
protected void onInit() {
super.onInit();
hueAdjust = GLES30.glGetUniformLocation(getProgramId(), "hueAdjust");
}
protected void onInitialized() {
super.onInitialized();
setFloat(hueAdjust, 3.0f);
}
@Override
public void onInputSizeChanged(int width, int height) {
super.onInputSizeChanged(width, height);
}
}

@ -1,53 +0,0 @@
varying highp vec2 textureCoordinate;
precision mediump float;
uniform sampler2D inputImageTexture;
uniform vec2 singleStepOffset;
uniform float strength;
const highp vec3 W = vec3(0.299,0.587,0.114);
const mat3 rgb2yiqMatrix = mat3(
0.299, 0.587, 0.114,
0.596,-0.275,-0.321,
0.212,-0.523, 0.311);
const mat3 yiq2rgbMatrix = mat3(
1.0, 0.956, 0.621,
1.0,-0.272,-1.703,
1.0,-1.106, 0.0);
void main()
{
vec4 oralColor = texture2D(inputImageTexture, textureCoordinate);
vec3 maxValue = vec3(0.,0.,0.);
for(int i = -2; i<=2; i++)
{
for(int j = -2; j<=2; j++)
{
vec4 tempColor = texture2D(inputImageTexture, textureCoordinate+singleStepOffset*vec2(i,j));
maxValue.r = max(maxValue.r,tempColor.r);
maxValue.g = max(maxValue.g,tempColor.g);
maxValue.b = max(maxValue.b,tempColor.b);
}
}
vec3 textureColor = oralColor.rgb / maxValue;
float gray = dot(textureColor, W);
float k = 0.223529;
float alpha = min(gray,k)/k;
textureColor = textureColor * alpha + (1.-alpha)*oralColor.rgb;
vec3 yiqColor = textureColor * rgb2yiqMatrix;
yiqColor.r = max(0.0,min(1.0,pow(gray,strength)));
textureColor = yiqColor * yiq2rgbMatrix;
gl_FragColor = vec4(textureColor, oralColor.w);
}

@ -0,0 +1,43 @@
precision highp float;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform mediump float hueAdjust;
const highp vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);
const highp vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0);
const highp vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0);
const highp vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0);
const highp vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0);
const highp vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0);
void main ()
{
// Sample the input pixel
highp vec4 color = texture2D(inputImageTexture, textureCoordinate);
// Convert to YIQ
highp float YPrime = dot (color, kRGBToYPrime);
highp float I = dot (color, kRGBToI);
highp float Q = dot (color, kRGBToQ);
// Calculate the hue and chroma
highp float hue = atan (Q, I);
highp float chroma = sqrt (I * I + Q * Q);
// Make the user's adjustments
hue += (-hueAdjust); //why negative rotation?
// Convert back to YIQ
Q = chroma * sin (hue);
I = chroma * cos (hue);
// Convert back to RGB
highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0);
color.r = dot (yIQ, kYIQToR);
color.g = dot (yIQ, kYIQToG);
color.b = dot (yIQ, kYIQToB);
// Save the result
gl_FragColor = color;
}

@ -5,7 +5,7 @@ uniform sampler2D inputImageTexture;
uniform vec2 singleStepOffset; uniform vec2 singleStepOffset;
uniform float strength; uniform float strength;
const highp vec3 W = vec3(0.299,0.587,0.114); const highp vec3 W = vec3(0.299, 0.587, 0.114);
void main() void main()
@ -13,34 +13,31 @@ void main()
float threshold = 0.0; float threshold = 0.0;
//pic1 //pic1
vec4 oralColor = texture2D(inputImageTexture, textureCoordinate); vec4 oralColor = texture2D(inputImageTexture, textureCoordinate);
//pic2 //pic2
vec3 maxValue = vec3(0.,0.,0.); vec3 maxValue = vec3(0., 0., 0.);
for(int i = -2; i<=2; i++) for (int i = -2; i<=2; i++)
{ {
for(int j = -2; j<=2; j++) for (int j = -2; j<=2; j++)
{ {
vec4 tempColor = texture2D(inputImageTexture, textureCoordinate+singleStepOffset*vec2(i,j)); vec4 tempColor = texture2D(inputImageTexture, textureCoordinate+singleStepOffset*vec2(i, j));
maxValue.r = max(maxValue.r,tempColor.r); maxValue.r = max(maxValue.r, tempColor.r);
maxValue.g = max(maxValue.g,tempColor.g); maxValue.g = max(maxValue.g, tempColor.g);
maxValue.b = max(maxValue.b,tempColor.b); maxValue.b = max(maxValue.b, tempColor.b);
threshold += dot(tempColor.rgb, W); threshold += dot(tempColor.rgb, W);
} }
} }
//pic3 //pic3
float gray1 = dot(oralColor.rgb, W); float gray1 = dot(oralColor.rgb, W);
//pic4 //pic4
float gray2 = dot(maxValue, W); float gray2 = dot(maxValue, W);
//pic5 //pic5
float contour = gray1 / gray2; float contour = gray1 / gray2;
threshold = threshold / 25.; threshold = threshold / 25.;
float alpha = max(1.0,gray1>threshold?1.0:(gray1/threshold)); float alpha = max(1.0, gray1>threshold?1.0:(gray1/threshold));
float result = contour * alpha + (1.0-alpha)*gray1; float result = contour * alpha + (1.0-alpha)*gray1;
gl_FragColor = vec4(vec3(result,result,result), oralColor.w); gl_FragColor = vec4(vec3(result, result, result), oralColor.w);
} }
Loading…
Cancel
Save