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
value(int r,int g,int b)20 int value(int r, int g, int b) {
21 return MAX(r, MAX(g, b));
22 }
23
isRed(unsigned char * src,int p)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
findPossible(unsigned char * src,unsigned char * mask,int iw,int ih,short * rect)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
findReds(unsigned char * src,unsigned char * mask,int iw,int ih,short * rect)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
dialateMaskIfRed(unsigned char * src,int iw,int ih,unsigned char * mask,unsigned char * out,short * rect)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
dialateMask(unsigned char * mask,unsigned char * out,int mw,int mh)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
stuff(int r,int g,int b,unsigned char * img,int off)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
filterRedEye(unsigned char * src,unsigned char * dest,int iw,int ih,short * rect)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