diff options
-rw-r--r-- | jni/Android.mk | 1 | ||||
-rw-r--r-- | jni/filters/wbalance.c | 169 | ||||
-rw-r--r-- | res/layout/filtershow_activity.xml | 32 | ||||
-rw-r--r-- | res/values/filtershow_strings.xml | 6 | ||||
-rw-r--r-- | src/com/android/gallery3d/filtershow/FilterShowActivity.java | 12 | ||||
-rw-r--r-- | src/com/android/gallery3d/filtershow/PanelController.java | 13 | ||||
-rw-r--r-- | src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java | 24 |
7 files changed, 232 insertions, 25 deletions
diff --git a/jni/Android.mk b/jni/Android.mk index f2f714d50..85e867ab4 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -37,6 +37,7 @@ LOCAL_SRC_FILES := filters/bw.c \ filters/vignette.c \ filters/redEyeMath.c \ filters/fx.c \ + filters/wbalance.c \ filters/redeye.c LOCAL_CFLAGS += -ffast-math -O3 -funroll-loops diff --git a/jni/filters/wbalance.c b/jni/filters/wbalance.c new file mode 100644 index 000000000..2b92b9978 --- /dev/null +++ b/jni/filters/wbalance.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "filters.h" + +void estmateWhite(unsigned char *src, int len, int *wr, int *wb, int *wg){ + + int STEP = 4; + int RANGE = 256; + int *histR = (int *) malloc(256*sizeof(int)); + int *histG = (int *) malloc(256*sizeof(int)); + int *histB = (int *) malloc(256*sizeof(int)); + int i; + for (i = 0; i < 255; i++) { + histR[i] = histG[i] = histB[i] =0; + } + + for (i = 0; i < len; i+=STEP) { + histR[(src[RED])]++; + histG[(src[GREEN])]++; + histB[(src[BLUE])]++; + } + int min_r = -1, min_g = -1,min_b = -1; + int max_r = 0, max_g = 0,max_b = 0; + int sum_r = 0,sum_g=0,sum_b=0; + + for (i = 1; i < RANGE-1; i++) { + int r = histR[i]; + int g = histG[i]; + int b = histB[i]; + sum_r += r; + sum_g += g; + sum_b += b; + + if (r>0){ + if (min_r < 0) min_r = i; + max_r = i; + } + if (g>0){ + if (min_g < 0) min_g = i; + max_g = i; + } + if (b>0){ + if (min_b < 0) min_b = i; + max_b = i; + } + } + + int sum15r = 0,sum15g=0,sum15b=0; + int count15r = 0,count15g=0,count15b=0; + int tmp_r = 0,tmp_g=0,tmp_b=0; + + for (i = RANGE-2; i >0; i--) { + int r = histR[i]; + int g = histG[i]; + int b = histB[i]; + tmp_r += r; + tmp_g += g; + tmp_b += b; + + if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) { + sum15r += r*i; + count15r += r; + } + if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) { + sum15g += g*i; + count15g += g; + } + if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) { + sum15b += b*i; + count15b += b; + } + + } + free(histR); + free(histG); + free(histB); + + if ((count15r>0) && (count15g>0) && (count15b>0) ){ + *wr = sum15r/count15r; + *wb = sum15g/count15g; + *wg = sum15b/count15b; + }else { + *wg = *wb = *wr=255; + } +} + +void estmateWhiteBox(unsigned char *src, int iw, int ih, int x,int y, int *wr, int *wb, int *wg){ + int r; + int g; + int b; + int sum; + int xp,yp; + int bounds = 5; + if (x<0) x = bounds; + if (y<0) y = bounds; + if (x>=(iw-bounds)) x = (iw-bounds-1); + if (y>=(ih-bounds)) y = (ih-bounds-1); + int startx = x - bounds; + int starty = y - bounds; + int endx = x + bounds; + int endy = y + bounds; + + for(yp= starty;yp<endy;yp++) { + for(xp= startx;xp<endx;xp++) { + int i = 4*(xp+yp*iw); + r += src[RED]; + g += src[GREEN]; + b += src[BLUE]; + sum++; + } + } + *wr = r/sum; + *wg = g/sum; + *wb = b/sum; +} + +void JNIFUNCF(ImageFilterWBalance, nativeApplyFilter, jobject bitmap, jint width, jint height, int locX,int locY) +{ + char* destination = 0; + AndroidBitmap_lockPixels(env, bitmap, (void**) &destination); + int i; + int len = width * height * 4; + unsigned char * rgb = (unsigned char * )destination; + int wr; + int wg; + int wb; + + if (locX==-1) + estmateWhite(rgb,len,&wr,&wg,&wb); + else + estmateWhiteBox(rgb, width, height,locX,locY,&wr,&wg,&wb); + + int min = MIN(wr, MIN(wg, wb)); + int max = MAX(wr, MAX(wg, wb)); + float avg = (min+max)/2.f; + float scaleR = avg/wr; + float scaleG = avg/wg; + float scaleB = avg/wb; + + for (i = 0; i < len; i+=4) + { + int r = rgb[RED]; + int g = rgb[GREEN]; + int b = rgb[BLUE]; + + float Rc = r*scaleR; + float Gc = g*scaleG; + float Bc = b*scaleB; + + rgb[RED] = clamp(Rc); + rgb[GREEN] = clamp(Gc); + rgb[BLUE] = clamp(Bc); + } + AndroidBitmap_unlockPixels(env, bitmap); +} diff --git a/res/layout/filtershow_activity.xml b/res/layout/filtershow_activity.xml index 178f18a68..6f1b1901e 100644 --- a/res/layout/filtershow_activity.xml +++ b/res/layout/filtershow_activity.xml @@ -276,7 +276,9 @@ android:id="@+id/redEyeButton" style="@style/FilterShowBottomButton" android:src="@drawable/photoeditor_effect_redeye" - android:text="@string/redeye" /> + android:text="@string/redeye" + android:visibility="gone" /> + </LinearLayout> </HorizontalScrollView> @@ -294,22 +296,22 @@ android:orientation="horizontal" > <com.android.gallery3d.filtershow.ui.ImageButtonTitle - android:id="@+id/exposureButton" + android:id="@+id/wbalanceButton" style="@style/FilterShowBottomButton" android:src="@drawable/filtershow_button_colors_contrast" - android:text="@string/exposure" /> + android:text="@string/wbalance" /> <com.android.gallery3d.filtershow.ui.ImageButtonTitle - android:id="@+id/vibranceButton" + android:id="@+id/exposureButton" style="@style/FilterShowBottomButton" android:src="@drawable/filtershow_button_colors_contrast" - android:text="@string/vibrance" /> + android:text="@string/exposure" /> <com.android.gallery3d.filtershow.ui.ImageButtonTitle - android:id="@+id/saturationButton" + android:id="@+id/vibranceButton" style="@style/FilterShowBottomButton" android:src="@drawable/filtershow_button_colors_contrast" - android:text="@string/saturation" /> + android:text="@string/vibrance" /> <com.android.gallery3d.filtershow.ui.ImageButtonTitle android:id="@+id/contrastButton" @@ -336,16 +338,22 @@ android:text="@string/sharpen" /> <com.android.gallery3d.filtershow.ui.ImageButtonTitle - android:id="@+id/tintButton" + android:id="@+id/curvesButtonRGB" + style="@style/FilterShowBottomButton" + android:src="@drawable/filtershow_button_colors_curve" + android:text="@string/curvesRGB" /> + + <com.android.gallery3d.filtershow.ui.ImageButtonTitle + android:id="@+id/hueButton" style="@style/FilterShowBottomButton" android:src="@drawable/filtershow_button_colors_contrast" - android:text="@string/tint" /> + android:text="@string/hue" /> <com.android.gallery3d.filtershow.ui.ImageButtonTitle - android:id="@+id/curvesButtonRGB" + android:id="@+id/saturationButton" style="@style/FilterShowBottomButton" - android:src="@drawable/filtershow_button_colors_curve" - android:text="@string/curvesRGB" /> + android:src="@drawable/filtershow_button_colors_contrast" + android:text="@string/saturation" /> </LinearLayout> </HorizontalScrollView> diff --git a/res/values/filtershow_strings.xml b/res/values/filtershow_strings.xml index 50235669d..e953fa089 100644 --- a/res/values/filtershow_strings.xml +++ b/res/values/filtershow_strings.xml @@ -73,8 +73,10 @@ <string name="vibrance">Vibrance</string> <!-- Label for the saturation filter button [CHAR LIMIT=15] --> <string name="saturation">Saturation</string> - <!-- Label for the tint filter button [CHAR LIMIT=15] --> - <string name="tint">Tint</string> + <!-- Label for the White Balance filter button [CHAR LIMIT=15] --> + <string name="wbalance">White Balance</string> + <!-- Label for the Hue filter button [CHAR LIMIT=15] --> + <string name="hue">Hue</string> <!-- Label for the shadow recovery filter button [CHAR LIMIT=15] --> <string name="shadow_recovery">Shadows</string> <!-- Label for the curves filter button [CHAR LIMIT=15] --> diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 505f4608e..aca7f4280 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -206,10 +206,10 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, mPanelController.addComponent(mColorsButton, findViewById(R.id.vibranceButton)); mPanelController.addComponent(mColorsButton, findViewById(R.id.contrastButton)); mPanelController.addComponent(mColorsButton, findViewById(R.id.saturationButton)); - mPanelController.addComponent(mColorsButton, findViewById(R.id.tintButton)); + mPanelController.addComponent(mColorsButton, findViewById(R.id.wbalanceButton)); + mPanelController.addComponent(mColorsButton, findViewById(R.id.hueButton)); mPanelController.addComponent(mColorsButton, findViewById(R.id.exposureButton)); mPanelController.addComponent(mColorsButton, findViewById(R.id.shadowRecoveryButton)); - mPanelController.addComponent(mColorsButton, findViewById(R.id.redEyeButton)); mPanelController.addView(findViewById(R.id.resetEffect)); mPanelController.addView(findViewById(R.id.applyEffect)); @@ -431,14 +431,6 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, preset[p++] = new ImagePresetFX(b, getString(fxNameid[i])); } - preset[p++] = new ImagePresetSaturated(); - preset[p++] = new ImagePresetOld(); - preset[p++] = new ImagePresetXProcessing(); - preset[p++] = new ImagePresetBW(); - preset[p++] = new ImagePresetBWRed(); - preset[p++] = new ImagePresetBWGreen(); - preset[p++] = new ImagePresetBWBlue(); - ImageSmallFilter previousFilter = null; for (int i = 0; i < p; i++) { ImageSmallFilter filter = new ImageSmallFilter(this); diff --git a/src/com/android/gallery3d/filtershow/PanelController.java b/src/com/android/gallery3d/filtershow/PanelController.java index 0c50046df..8da762559 100644 --- a/src/com/android/gallery3d/filtershow/PanelController.java +++ b/src/com/android/gallery3d/filtershow/PanelController.java @@ -19,6 +19,7 @@ import com.android.gallery3d.filtershow.filters.ImageFilterShadows; import com.android.gallery3d.filtershow.filters.ImageFilterSharpen; import com.android.gallery3d.filtershow.filters.ImageFilterVibrance; import com.android.gallery3d.filtershow.filters.ImageFilterVignette; +import com.android.gallery3d.filtershow.filters.ImageFilterWBalance; import com.android.gallery3d.filtershow.imageshow.ImageShow; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.filtershow.ui.ImageCurves; @@ -372,6 +373,9 @@ public class PanelController implements OnClickListener { if (filter == null && name.equalsIgnoreCase("Redeye")) { filter = setImagePreset(new ImageFilterRedEye(), name); } + if (filter == null && name.equalsIgnoreCase("WBalance")) { + filter = setImagePreset(new ImageFilterWBalance(), name); + } mMasterImage.setCurrentFilter(filter); } @@ -456,7 +460,14 @@ public class PanelController implements OnClickListener { ensureFilter("Saturated"); break; } - case R.id.tintButton: { + case R.id.wbalanceButton: { + mCurrentImage = showImageView(R.id.imageShow).setShowControls(false); + mUtilityPanel.setEffectName("White Balance"); + mUtilityPanel.setGeometryEffect(true); + ensureFilter("WBalance"); + break; + } + case R.id.hueButton: { mCurrentImage = showImageView(R.id.imageShow).setShowControls(true); mUtilityPanel.setEffectName("Hue"); mUtilityPanel.setGeometryEffect(false); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java new file mode 100644 index 000000000..163ed0c65 --- /dev/null +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java @@ -0,0 +1,24 @@ + +package com.android.gallery3d.filtershow.filters; + +import android.graphics.Bitmap; +import android.util.Log; + +public class ImageFilterWBalance extends ImageFilter { + private static final String TAG = "ImageFilterWBalance"; + + public ImageFilterWBalance() { + mName = "WBalance"; + } + + native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int locX, int locY); + + @Override + public Bitmap apply(Bitmap bitmap, float scaleFactor, boolean highQuality) { + int w = bitmap.getWidth(); + int h = bitmap.getHeight(); + Log.v(TAG,"White Balance Call"); + nativeApplyFilter(bitmap, w, h, -1,-1); + return bitmap; + } +} |