shadows.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 double shadowFilterMap[] = {
21    -0.00591,  0.0001,
22     1.16488,  0.01668,
23    -0.18027, -0.06791,
24    -0.12625,  0.09001,
25     0.15065, -0.03897
26};
27
28static double poly[] = {
29    0., 0.,
30    0., 0.,
31    0.
32};
33
34static const int ABITS = 4;
35static const int HSCALE = 256;
36static const int k1=255 << ABITS;
37static const int k2=HSCALE << ABITS;
38
39static double fastevalPoly(double *poly,int n, double x){
40
41    double f =x;
42    double sum = poly[0]+poly[1]*f;
43    int i;
44    for (i = 2; i < n; i++) {
45        f*=x;
46        sum += poly[i]*f;
47    }
48    return sum;
49}
50
51static ushort3 rgb2hsv( uchar4 rgb)
52{
53    int iMin,iMax,chroma;
54
55    int ri = rgb.r;
56    int gi = rgb.g;
57    int bi = rgb.b;
58    short rv,rs,rh;
59
60    if (ri > gi) {
61        iMax = max (ri, bi);
62        iMin = min (gi, bi);
63    } else {
64        iMax = max (gi, bi);
65        iMin = min (ri, bi);
66    }
67
68    chroma = iMax - iMin;
69    // set value
70    rv = (short)( iMax << ABITS);
71
72    // set saturation
73    if (rv == 0)
74        rs = 0;
75    else
76        rs = (short)((k1*chroma)/iMax);
77
78    // set hue
79    if (rs == 0)
80        rh = 0;
81    else {
82        if ( ri == iMax ) {
83            rh  = (short)( (k2*(6*chroma+gi - bi))/(6*chroma));
84            if (rh >= k2) rh -= k2;
85        } else if (gi  == iMax)
86            rh  = (short)( (k2*(2*chroma+bi - ri ))/(6*chroma));
87        else // (bi == iMax )
88                    rh  = (short)( (k2*(4*chroma+ri - gi ))/(6*chroma));
89    }
90
91    ushort3 out;
92    out.x = rv;
93    out.y = rs;
94    out.z = rh;
95    return out;
96}
97
98static uchar4 hsv2rgb(ushort3 hsv)
99{
100    int ABITS = 4;
101    int HSCALE = 256;
102    int m;
103    int H,X,ih,is,iv;
104    int k1=255<<ABITS;
105    int k2=HSCALE<<ABITS;
106    int k3=1<<(ABITS-1);
107    int rr=0;
108    int rg=0;
109    int rb=0;
110    short cv = hsv.x;
111    short cs = hsv.y;
112    short ch = hsv.z;
113
114    // set chroma and min component value m
115    //chroma = ( cv * cs )/k1;
116    //m = cv - chroma;
117    m = ((int)cv*(k1 - (int)cs ))/k1;
118
119    // chroma  == 0 <-> cs == 0 --> m=cv
120    if (cs == 0) {
121        rb = ( rg = ( rr =( cv >> ABITS) ));
122    } else {
123        ih=(int)ch;
124        is=(int)cs;
125        iv=(int)cv;
126
127        H = (6*ih)/k2;
128        X = ((iv*is)/k2)*(k2- abs(6*ih- 2*(H>>1)*k2 - k2)) ;
129
130        // removing additional bits --> unit8
131        X=( (X+iv*(k1 - is ))/k1 + k3 ) >> ABITS;
132        m=m >> ABITS;
133
134        // ( chroma + m ) --> cv ;
135        cv=(short) (cv >> ABITS);
136        switch (H) {
137        case 0:
138            rr = cv;
139            rg = X;
140            rb = m;
141            break;
142        case 1:
143            rr = X;
144            rg = cv;
145            rb = m;
146            break;
147        case 2:
148            rr = m;
149            rg = cv;
150            rb = X;
151            break;
152        case 3:
153            rr = m;
154            rg = X;
155            rb = cv;
156            break;
157        case 4:
158            rr = X;
159            rg = m;
160            rb = cv;
161            break;
162        case 5:
163            rr = cv;
164            rg = m ;
165            rb = X;
166            break;
167        }
168    }
169
170    uchar4 rgb;
171
172    rgb.r =  rr;
173    rgb.g =  rg;
174    rgb.b =  rb;
175
176    return rgb;
177}
178
179void prepareShadows(float scale) {
180    double s = (scale>=0)?scale:scale/5;
181    for (int i = 0; i < 5; i++) {
182        poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
183    }
184}
185
186void shadowsKernel(const uchar4 *in, uchar4 *out) {
187    ushort3 hsv = rgb2hsv(*in);
188    double v = (fastevalPoly(poly,5,hsv.x/4080.)*4080);
189    if (v>4080) v = 4080;
190    hsv.x = (unsigned short) ((v>0)?v:0);
191    *out = hsv2rgb(hsv);
192}
193