Home | History | Annotate | Download | only in image
      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 
     20 static float shadowFilterMap[] = {
     21     -0.00591f,  0.0001f,
     22      1.16488f,  0.01668f,
     23     -0.18027f, -0.06791f,
     24     -0.12625f,  0.09001f,
     25      0.15065f, -0.03897f
     26 };
     27 
     28 static float poly[] = {
     29     0.f, 0.f,
     30     0.f, 0.f,
     31     0.f
     32 };
     33 
     34 static const int ABITS = 4;
     35 static const int HSCALE = 256;
     36 static const int k1=255 << ABITS;
     37 static const int k2=HSCALE << ABITS;
     38 
     39 static float fastevalPoly(float *poly,int n, float x){
     40 
     41     float f =x;
     42     float 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 
     51 static 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 
     98 static 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 
    179 void prepareShadows(float scale) {
    180     float s = (scale>=0) ? scale : scale / 5.f;
    181     for (int i = 0; i < 5; i++) {
    182         poly[i] = fastevalPoly(shadowFilterMap+i*2,2 , s);
    183     }
    184 }
    185 
    186 uchar4 RS_KERNEL shadowsKernel(uchar4 in) {
    187     ushort3 hsv = rgb2hsv(in);
    188     float v = (fastevalPoly(poly, 5, hsv.x * (1.f / 4080.f)) * 4080.f);
    189     hsv.x = (unsigned short) clamp(v, 0.f, 4080.f);
    190     return hsv2rgb(hsv);
    191 }
    192