1bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford/*
2bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * Copyright (C) 2012 Unknown
3bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford *
4bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * Licensed under the Apache License, Version 2.0 (the "License");
5bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * you may not use this file except in compliance with the License.
6bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * You may obtain a copy of the License at
7bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford *
8bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford *      http://www.apache.org/licenses/LICENSE-2.0
9bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford *
10bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * Unless required by applicable law or agreed to in writing, software
11bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * distributed under the License is distributed on an "AS IS" BASIS,
12bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * See the License for the specific language governing permissions and
14bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford * limitations under the License.
15bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford */
16bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
17bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford#pragma version(1)
18bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford#pragma rs java_package_name(com.android.gallery3d.filtershow.filters)
19bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
20bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford#define MAX_CHANELS 7
21bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford#define MAX_HUE 4096
22bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const int ABITS = 4;
23bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const int HSCALE = 256;
24bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const int k1=255 << ABITS;
25bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const int k2=HSCALE << ABITS;
26bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
27bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const float Rf = 0.2999f;
28bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const float Gf = 0.587f;
29bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic const float Bf = 0.114f;
30bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
31bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordrs_matrix3x3 colorMatrix_min;
32bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordrs_matrix3x3 colorMatrix_max;
33bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
34bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordint mNumberOfLines;
35bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford// input data
36bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordint saturation[MAX_CHANELS];
37bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordfloat sat[MAX_CHANELS];
38bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
39bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordfloat satLut[MAX_HUE];
40bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford// generated data
41bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
42bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
43bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordvoid setupGradParams() {
44bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
45bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int master = saturation[0];
46bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int max = master+saturation[1];
47bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int min = max;
48bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
49bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    // calculate the minimum and maximum saturation
50bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    for (int i = 1; i < MAX_CHANELS; i++) {
51bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       int v = master+saturation[i];
52bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       if (max < v) {
53bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford         max = v;
54bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       }
55bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       else if (min > v) {
56bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford         min = v;
57bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       }
58bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
59bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    // generate a lookup table for all hue 0 to 4K  which goes from 0 to 1 0=min sat 1 = max sat
60bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    min = min - 1;
61bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    for(int i = 0; i < MAX_HUE ; i++) {
62bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       float p =  i * 6 / (float)MAX_HUE;
63bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       int ip = ((int)(p + .5f)) % 6;
64bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       int v = master + saturation[ip + 1];
65bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford       satLut[i] = (v - min)/(float)(max - min);
66bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
67bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
68bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float S = 1 + max / 100.f;
69bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float MS = 1 - S;
70bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float Rt = Rf * MS;
71bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float Gt = Gf * MS;
72bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float Bt = Bf * MS;
73bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float b = 1.f;
74bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
75bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    // Generate 2 color matrix one at min sat and one at max
76bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 0, 0, b * (Rt + S));
77bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 1, 0, b * Gt);
78bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 2, 0, b * Bt);
79bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 0, 1, b * Rt);
80bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 1, 1, b * (Gt + S));
81bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 2, 1, b * Bt);
82bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 0, 2, b * Rt);
83bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 1, 2, b * Gt);
84bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_max, 2, 2, b * (Bt + S));
85bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
86bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    S = 1 + min / 100.f;
87bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    MS = 1-S;
88bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    Rt = Rf * MS;
89bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    Gt = Gf * MS;
90bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    Bt = Bf * MS;
91bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    b = 1;
92bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
93bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 0, 0, b * (Rt + S));
94bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 1, 0, b * Gt);
95bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 2, 0, b * Bt);
96bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 0, 1, b * Rt);
97bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 1, 1, b * (Gt + S));
98bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 2, 1, b * Bt);
99bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 0, 2, b * Rt);
100bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 1, 2, b * Gt);
101bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rsMatrixSet(&colorMatrix_min, 2, 2, b * (Bt + S));
102bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford}
103bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
104bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hofordstatic ushort rgb2hue( uchar4 rgb)
105bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford{
106bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int iMin,iMax,chroma;
107bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
108bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int ri = rgb.r;
109bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int gi = rgb.g;
110bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int bi = rgb.b;
111bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    short rv,rs,rh;
112bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
113bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    if (ri > gi) {
114bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        iMax = max (ri, bi);
115bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        iMin = min (gi, bi);
116bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    } else {
117bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        iMax = max (gi, bi);
118bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        iMin = min (ri, bi);
119bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
120bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
121bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rv = (short) (iMax << ABITS);
122bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
123bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    if (rv == 0) {
124bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        return 0;
125bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
126bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
127bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    chroma = iMax - iMin;
128bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    rs = (short) ((k1 * chroma) / iMax);
129bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    if (rs == 0) {
130bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        return 0;
131bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
132bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
133bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    if ( ri == iMax ) {
134bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        rh  = (short) ((k2 * (6 * chroma + gi - bi))/(6 * chroma));
135bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        if (rh >= k2) {
136bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford           rh -= k2;
137bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        }
138bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        return rh;
139bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
140bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
141bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    if (gi  == iMax) {
142bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        return(short) ((k2 * (2 * chroma + bi - ri)) / (6 * chroma));
143bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    }
144bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
145bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    return (short) ((k2 * (4 * chroma + ri - gi)) / (6 * chroma));
146bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford}
147bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
148bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoforduchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x,
149bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    uint32_t y) {
150bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float4 pixel = rsUnpackColor8888(in);
151bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
152bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float4 wsum = pixel;
153bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    int hue = rgb2hue(in);
154bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
155bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    float t = satLut[hue];
156bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford        pixel.xyz = rsMatrixMultiply(&colorMatrix_min ,pixel.xyz) * (1 - t) +
157bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford            t * (rsMatrixMultiply(&colorMatrix_max ,pixel.xyz));
158bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford
159bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    pixel.a = 1.0f;
160bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford    return rsPackColorTo8888(clamp(pixel, 0.f, 1.0f));
161bc8e077e77cf6f0dda8efd8318b8a8e7eda16f61John Hoford}