1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdlib.h> 18 19#include "filters.h" 20 21void estmateWhite(unsigned char *src, int len, int *wr, int *wb, int *wg){ 22 23 int STEP = 4; 24 int RANGE = 256; 25 int *histR = (int *) malloc(256*sizeof(int)); 26 int *histG = (int *) malloc(256*sizeof(int)); 27 int *histB = (int *) malloc(256*sizeof(int)); 28 int i; 29 for (i = 0; i < 255; i++) { 30 histR[i] = histG[i] = histB[i] =0; 31 } 32 33 for (i = 0; i < len; i+=STEP) { 34 histR[(src[RED])]++; 35 histG[(src[GREEN])]++; 36 histB[(src[BLUE])]++; 37 } 38 int min_r = -1, min_g = -1,min_b = -1; 39 int max_r = 0, max_g = 0,max_b = 0; 40 int sum_r = 0,sum_g=0,sum_b=0; 41 42 for (i = 1; i < RANGE-1; i++) { 43 int r = histR[i]; 44 int g = histG[i]; 45 int b = histB[i]; 46 sum_r += r; 47 sum_g += g; 48 sum_b += b; 49 50 if (r>0){ 51 if (min_r < 0) min_r = i; 52 max_r = i; 53 } 54 if (g>0){ 55 if (min_g < 0) min_g = i; 56 max_g = i; 57 } 58 if (b>0){ 59 if (min_b < 0) min_b = i; 60 max_b = i; 61 } 62 } 63 64 int sum15r = 0,sum15g=0,sum15b=0; 65 int count15r = 0,count15g=0,count15b=0; 66 int tmp_r = 0,tmp_g=0,tmp_b=0; 67 68 for (i = RANGE-2; i >0; i--) { 69 int r = histR[i]; 70 int g = histG[i]; 71 int b = histB[i]; 72 tmp_r += r; 73 tmp_g += g; 74 tmp_b += b; 75 76 if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) { 77 sum15r += r*i; 78 count15r += r; 79 } 80 if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) { 81 sum15g += g*i; 82 count15g += g; 83 } 84 if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) { 85 sum15b += b*i; 86 count15b += b; 87 } 88 89 } 90 free(histR); 91 free(histG); 92 free(histB); 93 94 if ((count15r>0) && (count15g>0) && (count15b>0) ){ 95 *wr = sum15r/count15r; 96 *wb = sum15g/count15g; 97 *wg = sum15b/count15b; 98 }else { 99 *wg = *wb = *wr=255; 100 } 101} 102 103void estmateWhiteBox(unsigned char *src, int iw, int ih, int x,int y, int *wr, int *wb, int *wg){ 104 int r = 0; 105 int g = 0; 106 int b = 0; 107 int sum = 0; 108 int xp,yp; 109 int bounds = 5; 110 if (x<0) x = bounds; 111 if (y<0) y = bounds; 112 if (x>=(iw-bounds)) x = (iw-bounds-1); 113 if (y>=(ih-bounds)) y = (ih-bounds-1); 114 int startx = x - bounds; 115 int starty = y - bounds; 116 int endx = x + bounds; 117 int endy = y + bounds; 118 119 for(yp= starty;yp<endy;yp++) { 120 for(xp= startx;xp<endx;xp++) { 121 int i = 4*(xp+yp*iw); 122 r += src[RED]; 123 g += src[GREEN]; 124 b += src[BLUE]; 125 sum++; 126 } 127 } 128 *wr = r/sum; 129 *wg = g/sum; 130 *wb = b/sum; 131} 132 133void JNIFUNCF(ImageFilterWBalance, nativeApplyFilter, jobject bitmap, jint width, jint height, int locX,int locY) 134{ 135 char* destination = 0; 136 AndroidBitmap_lockPixels(env, bitmap, (void**) &destination); 137 int i; 138 int len = width * height * 4; 139 unsigned char * rgb = (unsigned char * )destination; 140 int wr; 141 int wg; 142 int wb; 143 144 if (locX==-1) 145 estmateWhite(rgb,len,&wr,&wg,&wb); 146 else 147 estmateWhiteBox(rgb, width, height,locX,locY,&wr,&wg,&wb); 148 149 int min = MIN(wr, MIN(wg, wb)); 150 int max = MAX(wr, MAX(wg, wb)); 151 float avg = (min+max)/2.f; 152 float scaleR = avg/wr; 153 float scaleG = avg/wg; 154 float scaleB = avg/wb; 155 156 for (i = 0; i < len; i+=4) 157 { 158 int r = rgb[RED]; 159 int g = rgb[GREEN]; 160 int b = rgb[BLUE]; 161 162 float Rc = r*scaleR; 163 float Gc = g*scaleG; 164 float Bc = b*scaleB; 165 166 rgb[RED] = clamp(Rc); 167 rgb[GREEN] = clamp(Gc); 168 rgb[BLUE] = clamp(Bc); 169 } 170 AndroidBitmap_unlockPixels(env, bitmap); 171} 172