1572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams/*
2572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Copyright (C) 2012 The Android Open Source Project
3572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
4572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Licensed under the Apache License, Version 2.0 (the "License");
5572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * you may not use this file except in compliance with the License.
6572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * You may obtain a copy of the License at
7572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
8572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *      http://www.apache.org/licenses/LICENSE-2.0
9572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams *
10572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * Unless required by applicable law or agreed to in writing, software
11572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * distributed under the License is distributed on an "AS IS" BASIS,
12572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * See the License for the specific language governing permissions and
14572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams * limitations under the License.
15572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams */
16572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
17572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams#include "ip.rsh"
18dc08c6d13a68aa8fd35ce5922c1c98b915f35f08Jason Sams#pragma rs_fp_relaxed
19572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
206b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Samsrs_allocation histogramValues;
21ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Samsstatic float3 scale;
22572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
23572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsstatic uchar4 estimateWhite() {
24572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int min_r = -1, min_g = -1, min_b = -1;
25572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int max_r =  0, max_g =  0, max_b =  0;
26572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int sum_r =  0, sum_g =  0, sum_b =  0;
27572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
28572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    for (int i = 1; i < 255; i++) {
296b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int4 hv = rsGetElementAt_int4(histogramValues, i);
306b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int r = hv.r;
316b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int g = hv.g;
326b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int b = hv.b;
33572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        sum_r += r;
34572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        sum_g += g;
35572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        sum_b += b;
36572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
37572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (r>0){
38572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (min_r < 0) min_r = i;
39572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            max_r = i;
40572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
41572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (g>0){
42572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (min_g < 0) min_g = i;
43572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            max_g = i;
44572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
45572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if (b>0){
46572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            if (min_b < 0) min_b = i;
47572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            max_b = i;
48572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
49572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
50572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
51572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int sum15r = 0, sum15g = 0, sum15b = 0;
52572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int count15r = 0, count15g = 0, count15b = 0;
53572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int tmp_r = 0, tmp_g = 0, tmp_b = 0;
54572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
55572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    for (int i = 254; i >0; i--) {
566b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int4 hv = rsGetElementAt_int4(histogramValues, i);
576b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int r = hv.r;
586b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int g = hv.g;
596b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams        int b = hv.b;
60572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        tmp_r += r;
61572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        tmp_g += g;
62572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        tmp_b += b;
63572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
64572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if ((tmp_r > sum_r/20) && (tmp_r < sum_r/5)) {
65572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            sum15r += r*i;
66572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            count15r += r;
67572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
68572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if ((tmp_g > sum_g/20) && (tmp_g < sum_g/5)) {
69572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            sum15g += g*i;
70572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            count15g += g;
71572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
72572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        if ((tmp_b > sum_b/20) && (tmp_b < sum_b/5)) {
73572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            sum15b += b*i;
74572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams            count15b += b;
75572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        }
76572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
77572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
78572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
79572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    uchar4 out;
80572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
81572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    if ((count15r>0) && (count15g>0) && (count15b>0) ){
82572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        out.r = sum15r/count15r;
83572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        out.g = sum15g/count15g;
84572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        out.b = sum15b/count15b;
85572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }else {
86572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams        out.r = out.g = out.b = 255;
87572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    }
88572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
89572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    return out;
90572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
91572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
92572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
93572a5031a5d8602db0bec0b253428a034bd4dd59Jason Samsvoid prepareWhiteBalance() {
94572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    uchar4 estimation = estimateWhite();
95572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int minimum = min(estimation.r, min(estimation.g, estimation.b));
96572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    int maximum = max(estimation.r, max(estimation.g, estimation.b));
97572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams    float avg = (minimum + maximum) / 2.f;
98572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
996b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams    scale.r =  avg / estimation.r;
1006b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams    scale.g =  avg / estimation.g;
1016b9cb41efc17c2731a2762c1ac6071ba5684af63Jason Sams    scale.b =  avg / estimation.b;
102572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
103572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
104025b5f82971c431eb22df3c9d0f00b3cbe426bdbChris Wailesuchar4 RS_KERNEL whiteBalanceKernel(uchar4 in) {
105ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    float3 t = convert_float3(in.rgb);
106ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    t *= scale;
107ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    t = min(t, 255.f);
108572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams
109ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    uchar4 out;
110ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    out.rgb = convert_uchar3(t);
111ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    out.a = 255;
112ab84c3968abce348c212bc9d466c534bc2a03cd6Jason Sams    return out;
113572a5031a5d8602db0bec0b253428a034bd4dd59Jason Sams}
114