190b1d251973bfa748d435896fc277cb4024451adJohn Hoford/* 290b1d251973bfa748d435896fc277cb4024451adJohn Hoford * Copyright (C) 2012 The Android Open Source Project 390b1d251973bfa748d435896fc277cb4024451adJohn Hoford * 490b1d251973bfa748d435896fc277cb4024451adJohn Hoford * Licensed under the Apache License, Version 2.0 (the "License"); 590b1d251973bfa748d435896fc277cb4024451adJohn Hoford * you may not use this file except in compliance with the License. 690b1d251973bfa748d435896fc277cb4024451adJohn Hoford * You may obtain a copy of the License at 790b1d251973bfa748d435896fc277cb4024451adJohn Hoford * 890b1d251973bfa748d435896fc277cb4024451adJohn Hoford * http://www.apache.org/licenses/LICENSE-2.0 990b1d251973bfa748d435896fc277cb4024451adJohn Hoford * 1090b1d251973bfa748d435896fc277cb4024451adJohn Hoford * Unless required by applicable law or agreed to in writing, software 1190b1d251973bfa748d435896fc277cb4024451adJohn Hoford * distributed under the License is distributed on an "AS IS" BASIS, 1290b1d251973bfa748d435896fc277cb4024451adJohn Hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1390b1d251973bfa748d435896fc277cb4024451adJohn Hoford * See the License for the specific language governing permissions and 1490b1d251973bfa748d435896fc277cb4024451adJohn Hoford * limitations under the License. 1590b1d251973bfa748d435896fc277cb4024451adJohn Hoford */ 1690b1d251973bfa748d435896fc277cb4024451adJohn Hoford 1790b1d251973bfa748d435896fc277cb4024451adJohn Hoford#include <math.h> 1890b1d251973bfa748d435896fc277cb4024451adJohn Hoford#include "filters.h" 1990b1d251973bfa748d435896fc277cb4024451adJohn Hoford 2090b1d251973bfa748d435896fc277cb4024451adJohn Hofordint value(int r, int g, int b) { 2190b1d251973bfa748d435896fc277cb4024451adJohn Hoford return MAX(r, MAX(g, b)); 2290b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 2390b1d251973bfa748d435896fc277cb4024451adJohn Hoford 2490b1d251973bfa748d435896fc277cb4024451adJohn Hofordint isRed(unsigned char *src, int p) { 2590b1d251973bfa748d435896fc277cb4024451adJohn Hoford int b = src[p + 2]; 2690b1d251973bfa748d435896fc277cb4024451adJohn Hoford int g = src[p + 1]; 2790b1d251973bfa748d435896fc277cb4024451adJohn Hoford int r = src[p]; 2890b1d251973bfa748d435896fc277cb4024451adJohn Hoford int max = MAX(g, b); 2990b1d251973bfa748d435896fc277cb4024451adJohn Hoford 3090b1d251973bfa748d435896fc277cb4024451adJohn Hoford return ((r * 100 / (max + 2) > 160) & (max < 80)); 3190b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 3290b1d251973bfa748d435896fc277cb4024451adJohn Hoford 3390b1d251973bfa748d435896fc277cb4024451adJohn Hofordvoid findPossible(unsigned char *src, unsigned char *mask, int iw, int ih, 3490b1d251973bfa748d435896fc277cb4024451adJohn Hoford short *rect) { 3590b1d251973bfa748d435896fc277cb4024451adJohn Hoford int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; 3690b1d251973bfa748d435896fc277cb4024451adJohn Hoford int y, x; 3790b1d251973bfa748d435896fc277cb4024451adJohn Hoford 3890b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (y = 0; y < recH; y++) { 3990b1d251973bfa748d435896fc277cb4024451adJohn Hoford int sy = (recY + y) * iw; 4090b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (x = 0; x < recW; x++) { 4190b1d251973bfa748d435896fc277cb4024451adJohn Hoford int p = (recX + x + sy) * 4; 4290b1d251973bfa748d435896fc277cb4024451adJohn Hoford 4390b1d251973bfa748d435896fc277cb4024451adJohn Hoford int b = src[p + 2]; 4490b1d251973bfa748d435896fc277cb4024451adJohn Hoford int g = src[p + 1]; 4590b1d251973bfa748d435896fc277cb4024451adJohn Hoford int r = src[p]; 4690b1d251973bfa748d435896fc277cb4024451adJohn Hoford mask[x + y * recW] = ( 4790b1d251973bfa748d435896fc277cb4024451adJohn Hoford mask[x + y * recW] > 0 && (value(r, g, b) > 240) ? 1 : 0); 4890b1d251973bfa748d435896fc277cb4024451adJohn Hoford 4990b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 5090b1d251973bfa748d435896fc277cb4024451adJohn Hoford 5190b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 5290b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 5390b1d251973bfa748d435896fc277cb4024451adJohn Hoford 5490b1d251973bfa748d435896fc277cb4024451adJohn Hofordvoid findReds(unsigned char *src, unsigned char *mask, int iw, int ih, 5590b1d251973bfa748d435896fc277cb4024451adJohn Hoford short *rect) { 5690b1d251973bfa748d435896fc277cb4024451adJohn Hoford int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; 5790b1d251973bfa748d435896fc277cb4024451adJohn Hoford int y, x; 5890b1d251973bfa748d435896fc277cb4024451adJohn Hoford 5990b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (y = 0; y < recH; y++) { 6090b1d251973bfa748d435896fc277cb4024451adJohn Hoford int sy = (recY + y) * iw; 6190b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (x = 0; x < recW; x++) { 6290b1d251973bfa748d435896fc277cb4024451adJohn Hoford int p = (recX + x + sy) * 4; 6390b1d251973bfa748d435896fc277cb4024451adJohn Hoford 6490b1d251973bfa748d435896fc277cb4024451adJohn Hoford mask[x + y * recW] = ((isRed(src, p)) ? 1 : 0); 6590b1d251973bfa748d435896fc277cb4024451adJohn Hoford 6690b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 6790b1d251973bfa748d435896fc277cb4024451adJohn Hoford 6890b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 6990b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 7090b1d251973bfa748d435896fc277cb4024451adJohn Hoford 7190b1d251973bfa748d435896fc277cb4024451adJohn Hofordvoid dialateMaskIfRed(unsigned char *src, int iw, int ih, unsigned char *mask, 7290b1d251973bfa748d435896fc277cb4024451adJohn Hoford unsigned char *out, short *rect) { 7390b1d251973bfa748d435896fc277cb4024451adJohn Hoford int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; 7490b1d251973bfa748d435896fc277cb4024451adJohn Hoford int y, x; 7590b1d251973bfa748d435896fc277cb4024451adJohn Hoford 7690b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (y = 1; y < recH - 1; y++) { 7790b1d251973bfa748d435896fc277cb4024451adJohn Hoford int row = recW * y; 7890b1d251973bfa748d435896fc277cb4024451adJohn Hoford int sy = (recY + y) * iw; 7990b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (x = 1; x < recW - 1; x++) { 8090b1d251973bfa748d435896fc277cb4024451adJohn Hoford int p = (recX + x + sy) * 4; 8190b1d251973bfa748d435896fc277cb4024451adJohn Hoford 8290b1d251973bfa748d435896fc277cb4024451adJohn Hoford char b = (mask[row + x] | mask[row + x + 1] | mask[row + x - 1] 8390b1d251973bfa748d435896fc277cb4024451adJohn Hoford | mask[row + x - recW] | mask[row + x + recW]); 8490b1d251973bfa748d435896fc277cb4024451adJohn Hoford if (b != 0 && isRed(src, p)) 8590b1d251973bfa748d435896fc277cb4024451adJohn Hoford out[row + x] = 1; 8690b1d251973bfa748d435896fc277cb4024451adJohn Hoford else 8790b1d251973bfa748d435896fc277cb4024451adJohn Hoford out[row + x] = mask[row + x]; 8890b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 8990b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 9090b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 9190b1d251973bfa748d435896fc277cb4024451adJohn Hoford 9290b1d251973bfa748d435896fc277cb4024451adJohn Hofordvoid dialateMask(unsigned char *mask, unsigned char *out, int mw, int mh) { 9390b1d251973bfa748d435896fc277cb4024451adJohn Hoford int y, x; 9490b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (y = 1; y < mh - 1; y++) { 9590b1d251973bfa748d435896fc277cb4024451adJohn Hoford int row = mw * y; 9690b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (x = 1; x < mw - 1; x++) { 9790b1d251973bfa748d435896fc277cb4024451adJohn Hoford out[row + x] = (mask[row + x] | mask[row + x + 1] 9890b1d251973bfa748d435896fc277cb4024451adJohn Hoford | mask[row + x - 1] | mask[row + x - mw] 9990b1d251973bfa748d435896fc277cb4024451adJohn Hoford | mask[row + x + mw]); 10090b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 10190b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 10290b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 10390b1d251973bfa748d435896fc277cb4024451adJohn Hoford 10490b1d251973bfa748d435896fc277cb4024451adJohn Hofordvoid stuff(int r, int g, int b, unsigned char *img, int off) { 10590b1d251973bfa748d435896fc277cb4024451adJohn Hoford img[off + 2] = b; 10690b1d251973bfa748d435896fc277cb4024451adJohn Hoford img[off + 1] = g; 10790b1d251973bfa748d435896fc277cb4024451adJohn Hoford img[off] = r; 10890b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 10990b1d251973bfa748d435896fc277cb4024451adJohn Hoford 11090b1d251973bfa748d435896fc277cb4024451adJohn Hofordvoid filterRedEye(unsigned char *src, unsigned char *dest, int iw, int ih, short *rect) { 11190b1d251973bfa748d435896fc277cb4024451adJohn Hoford int recX = rect[0], recY = rect[1], recW = rect[2], recH = rect[3]; 11290b1d251973bfa748d435896fc277cb4024451adJohn Hoford unsigned char *mask1 = (unsigned char *) malloc(recW * recH); 11390b1d251973bfa748d435896fc277cb4024451adJohn Hoford unsigned char *mask2 = (unsigned char *)malloc(recW*recH); 11490b1d251973bfa748d435896fc277cb4024451adJohn Hoford int QUE_LEN = 100; 11590b1d251973bfa748d435896fc277cb4024451adJohn Hoford int y, x, i; 11690b1d251973bfa748d435896fc277cb4024451adJohn Hoford 11790b1d251973bfa748d435896fc277cb4024451adJohn Hoford rect[0] = MAX(rect[0],0); 11890b1d251973bfa748d435896fc277cb4024451adJohn Hoford rect[1] = MAX(rect[1],0); 11990b1d251973bfa748d435896fc277cb4024451adJohn Hoford rect[2] = MIN(rect[2]+rect[0],iw)-rect[0]; 12090b1d251973bfa748d435896fc277cb4024451adJohn Hoford rect[3] = MIN(rect[3]+rect[1],ih)-rect[1]; 12190b1d251973bfa748d435896fc277cb4024451adJohn Hoford 12290b1d251973bfa748d435896fc277cb4024451adJohn Hoford findReds(src, mask2, iw, ih, rect); 12390b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask2, mask1, recW, recH); 12490b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask1, mask2, recW, recH); 12590b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask2, mask1, recW, recH); 12690b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask1, mask2, recW, recH); 12790b1d251973bfa748d435896fc277cb4024451adJohn Hoford findPossible(src, mask2, iw, ih, rect); 12890b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask2, mask1, recW, recH); 12990b1d251973bfa748d435896fc277cb4024451adJohn Hoford 13090b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (i = 0; i < 12; i++) { 13190b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMaskIfRed(src, iw, ih, mask1, mask2, rect); 13290b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMaskIfRed(src, iw, ih, mask2, mask1, rect); 13390b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 13490b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask1, mask2, recW, recH); 13590b1d251973bfa748d435896fc277cb4024451adJohn Hoford dialateMask(mask2, mask1, recW, recH); 13690b1d251973bfa748d435896fc277cb4024451adJohn Hoford 13790b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (y = 3; y < recH-3; y++) { 13890b1d251973bfa748d435896fc277cb4024451adJohn Hoford int sy = (recY + y) * iw; 13990b1d251973bfa748d435896fc277cb4024451adJohn Hoford for (x = 3; x < recW-3; x++) { 14090b1d251973bfa748d435896fc277cb4024451adJohn Hoford int p = (recX + x + sy) * 4; 14190b1d251973bfa748d435896fc277cb4024451adJohn Hoford 14290b1d251973bfa748d435896fc277cb4024451adJohn Hoford int b = src[p + 2]; 14390b1d251973bfa748d435896fc277cb4024451adJohn Hoford int g = src[p + 1]; 14490b1d251973bfa748d435896fc277cb4024451adJohn Hoford int r = src[p]; 14590b1d251973bfa748d435896fc277cb4024451adJohn Hoford 14690b1d251973bfa748d435896fc277cb4024451adJohn Hoford if (mask1[x + y * recW] != 0) { 14790b1d251973bfa748d435896fc277cb4024451adJohn Hoford int m = MAX(g,b); 14890b1d251973bfa748d435896fc277cb4024451adJohn Hoford float rr = (r - m) / (float) m; 14990b1d251973bfa748d435896fc277cb4024451adJohn Hoford if (rr > .7f && g < 60 && b < 60) { 15090b1d251973bfa748d435896fc277cb4024451adJohn Hoford dest[p + 2] = (0); 15190b1d251973bfa748d435896fc277cb4024451adJohn Hoford dest[p + 1] = (0); 15290b1d251973bfa748d435896fc277cb4024451adJohn Hoford dest[p] = (0); 15390b1d251973bfa748d435896fc277cb4024451adJohn Hoford } else { 15490b1d251973bfa748d435896fc277cb4024451adJohn Hoford if (mask2[x + y * recW] != 0) { 15590b1d251973bfa748d435896fc277cb4024451adJohn Hoford stuff(r / 2, g / 2, b / 2, dest, p); 15690b1d251973bfa748d435896fc277cb4024451adJohn Hoford } else 15790b1d251973bfa748d435896fc277cb4024451adJohn Hoford stuff((2 * r) / 3, (2 * g) / 3, (2 * b) / 3, dest, p); 15890b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 15990b1d251973bfa748d435896fc277cb4024451adJohn Hoford 16090b1d251973bfa748d435896fc277cb4024451adJohn Hoford } else 16190b1d251973bfa748d435896fc277cb4024451adJohn Hoford stuff(r, g, b, dest, p); 16290b1d251973bfa748d435896fc277cb4024451adJohn Hoford 16390b1d251973bfa748d435896fc277cb4024451adJohn Hoford //dest[p + 2] = dest[p + 1] =dest[p]=src[p]; 16490b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 16590b1d251973bfa748d435896fc277cb4024451adJohn Hoford 16690b1d251973bfa748d435896fc277cb4024451adJohn Hoford } 16790b1d251973bfa748d435896fc277cb4024451adJohn Hoford 16890b1d251973bfa748d435896fc277cb4024451adJohn Hoford free(mask1); 16990b1d251973bfa748d435896fc277cb4024451adJohn Hoford free(mask2); 17090b1d251973bfa748d435896fc277cb4024451adJohn Hoford} 17190b1d251973bfa748d435896fc277cb4024451adJohn Hoford 17290b1d251973bfa748d435896fc277cb4024451adJohn Hoford 173