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