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