From fc275d4e972304a8c4935d6161c74cbbbdf600ae Mon Sep 17 00:00:00 2001 From: John Hoford Date: Thu, 27 Sep 2012 16:34:21 -0700 Subject: Add contrast & brightness filters Added hue fixed contrast Stablized Contrast, Saturation, Tint, Exposure bug:7234321 Change-Id: Iadd1e3ab215b60f920b718fa56611a07f24effee --- .../gallery3d/filtershow/FilterShowActivity.java | 169 ++++++++++++++++- .../filtershow/filters/ColorSpaceMatrix.java | 201 +++++++++++++++++++++ .../filtershow/filters/ImageFilterBrightness.java | 25 +++ .../filtershow/filters/ImageFilterContrast.java | 25 +++ .../filtershow/filters/ImageFilterHue.java | 29 +++ .../filtershow/filters/ImageFilterSaturated.java | 4 +- 6 files changed, 449 insertions(+), 4 deletions(-) create mode 100644 src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java create mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterBrightness.java create mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java create mode 100644 src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 43ff67750..589d5731b 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -65,7 +65,13 @@ public class FilterShowActivity extends Activity implements OnItemClickListener private ImageButton mCurvesButtonGreen = null; private ImageButton mCurvesButtonBlue = null; private ImageButton mSharpenButton = null; + private ImageButton mContrastButton = null; + private ImageButton mSaturationButton = null; + private ImageButton mTintButton = null; + private ImageButton mVibranceButton = null; + private ImageButton mExposureButton = null; + private ImageButton mShadowRecoveryButton = null; private static final int SELECT_PICTURE = 1; private static final String LOGTAG = "FilterShowActivity"; @@ -133,7 +139,13 @@ public class FilterShowActivity extends Activity implements OnItemClickListener mCurvesButtonGreen = (ImageButton) findViewById(R.id.curvesButtonGreen); mCurvesButtonBlue = (ImageButton) findViewById(R.id.curvesButtonBlue); mSharpenButton = (ImageButton) findViewById(R.id.sharpenButton); + mVibranceButton = (ImageButton) findViewById(R.id.vibranceButton); mContrastButton = (ImageButton) findViewById(R.id.contrastButton); + mSaturationButton = (ImageButton) findViewById(R.id.saturationButton); + mTintButton = (ImageButton) findViewById(R.id.tintButton); + mExposureButton = (ImageButton) findViewById(R.id.exposureButton); + mShadowRecoveryButton = (ImageButton) findViewById(R.id.shadowRecoveryButton); + mColorsPanelButtons.add(mVignetteButton); mColorsPanelButtons.add(mCurvesButtonRGB); mColorsPanelButtons.add(mCurvesButtonRed); @@ -141,6 +153,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener mColorsPanelButtons.add(mCurvesButtonBlue); mColorsPanelButtons.add(mSharpenButton); mColorsPanelButtons.add(mContrastButton); + mColorsPanelButtons.add(mSaturationButton); + mColorsPanelButtons.add(mTintButton); + mColorsPanelButtons.add(mVibranceButton); + mColorsPanelButtons.add(mExposureButton); + mColorsPanelButtons.add(mShadowRecoveryButton); mCurvesButtonRGB.setSelected(true); @@ -160,6 +177,12 @@ public class FilterShowActivity extends Activity implements OnItemClickListener mSharpenButton.setOnClickListener(createOnClickSharpenButton()); mContrastButton.setOnClickListener(createOnClickContrastButton()); + mSaturationButton.setOnClickListener(createOnClickSaturationButton()); + + mTintButton.setOnClickListener(createOnClickTintButton()); + mVibranceButton.setOnClickListener(createOnClickVibranceButton()); + mExposureButton.setOnClickListener(createOnClickExposureButton()); + mShadowRecoveryButton.setOnClickListener(createOnClickShadowRecoveryButton()); mFxButton.setOnClickListener(createOnClickFxButton()); mBorderButton.setOnClickListener(createOnClickBorderButton()); @@ -648,14 +671,156 @@ public class FilterShowActivity extends Activity implements OnItemClickListener public void onClick(View v) { hideImageViews(); mImageShow.setVisibility(View.VISIBLE); + mImageShow.setShowControls(true); + ImagePreset preset = mImageShow.getImagePreset(); + ImageFilter filter = preset.getFilter("Contrast"); + if (filter == null) { + ImageFilterContrast contrast = new ImageFilterContrast(); + ImagePreset copy = new ImagePreset(preset); + copy.add(contrast); + copy.setHistoryName(contrast.name()); + copy.setIsFx(false); + filter = copy.getFilter("Contrast"); + mImageShow.setImagePreset(copy); + } + mImageShow.setCurrentFilter(filter); unselectPanelButtons(mColorsPanelButtons); mContrastButton.setSelected(true); - mImageShow.showToast("Contrast", true); - mImageShow.setCurrentFilter(null); + invalidateViews(); } }; } + private OnClickListener createOnClickSaturationButton() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + hideImageViews(); + mImageShow.setVisibility(View.VISIBLE); + mImageShow.setShowControls(true); + ImagePreset preset = mImageShow.getImagePreset(); + ImageFilter filter = preset.getFilter("Saturated"); + if (filter == null) { + ImageFilterSaturated sat = new ImageFilterSaturated(); + ImagePreset copy = new ImagePreset(preset); + copy.add(sat); + copy.setHistoryName(sat.name()); + copy.setIsFx(false); + filter = copy.getFilter("Saturated"); + mImageShow.setImagePreset(copy); + } + mImageShow.setCurrentFilter(filter); + unselectPanelButtons(mColorsPanelButtons); + mSaturationButton.setSelected(true); + invalidateViews(); + } + }; + } + + private OnClickListener createOnClickTintButton() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + hideImageViews(); + mImageShow.setVisibility(View.VISIBLE); + mImageShow.setShowControls(true); + ImagePreset preset = mImageShow.getImagePreset(); + ImageFilter filter = preset.getFilter("Hue"); + if (filter == null) { + ImageFilterHue contrast = new ImageFilterHue(); + ImagePreset copy = new ImagePreset(preset); + copy.add(contrast); + copy.setHistoryName(contrast.name()); + copy.setIsFx(false); + filter = copy.getFilter("Hue"); + mImageShow.setImagePreset(copy); + } + mImageShow.setCurrentFilter(filter); + unselectPanelButtons(mColorsPanelButtons); + mTintButton.setSelected(true); + invalidateViews(); + } + }; + } + + private OnClickListener createOnClickVibranceButton() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + hideImageViews(); + mImageShow.setVisibility(View.VISIBLE); + mImageShow.setShowControls(true); + ImagePreset preset = mImageShow.getImagePreset(); + ImageFilter filter = preset.getFilter("Hue"); + if (filter == null) { + ImageFilterHue contrast = new ImageFilterHue(); + ImagePreset copy = new ImagePreset(preset); + copy.add(contrast); + copy.setHistoryName(contrast.name()); + copy.setIsFx(false); + filter = copy.getFilter("Hue"); + mImageShow.setImagePreset(copy); + } + mImageShow.setCurrentFilter(filter); + unselectPanelButtons(mColorsPanelButtons); + mVibranceButton.setSelected(true); + invalidateViews(); + } + }; + } + + private OnClickListener createOnClickExposureButton() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + hideImageViews(); + mImageShow.setVisibility(View.VISIBLE); + mImageShow.setShowControls(true); + ImagePreset preset = mImageShow.getImagePreset(); + ImageFilter filter = preset.getFilter("Brightness"); + if (filter == null) { + ImageFilterBrightness bright = new ImageFilterBrightness(); + ImagePreset copy = new ImagePreset(preset); + copy.add(bright); + copy.setHistoryName(bright.name()); + copy.setIsFx(false); + filter = copy.getFilter("Brightness"); + mImageShow.setImagePreset(copy); + } + mImageShow.setCurrentFilter(filter); + unselectPanelButtons(mColorsPanelButtons); + mExposureButton.setSelected(true); + invalidateViews(); + } + }; + } + + private OnClickListener createOnClickShadowRecoveryButton() { + return new View.OnClickListener() { + @Override + public void onClick(View v) { + hideImageViews(); + mImageShow.setVisibility(View.VISIBLE); + mImageShow.setShowControls(true); + ImagePreset preset = mImageShow.getImagePreset(); + ImageFilter filter = preset.getFilter("Hue"); + if (filter == null) { + ImageFilterHue contrast = new ImageFilterHue(); + ImagePreset copy = new ImagePreset(preset); + copy.add(contrast); + copy.setHistoryName(contrast.name()); + copy.setIsFx(false); + filter = copy.getFilter("Hue"); + mImageShow.setImagePreset(copy); + } + mImageShow.setCurrentFilter(filter); + unselectPanelButtons(mColorsPanelButtons); + mShadowRecoveryButton.setSelected(true); + invalidateViews(); + } + }; + } + // ////////////////////////////////////////////////////////////////////////////// public float getPixelsFromDip(float value) { diff --git a/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java b/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java new file mode 100644 index 000000000..f03a04569 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java @@ -0,0 +1,201 @@ + +package com.android.gallery3d.filtershow.filters; + +import java.util.Arrays; + +public class ColorSpaceMatrix { + private final float[] matrix = new float[16]; + private static final float RLUM = 0.3086f; + private static final float GLUM = 0.6094f; + private static final float BLUM = 0.0820f; + + public ColorSpaceMatrix() { + identity(); + } + + /** + * get the matrix + * + * @return the internal matrix + */ + public float[] getMatrix() { + return matrix; + } + + /** + * set matrix to identity + */ + public void identity() { + Arrays.fill(matrix, 0); + matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1; + } + + public void convertToLuminance() { + matrix[0] = matrix[1] = matrix[2] = 0.3086f; + matrix[4] = matrix[5] = matrix[6] = 0.6094f; + matrix[8] = matrix[9] = matrix[10] = 0.0820f; + } + + private void multiply(float[] a) + { + int x, y; + float[] temp = new float[16]; + + for (y = 0; y < 4; y++) { + int y4 = y * 4; + for (x = 0; x < 4; x++) { + temp[y4 + x] = matrix[y4 + 0] * a[x] + + matrix[y4 + 1] * a[4 + x] + + matrix[y4 + 2] * a[8 + x] + + matrix[y4 + 3] * a[12 + x]; + } + } + for (int i = 0; i < 16; i++) + matrix[i] = temp[i]; + } + + private void xRotateMatrix(float rs, float rc) + { + ColorSpaceMatrix c = new ColorSpaceMatrix(); + float[] tmp = c.matrix; + + tmp[5] = rc; + tmp[6] = rs; + tmp[9] = -rs; + tmp[10] = rc; + + multiply(tmp); + } + + private void yRotateMatrix(float rs, float rc) + { + ColorSpaceMatrix c = new ColorSpaceMatrix(); + float[] tmp = c.matrix; + + tmp[0] = rc; + tmp[2] = -rs; + tmp[8] = rs; + tmp[10] = rc; + + multiply(tmp); + } + + private void zRotateMatrix(float rs, float rc) + { + ColorSpaceMatrix c = new ColorSpaceMatrix(); + float[] tmp = c.matrix; + + tmp[0] = rc; + tmp[1] = rs; + tmp[4] = -rs; + tmp[5] = rc; + multiply(tmp); + } + + private void zShearMatrix(float dx, float dy) + { + ColorSpaceMatrix c = new ColorSpaceMatrix(); + float[] tmp = c.matrix; + + tmp[2] = dx; + tmp[6] = dy; + multiply(tmp); + } + + /** + * sets the transform to a shift in Hue + * + * @param rot rotation in degrees + */ + public void setHue(float rot) + { + float mag = (float) Math.sqrt(2.0); + float xrs = 1 / mag; + float xrc = 1 / mag; + xRotateMatrix(xrs, xrc); + mag = (float) Math.sqrt(3.0); + float yrs = -1 / mag; + float yrc = (float) Math.sqrt(2.0) / mag; + yRotateMatrix(yrs, yrc); + + float lx = getRedf(RLUM, GLUM, BLUM); + float ly = getGreenf(RLUM, GLUM, BLUM); + float lz = getBluef(RLUM, GLUM, BLUM); + float zsx = lx / lz; + float zsy = ly / lz; + zShearMatrix(zsx, zsy); + + float zrs = (float) Math.sin(rot * Math.PI / 180.0); + float zrc = (float) Math.cos(rot * Math.PI / 180.0); + zRotateMatrix(zrs, zrc); + zShearMatrix(-zsx, -zsy); + yRotateMatrix(-yrs, yrc); + xRotateMatrix(-xrs, xrc); + } + + /** + * set it to a saturation matrix + * + * @param s + */ + public void changeSaturation(float s) { + matrix[0] = (1 - s) * RLUM + s; + matrix[1] = (1 - s) * RLUM; + matrix[2] = (1 - s) * RLUM; + matrix[4] = (1 - s) * GLUM; + matrix[5] = (1 - s) * GLUM + s; + matrix[6] = (1 - s) * GLUM; + matrix[8] = (1 - s) * BLUM; + matrix[9] = (1 - s) * BLUM; + matrix[10] = (1 - s) * BLUM + s; + } + + /** + * Transform RGB value + * + * @param r red pixel value + * @param g green pixel value + * @param b blue pixel value + * @return computed red pixel value + */ + public float getRed(int r, int g, int b) { + return r * matrix[0] + g * matrix[4] + b * matrix[8] + matrix[12]; + } + + /** + * Transform RGB value + * + * @param r red pixel value + * @param g green pixel value + * @param b blue pixel value + * @return computed green pixel value + */ + public float getGreen(int r, int g, int b) { + return r * matrix[1] + g * matrix[5] + b * matrix[9] + matrix[13]; + } + + /** + * Transform RGB value + * + * @param r red pixel value + * @param g green pixel value + * @param b blue pixel value + * @return computed blue pixel value + */ + public float getBlue(int r, int g, int b) { + return r * matrix[2] + g * matrix[6] + b * matrix[10] + matrix[14]; + } + + private float getRedf(float r, float g, float b) { + return r * matrix[0] + g * matrix[4] + b * matrix[8] + matrix[12]; + } + + private float getGreenf(float r, float g, float b) { + return r * matrix[1] + g * matrix[5] + b * matrix[9] + matrix[13]; + } + + private float getBluef(float r, float g, float b) { + return r * matrix[2] + g * matrix[6] + b * matrix[10] + matrix[14]; + } + +} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBrightness.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBrightness.java new file mode 100644 index 000000000..8ec4dd061 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBrightness.java @@ -0,0 +1,25 @@ + +package com.android.gallery3d.filtershow.filters; + +import android.graphics.Bitmap; + +public class ImageFilterBrightness extends ImageFilter { + + public String name() { + return "Brightness"; + } + + public ImageFilter copy() { + return new ImageFilterBrightness(); + } + + native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright); + + public void apply(Bitmap bitmap) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + int p = mParameter; + float value = p; + nativeApplyFilter(bitmap, w, h, value); + } +} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java new file mode 100644 index 000000000..dd072cb56 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java @@ -0,0 +1,25 @@ + +package com.android.gallery3d.filtershow.filters; + +import android.graphics.Bitmap; + +public class ImageFilterContrast extends ImageFilter { + + public String name() { + return "Contrast"; + } + + public ImageFilter copy() { + return new ImageFilterContrast(); + } + + native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float strength); + + public void apply(Bitmap bitmap) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + float p = mParameter; + float value = p; + nativeApplyFilter(bitmap, w, h, value); + } +} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java new file mode 100644 index 000000000..154ae2941 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java @@ -0,0 +1,29 @@ + +package com.android.gallery3d.filtershow.filters; + +import android.graphics.Bitmap; + +public class ImageFilterHue extends ImageFilter { + private ColorSpaceMatrix cmatrix = new ColorSpaceMatrix(); + + public String name() { + return "Hue"; + } + + public ImageFilter copy() { + return new ImageFilterHue(); + } + + native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float []matrix); + + public void apply(Bitmap bitmap) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + float p = mParameter; + float value = p; + cmatrix.identity(); + cmatrix.setHue(value); + + nativeApplyFilter(bitmap, w, h, cmatrix.getMatrix()); + } +} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java index 7c03be68b..f44c6a1c6 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java @@ -18,8 +18,8 @@ public class ImageFilterSaturated extends ImageFilter { public void apply(Bitmap bitmap) { int w = bitmap.getWidth(); int h = bitmap.getHeight(); - int p = 100; - float value = 2 * p / 100.0f; + int p = mParameter; + float value = 1 + p / 100.0f; nativeApplyFilter(bitmap, w, h, value); } } -- cgit v1.2.3