Skip to content

Commit 7c9f4d7

Browse files
committed
Add GPUImageHueFilter support
Signed-off-by: Wenwei Cai <stanley.w.cai@gmail.com>
1 parent 112be71 commit 7c9f4d7

File tree

2 files changed

+94
-1
lines changed

2 files changed

+94
-1
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package jp.co.cyberagent.android.gpuimage;
2+
3+
import android.opengl.GLES20;
4+
5+
public class GPUImageHueFilter extends GPUImageFilter {
6+
public static final String HUE_FRAGMENT_SHADER = "" +
7+
"precision highp float;\n" +
8+
"varying highp vec2 textureCoordinate;\n" +
9+
"\n" +
10+
"uniform sampler2D inputImageTexture;\n" +
11+
"uniform mediump float hueAdjust;\n" +
12+
"const highp vec4 kRGBToYPrime = vec4 (0.299, 0.587, 0.114, 0.0);\n" +
13+
"const highp vec4 kRGBToI = vec4 (0.595716, -0.274453, -0.321263, 0.0);\n" +
14+
"const highp vec4 kRGBToQ = vec4 (0.211456, -0.522591, 0.31135, 0.0);\n" +
15+
"\n" +
16+
"const highp vec4 kYIQToR = vec4 (1.0, 0.9563, 0.6210, 0.0);\n" +
17+
"const highp vec4 kYIQToG = vec4 (1.0, -0.2721, -0.6474, 0.0);\n" +
18+
"const highp vec4 kYIQToB = vec4 (1.0, -1.1070, 1.7046, 0.0);\n" +
19+
"\n" +
20+
"void main ()\n" +
21+
"{\n" +
22+
" // Sample the input pixel\n" +
23+
" highp vec4 color = texture2D(inputImageTexture, textureCoordinate);\n" +
24+
"\n" +
25+
" // Convert to YIQ\n" +
26+
" highp float YPrime = dot (color, kRGBToYPrime);\n" +
27+
" highp float I = dot (color, kRGBToI);\n" +
28+
" highp float Q = dot (color, kRGBToQ);\n" +
29+
"\n" +
30+
" // Calculate the hue and chroma\n" +
31+
" highp float hue = atan (Q, I);\n" +
32+
" highp float chroma = sqrt (I * I + Q * Q);\n" +
33+
"\n" +
34+
" // Make the user's adjustments\n" +
35+
" hue += (-hueAdjust); //why negative rotation?\n" +
36+
"\n" +
37+
" // Convert back to YIQ\n" +
38+
" Q = chroma * sin (hue);\n" +
39+
" I = chroma * cos (hue);\n" +
40+
"\n" +
41+
" // Convert back to RGB\n" +
42+
" highp vec4 yIQ = vec4 (YPrime, I, Q, 0.0);\n" +
43+
" color.r = dot (yIQ, kYIQToR);\n" +
44+
" color.g = dot (yIQ, kYIQToG);\n" +
45+
" color.b = dot (yIQ, kYIQToB);\n" +
46+
"\n" +
47+
" // Save the result\n" +
48+
" gl_FragColor = color;\n" +
49+
"}\n";
50+
51+
private float mHue;
52+
private int mHueLocation;
53+
54+
public GPUImageHueFilter() {
55+
this(90.0f);
56+
}
57+
58+
public GPUImageHueFilter(final float hue) {
59+
super(NO_FILTER_VERTEX_SHADER, HUE_FRAGMENT_SHADER);
60+
mHue = hue;
61+
}
62+
63+
@Override
64+
public void onInit() {
65+
super.onInit();
66+
mHueLocation = GLES20.glGetUniformLocation(getProgram(), "hueAdjust");
67+
}
68+
69+
@Override
70+
public void onInitialized() {
71+
super.onInitialized();
72+
setHue(mHue);
73+
}
74+
75+
public void setHue(final float hue) {
76+
mHue = hue;
77+
float hueAdjust = (mHue % 360.0f) * (float) Math.PI / 180.0f;
78+
setFloat(mHueLocation, hueAdjust);
79+
}
80+
}

sample/src/jp/co/cyberagent/android/gpuimage/sample/GPUImageFilterTools.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import jp.co.cyberagent.android.gpuimage.GPUImageSharpenFilter;
3535
import jp.co.cyberagent.android.gpuimage.GPUImageSobelEdgeDetection;
3636
import jp.co.cyberagent.android.gpuimage.GPUImageColorInvertFilter;
37+
import jp.co.cyberagent.android.gpuimage.GPUImageHueFilter;
3738
import android.app.AlertDialog;
3839
import android.content.Context;
3940
import android.content.DialogInterface;
@@ -44,6 +45,7 @@ public static void showDialog(final Context context,
4445
final FilterList filters = new FilterList();
4546
filters.addFilter("Contrast", FilterType.CONTRAST);
4647
filters.addFilter("Invert", FilterType.INVERT);
48+
filters.addFilter("Hue", FilterType.HUE);
4749
filters.addFilter("Gamma", FilterType.GAMMA);
4850
filters.addFilter("Brightness", FilterType.BRIGHTNESS);
4951
filters.addFilter("Sepia", FilterType.SEPIA);
@@ -76,6 +78,8 @@ private static GPUImageFilter createFilterForType(final Context context, final F
7678
return new GPUImageGammaFilter(2.0f);
7779
case INVERT:
7880
return new GPUImageColorInvertFilter();
81+
case HUE:
82+
return new GPUImageHueFilter(90.0f);
7983
case BRIGHTNESS:
8084
return new GPUImageBrightnessFilter(1.5f);
8185
case GRAYSCALE:
@@ -117,7 +121,7 @@ public interface OnGpuImageFilterChosenListener {
117121
}
118122

119123
private enum FilterType {
120-
CONTRAST, GRAYSCALE, SHARPEN, SEPIA, SOBEL_EDGE_DETECTION, THREE_X_THREE_CONVOLUTION, FILTER_GROUP, EMBOSS, POSTERIZE, GAMMA, BRIGHTNESS, INVERT,
124+
CONTRAST, GRAYSCALE, SHARPEN, SEPIA, SOBEL_EDGE_DETECTION, THREE_X_THREE_CONVOLUTION, FILTER_GROUP, EMBOSS, POSTERIZE, GAMMA, BRIGHTNESS, INVERT, HUE,
121125
}
122126

123127
private static class FilterList {
@@ -150,6 +154,8 @@ public FilterAdjuster(final GPUImageFilter filter) {
150154
adjuster = new GPU3x3TextureAdjuster().filter(filter);
151155
} else if (filter instanceof GPUImageEmbossFilter) {
152156
adjuster = new EmbossAdjuster().filter(filter);
157+
} else if (filter instanceof GPUImageHueFilter) {
158+
adjuster = new HueAdjuster().filter(filter);
153159
} else if (filter instanceof GPUImagePosterizeFilter) {
154160
adjuster = new PosterizeAdjuster().filter(filter);
155161
} else {
@@ -194,6 +200,13 @@ public void adjust(final int percentage) {
194200
}
195201
}
196202

203+
private class HueAdjuster extends Adjuster<GPUImageHueFilter> {
204+
@Override
205+
public void adjust(final int percentage) {
206+
getFilter().setHue(range(percentage, 0.0f, 360.0f));
207+
}
208+
}
209+
197210
private class ContrastAdjuster extends Adjuster<GPUImageContrastFilter> {
198211
@Override
199212
public void adjust(final int percentage) {

0 commit comments

Comments
 (0)