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