wbalance.rs revision 572a5031a5d8602db0bec0b253428a034bd4dd59
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 "ip.rsh" 18//#pragma rs_fp_relaxed 19 20static int histR[256] = {0}, histG[256] = {0}, histB[256] = {0}; 21 22rs_allocation histogramSource; 23uint32_t histogramHeight; 24uint32_t histogramWidth; 25 26static float scaleR; 27static float scaleG; 28static float scaleB; 29 30static uchar4 estimateWhite() { 31 32 for (int i = 0; i < 256; i++) { 33 histR[i] = 0; histG[i] = 0; histB[i] = 0; 34 } 35 36 for (uint32_t i = 0; i < histogramHeight; i++) { 37 for (uint32_t j = 0; j < histogramWidth; j++) { 38 uchar4 in = rsGetElementAt_uchar4(histogramSource, j, i); 39 histR[in.r]++; 40 histG[in.g]++; 41 histB[in.b]++; 42 } 43 } 44 45 int min_r = -1, min_g = -1, min_b = -1; 46 int max_r = 0, max_g = 0, max_b = 0; 47 int sum_r = 0, sum_g = 0, sum_b = 0; 48 49 for (int i = 1; i < 255; i++) { 50 int r = histR[i]; 51 int g = histG[i]; 52 int b = histB[i]; 53 sum_r += r; 54 sum_g += g; 55 sum_b += b; 56 57 if (r>0){ 58 if (min_r < 0) min_r = i; 59 max_r = i; 60 } 61 if (g>0){ 62 if (min_g < 0) min_g = i; 63 max_g = i; 64 } 65 if (b>0){ 66 if (min_b < 0) min_b = i; 67 max_b = i; 68 } 69 } 70 71 int sum15r = 0, sum15g = 0, sum15b = 0; 72 int count15r = 0, count15g = 0, count15b = 0; 73 int tmp_r = 0, tmp_g = 0, tmp_b = 0; 74 75 for (int i = 254; i >0; i--) { 76 int r = histR[i]; 77 int g = histG[i]; 78 int b = histB[i]; 79 tmp_r += r; 80 tmp_g += g; 81 tmp_b += b; 82 83 if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) { 84 sum15r += r*i; 85 count15r += r; 86 } 87 if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) { 88 sum15g += g*i; 89 count15g += g; 90 } 91 if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) { 92 sum15b += b*i; 93 count15b += b; 94 } 95 96 } 97 98 uchar4 out; 99 100 if ((count15r>0) && (count15g>0) && (count15b>0) ){ 101 out.r = sum15r/count15r; 102 out.g = sum15g/count15g; 103 out.b = sum15b/count15b; 104 }else { 105 out.r = out.g = out.b = 255; 106 } 107 108 return out; 109 110} 111 112void prepareWhiteBalance() { 113 uchar4 estimation = estimateWhite(); 114 int minimum = min(estimation.r, min(estimation.g, estimation.b)); 115 int maximum = max(estimation.r, max(estimation.g, estimation.b)); 116 float avg = (minimum + maximum) / 2.f; 117 118 scaleR = avg/estimation.r; 119 scaleG = avg/estimation.g; 120 scaleB = avg/estimation.b; 121 122} 123 124static unsigned char contrastClamp(int c) 125{ 126 int N = 255; 127 c &= ~(c >> 31); 128 c -= N; 129 c &= (c >> 31); 130 c += N; 131 return (unsigned char) c; 132} 133 134void whiteBalanceKernel(const uchar4 *in, uchar4 *out) { 135 float Rc = in->r*scaleR; 136 float Gc = in->g*scaleG; 137 float Bc = in->b*scaleB; 138 139 out->r = contrastClamp(Rc); 140 out->g = contrastClamp(Gc); 141 out->b = contrastClamp(Bc); 142} 143