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 "filters.h" 18 19 void estmateWhite(unsigned char *src, int len, int *wr, int *wb, int *wg){ 20 21 int STEP = 4; 22 int RANGE = 256; 23 int *histR = (int *) malloc(256*sizeof(int)); 24 int *histG = (int *) malloc(256*sizeof(int)); 25 int *histB = (int *) malloc(256*sizeof(int)); 26 int i; 27 for (i = 0; i < 255; i++) { 28 histR[i] = histG[i] = histB[i] =0; 29 } 30 31 for (i = 0; i < len; i+=STEP) { 32 histR[(src[RED])]++; 33 histG[(src[GREEN])]++; 34 histB[(src[BLUE])]++; 35 } 36 int min_r = -1, min_g = -1,min_b = -1; 37 int max_r = 0, max_g = 0,max_b = 0; 38 int sum_r = 0,sum_g=0,sum_b=0; 39 40 for (i = 1; i < RANGE-1; i++) { 41 int r = histR[i]; 42 int g = histG[i]; 43 int b = histB[i]; 44 sum_r += r; 45 sum_g += g; 46 sum_b += b; 47 48 if (r>0){ 49 if (min_r < 0) min_r = i; 50 max_r = i; 51 } 52 if (g>0){ 53 if (min_g < 0) min_g = i; 54 max_g = i; 55 } 56 if (b>0){ 57 if (min_b < 0) min_b = i; 58 max_b = i; 59 } 60 } 61 62 int sum15r = 0,sum15g=0,sum15b=0; 63 int count15r = 0,count15g=0,count15b=0; 64 int tmp_r = 0,tmp_g=0,tmp_b=0; 65 66 for (i = RANGE-2; i >0; i--) { 67 int r = histR[i]; 68 int g = histG[i]; 69 int b = histB[i]; 70 tmp_r += r; 71 tmp_g += g; 72 tmp_b += b; 73 74 if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) { 75 sum15r += r*i; 76 count15r += r; 77 } 78 if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) { 79 sum15g += g*i; 80 count15g += g; 81 } 82 if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) { 83 sum15b += b*i; 84 count15b += b; 85 } 86 87 } 88 free(histR); 89 free(histG); 90 free(histB); 91 92 if ((count15r>0) && (count15g>0) && (count15b>0) ){ 93 *wr = sum15r/count15r; 94 *wb = sum15g/count15g; 95 *wg = sum15b/count15b; 96 }else { 97 *wg = *wb = *wr=255; 98 } 99 } 100 101 void estmateWhiteBox(unsigned char *src, int iw, int ih, int x,int y, int *wr, int *wb, int *wg){ 102 int r; 103 int g; 104 int b; 105 int sum; 106 int xp,yp; 107 int bounds = 5; 108 if (x<0) x = bounds; 109 if (y<0) y = bounds; 110 if (x>=(iw-bounds)) x = (iw-bounds-1); 111 if (y>=(ih-bounds)) y = (ih-bounds-1); 112 int startx = x - bounds; 113 int starty = y - bounds; 114 int endx = x + bounds; 115 int endy = y + bounds; 116 117 for(yp= starty;yp<endy;yp++) { 118 for(xp= startx;xp<endx;xp++) { 119 int i = 4*(xp+yp*iw); 120 r += src[RED]; 121 g += src[GREEN]; 122 b += src[BLUE]; 123 sum++; 124 } 125 } 126 *wr = r/sum; 127 *wg = g/sum; 128 *wb = b/sum; 129 } 130 131 void JNIFUNCF(ImageFilterWBalance, nativeApplyFilter, jobject bitmap, jint width, jint height, int locX,int locY) 132 { 133 char* destination = 0; 134 AndroidBitmap_lockPixels(env, bitmap, (void**) &destination); 135 int i; 136 int len = width * height * 4; 137 unsigned char * rgb = (unsigned char * )destination; 138 int wr; 139 int wg; 140 int wb; 141 142 if (locX==-1) 143 estmateWhite(rgb,len,&wr,&wg,&wb); 144 else 145 estmateWhiteBox(rgb, width, height,locX,locY,&wr,&wg,&wb); 146 147 int min = MIN(wr, MIN(wg, wb)); 148 int max = MAX(wr, MAX(wg, wb)); 149 float avg = (min+max)/2.f; 150 float scaleR = avg/wr; 151 float scaleG = avg/wg; 152 float scaleB = avg/wb; 153 154 for (i = 0; i < len; i+=4) 155 { 156 int r = rgb[RED]; 157 int g = rgb[GREEN]; 158 int b = rgb[BLUE]; 159 160 float Rc = r*scaleR; 161 float Gc = g*scaleG; 162 float Bc = b*scaleB; 163 164 rgb[RED] = clamp(Rc); 165 rgb[GREEN] = clamp(Gc); 166 rgb[BLUE] = clamp(Bc); 167 } 168 AndroidBitmap_unlockPixels(env, bitmap); 169 } 170