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