diff options
Diffstat (limited to 'jni/filters/redEyeMath.c')
-rw-r--r-- | jni/filters/redEyeMath.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/jni/filters/redEyeMath.c b/jni/filters/redEyeMath.c new file mode 100644 index 000000000..26f3f76a4 --- /dev/null +++ b/jni/filters/redEyeMath.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <math.h> +#include "filters.h" + +int value(int r, int g, int b) { + return MAX(r, MAX(g, b)); +} + +int isRed(unsigned char *src, int p) { + int b = src[p + 2]; + int g = src[p + 1]; + int r = src[p]; + int max = MAX(g, b); + + return ((r * 100 / (max + 2) > 160) & (max < 80)); +} + +void findPossible(unsigned char *src, unsigned char *mask, int iw, int ih, + short *rect) { + int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; + int y, x; + + for (y = 0; y < recH; y++) { + int sy = (recY + y) * iw; + for (x = 0; x < recW; x++) { + int p = (recX + x + sy) * 4; + + int b = src[p + 2]; + int g = src[p + 1]; + int r = src[p]; + mask[x + y * recW] = ( + mask[x + y * recW] > 0 && (value(r, g, b) > 240) ? 1 : 0); + + } + + } +} + +void findReds(unsigned char *src, unsigned char *mask, int iw, int ih, + short *rect) { + int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; + int y, x; + + for (y = 0; y < recH; y++) { + int sy = (recY + y) * iw; + for (x = 0; x < recW; x++) { + int p = (recX + x + sy) * 4; + + mask[x + y * recW] = ((isRed(src, p)) ? 1 : 0); + + } + + } +} + +void dialateMaskIfRed(unsigned char *src, int iw, int ih, unsigned char *mask, + unsigned char *out, short *rect) { + int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; + int y, x; + + for (y = 1; y < recH - 1; y++) { + int row = recW * y; + int sy = (recY + y) * iw; + for (x = 1; x < recW - 1; x++) { + int p = (recX + x + sy) * 4; + + char b = (mask[row + x] | mask[row + x + 1] | mask[row + x - 1] + | mask[row + x - recW] | mask[row + x + recW]); + if (b != 0 && isRed(src, p)) + out[row + x] = 1; + else + out[row + x] = mask[row + x]; + } + } +} + +void dialateMask(unsigned char *mask, unsigned char *out, int mw, int mh) { + int y, x; + for (y = 1; y < mh - 1; y++) { + int row = mw * y; + for (x = 1; x < mw - 1; x++) { + out[row + x] = (mask[row + x] | mask[row + x + 1] + | mask[row + x - 1] | mask[row + x - mw] + | mask[row + x + mw]); + } + } +} + +void stuff(int r, int g, int b, unsigned char *img, int off) { + img[off + 2] = b; + img[off + 1] = g; + img[off] = r; +} + +void filterRedEye(unsigned char *src, unsigned char *dest, int iw, int ih, short *rect) { + int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; + unsigned char *mask1 = (unsigned char *) malloc(recW * recH); + unsigned char *mask2 = (unsigned char *)malloc(recW*recH); + int QUE_LEN = 100; + int y, x, i; + + rect[0] = MAX(rect[0],0); + rect[1] = MAX(rect[1],0); + rect[2] = MIN(rect[2]+rect[0],iw)-rect[0]; + rect[3] = MIN(rect[3]+rect[1],ih)-rect[1]; + + findReds(src, mask2, iw, ih, rect); + dialateMask(mask2, mask1, recW, recH); + dialateMask(mask1, mask2, recW, recH); + dialateMask(mask2, mask1, recW, recH); + dialateMask(mask1, mask2, recW, recH); + findPossible(src, mask2, iw, ih, rect); + dialateMask(mask2, mask1, recW, recH); + + for (i = 0; i < 12; i++) { + dialateMaskIfRed(src, iw, ih, mask1, mask2, rect); + dialateMaskIfRed(src, iw, ih, mask2, mask1, rect); + } + dialateMask(mask1, mask2, recW, recH); + dialateMask(mask2, mask1, recW, recH); + + for (y = 3; y < recH-3; y++) { + int sy = (recY + y) * iw; + for (x = 3; x < recW-3; x++) { + int p = (recX + x + sy) * 4; + + int b = src[p + 2]; + int g = src[p + 1]; + int r = src[p]; + + if (mask1[x + y * recW] != 0) { + int m = MAX(g,b); + float rr = (r - m) / (float) m; + if (rr > .7f && g < 60 && b < 60) { + dest[p + 2] = (0); + dest[p + 1] = (0); + dest[p] = (0); + } else { + if (mask2[x + y * recW] != 0) { + stuff(r / 2, g / 2, b / 2, dest, p); + } else + stuff((2 * r) / 3, (2 * g) / 3, (2 * b) / 3, dest, p); + } + + } else + stuff(r, g, b, dest, p); + + //dest[p + 2] = dest[p + 1] =dest[p]=src[p]; + } + + } + + free(mask1); + free(mask2); +} + + |