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 <stdlib.h>
     18 
     19 #include "filters.h"
     20 
     21 void 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 
    103 void 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 
    133 void 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