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 <math.h>
     18 #include <stdlib.h>
     19 
     20 #include "filters.h"
     21 
     22 int value(int r, int g, int b) {
     23     return MAX(r, MAX(g, b));
     24 }
     25 
     26 int isRed(unsigned char *src, int p) {
     27     int b = src[p + 2];
     28     int g = src[p + 1];
     29     int r = src[p];
     30     int max = MAX(g, b);
     31 
     32     return ((r * 100 / (max + 2) > 160) & (max < 80));
     33 }
     34 
     35 void findPossible(unsigned char *src, unsigned char *mask, int iw,
     36         int ih __unused, short *rect) {
     37     int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
     38     int y, x;
     39 
     40     for (y = 0; y < recH; y++) {
     41         int sy = (recY + y) * iw;
     42         for (x = 0; x < recW; x++) {
     43             int p = (recX + x + sy) * 4;
     44 
     45             int b = src[p + 2];
     46             int g = src[p + 1];
     47             int r = src[p];
     48             mask[x + y * recW] = (
     49                     mask[x + y * recW] > 0 && (value(r, g, b) > 240) ? 1 : 0);
     50 
     51         }
     52 
     53     }
     54 }
     55 
     56 void findReds(unsigned char *src, unsigned char *mask, int iw, int ih __unused,
     57         short *rect) {
     58     int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
     59     int y, x;
     60 
     61     for (y = 0; y < recH; y++) {
     62         int sy = (recY + y) * iw;
     63         for (x = 0; x < recW; x++) {
     64             int p = (recX + x + sy) * 4;
     65 
     66             mask[x + y * recW] = ((isRed(src, p)) ? 1 : 0);
     67 
     68         }
     69 
     70     }
     71 }
     72 
     73 void dialateMaskIfRed(unsigned char *src, int iw, int ih __unused,
     74         unsigned char *mask, unsigned char *out, short *rect) {
     75     int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
     76     int y, x;
     77 
     78     for (y = 1; y < recH - 1; y++) {
     79         int row = recW * y;
     80         int sy = (recY + y) * iw;
     81         for (x = 1; x < recW - 1; x++) {
     82             int p = (recX + x + sy) * 4;
     83 
     84             char b = (mask[row + x] | mask[row + x + 1] | mask[row + x - 1]
     85                     | mask[row + x - recW] | mask[row + x + recW]);
     86             if (b != 0 && isRed(src, p))
     87                 out[row + x] = 1;
     88             else
     89                 out[row + x] = mask[row + x];
     90         }
     91     }
     92 }
     93 
     94 void dialateMask(unsigned char *mask, unsigned char *out, int mw, int mh) {
     95     int y, x;
     96     for (y = 1; y < mh - 1; y++) {
     97         int row = mw * y;
     98         for (x = 1; x < mw - 1; x++) {
     99             out[row + x] = (mask[row + x] | mask[row + x + 1]
    100                     | mask[row + x - 1] | mask[row + x - mw]
    101                     | mask[row + x + mw]);
    102         }
    103     }
    104 }
    105 
    106 void stuff(int r, int g, int b, unsigned char *img, int off) {
    107     img[off + 2] = b;
    108     img[off + 1] = g;
    109     img[off] = r;
    110 }
    111 
    112 void filterRedEye(unsigned char *src, unsigned char *dest, int iw, int ih, short *rect) {
    113     int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3];
    114     unsigned char *mask1 = (unsigned char *) malloc(recW * recH);
    115     unsigned char *mask2 = (unsigned char *)malloc(recW*recH);
    116     int y, x, i;
    117 
    118     rect[0] = MAX(rect[0],0);
    119     rect[1] = MAX(rect[1],0);
    120     rect[2] = MIN(rect[2]+rect[0],iw)-rect[0];
    121     rect[3] = MIN(rect[3]+rect[1],ih)-rect[1];
    122 
    123     findReds(src, mask2, iw, ih, rect);
    124     dialateMask(mask2, mask1, recW, recH);
    125     dialateMask(mask1, mask2, recW, recH);
    126     dialateMask(mask2, mask1, recW, recH);
    127     dialateMask(mask1, mask2, recW, recH);
    128     findPossible(src, mask2, iw, ih, rect);
    129     dialateMask(mask2, mask1, recW, recH);
    130 
    131     for (i = 0; i < 12; i++) {
    132         dialateMaskIfRed(src, iw, ih, mask1, mask2, rect);
    133         dialateMaskIfRed(src, iw, ih, mask2, mask1, rect);
    134     }
    135     dialateMask(mask1, mask2, recW, recH);
    136     dialateMask(mask2, mask1, recW, recH);
    137 
    138     for (y = 3; y < recH-3; y++) {
    139         int sy = (recY + y) * iw;
    140         for (x = 3; x < recW-3; x++) {
    141             int p = (recX + x + sy) * 4;
    142 
    143             int b = src[p + 2];
    144             int g = src[p + 1];
    145             int r = src[p];
    146 
    147             if (mask1[x + y * recW] != 0) {
    148                 int m = MAX(g,b);
    149                 float rr = (r - m) / (float) m;
    150                 if (rr > .7f && g < 60 && b < 60) {
    151                     dest[p + 2] = (0);
    152                     dest[p + 1] = (0);
    153                     dest[p] = (0);
    154                 } else {
    155                     if (mask2[x + y * recW] != 0) {
    156                         stuff(r / 2, g / 2, b / 2, dest, p);
    157                     } else
    158                         stuff((2 * r) / 3, (2 * g) / 3, (2 * b) / 3, dest, p);
    159                 }
    160 
    161             } else
    162                 stuff(r, g, b, dest, p);
    163 
    164             //dest[p + 2] = dest[p + 1] =dest[p]=src[p];
    165         }
    166 
    167     }
    168 
    169     free(mask1);
    170     free(mask2);
    171 }
    172 
    173 
    174