1 
2 #pragma version(1)
3 #pragma rs java_package_name(com.android.rs.livepreview)
4 //#pragma rs_fp_relaxed
5 
6 static int gWidth;
7 static int gHeight;
8 static uchar crossProcess_tableR[256];
9 static uchar crossProcess_tableG[256];
10 static uchar crossProcess_tableB[256];
11 static uchar vignette_table[512];
12 
13 
14 static float4 crossProcess(float4 color) {
15     float4 ncolor = 0.f;
16     float v;
17 
18     if (color.r < 0.5f) {
19         v = color.r;
20         ncolor.r = 4.0f * v * v * v;
21     } else {
22         v = 1.0f - color.r;
23         ncolor.r = 1.0f - (4.0f * v * v * v);
24     }
25 
26     if (color.g < 0.5f) {
27         v = color.g;
28         ncolor.g = 2.0f * v * v;
29     } else {
30         v = 1.0f - color.g;
31         ncolor.g = 1.0f - (2.0f * v * v);
32     }
33 
34     ncolor.b = color.b * 0.5f + 0.25f;
35     ncolor.a = color.a;
36     return ncolor;
37 }
38 
39 static uchar4 crossProcess_i(uchar4 color) {
40     uchar4 ncolor = color;
41     ncolor.r = crossProcess_tableR[color.r];
42     ncolor.g = crossProcess_tableG[color.g];
43     ncolor.b = crossProcess_tableB[color.b];
44     return ncolor;
45 }
46 
47 
48 float temp = 0.2f;
49 static float4 colortemp(float4 color) {
50     float4 new_color = color;
51     float4 t = color * ((float4)1.0f - color) * temp;
52 
53     new_color.r = color.r + t.r;
54     new_color.b = color.b - t.b;
55     if (temp > 0.0f) {
56         color.g = color.g + t.g * 0.25f;
57     }
58     float max_value = max(new_color.r, max(new_color.g, new_color.b));
59     if (max_value > 1.0f) {
60         new_color /= max_value;
61     }
62 
63     return new_color;
64 }
65 
66 
67 static float vignette_dist_mod;
68 int2 vignette_half_dims;
69 static uchar4 vignette(uchar4 color, uint32_t x, uint32_t y) {
70     int2 xy = {x, y};
71     xy -= vignette_half_dims;
72     xy *= xy;
73 
74     float d = vignette_dist_mod * (xy.x + xy.y);
75     ushort4 c = convert_ushort4(color);
76     c *= vignette_table[(int)d];
77     c >>= (ushort4)8;
78     return convert_uchar4(c);
79 }
80 
81 void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
82     uchar4 p;
83     p = crossProcess_i(*in);
84     p = vignette(p, x, y);
85 
86     out->rgba = p;
87     out->a = 0xff;
88 }
89 
90 float vignetteScale = 0.5f;
91 float vignetteShade = 0.85f;
92 
93 static void precompute() {
94     for(int i=0; i <256; i++) {
95         float4 f = ((float)i) / 255.f;
96         float4 res = crossProcess(f);
97         res = colortemp(res);
98         crossProcess_tableR[i] = (uchar)(res.r * 255.f);
99         crossProcess_tableG[i] = (uchar)(res.g * 255.f);
100         crossProcess_tableB[i] = (uchar)(res.b * 255.f);
101     }
102 
103     for(int i=0; i <512; i++) {
104         const float slope = 20.0f;
105         float f = ((float)i) / 511.f;
106 
107         float range = 1.30f - sqrt(vignetteScale) * 0.7f;
108         float lumen = vignetteShade / (1.0f + exp((sqrt(f) - range) * slope)) + (1.0f - vignetteShade);
109         lumen = clamp(lumen, 0.f, 1.f);
110 
111         vignette_table[i] = (uchar)(lumen * 255.f + 0.5f);
112     }
113 }
114 
115 void init() {
116     precompute();
117 }
118 
119 void setSize(int w, int h) {
120     gWidth = w;
121     gHeight = h;
122     vignette_half_dims = (int2){w / 2, h / 2};
123     vignette_dist_mod = 512.f;
124     vignette_dist_mod /= (float)(w*w + h*h) / 4.f;
125 
126 }
127