Home | History | Annotate | Download | only in filters
      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