summaryrefslogtreecommitdiffstats
path: root/tests/RenderScriptTests/LivePreview/src/com/android/rs/livepreview/yuv.rs
blob: 6057effe2f6c91f140a8919296a1ca7d63a4a8ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

#pragma version(1)
#pragma rs java_package_name(com.android.rs.livepreview)
#pragma rs_fp_relaxed

uchar *gYuvIn;

static int gWidth;
static int gHeight;
static uchar crossProcess_tableR[256];
static uchar crossProcess_tableG[256];
static uchar crossProcess_tableB[256];
static uchar vignette_table[512];


static float4 crossProcess(float4 color) {
    float4 ncolor = 0.f;
    float v;

    if (color.r < 0.5f) {
        v = color.r;
        ncolor.r = 4.0f * v * v * v;
    } else {
        v = 1.0f - color.r;
        ncolor.r = 1.0f - (4.0f * v * v * v);
    }

    if (color.g < 0.5f) {
        v = color.g;
        ncolor.g = 2.0f * v * v;
    } else {
        v = 1.0f - color.g;
        ncolor.g = 1.0f - (2.0f * v * v);
    }

    ncolor.b = color.b * 0.5f + 0.25f;
    ncolor.a = color.a;
    return ncolor;
}

static uchar4 crossProcess_i(uchar4 color) {
    uchar4 ncolor = color;
    ncolor.r = crossProcess_tableR[color.r];
    ncolor.g = crossProcess_tableG[color.g];
    ncolor.b = crossProcess_tableB[color.b];
    return ncolor;
}


float temp = 0.2f;
static float4 colortemp(float4 color) {
    float4 new_color = color;
    float4 t = color * ((float4)1.0f - color) * temp;

    new_color.r = color.r + t.r;
    new_color.b = color.b - t.b;
    if (temp > 0.0f) {
        color.g = color.g + t.g * 0.25f;
    }
    float max_value = max(new_color.r, max(new_color.g, new_color.b));
    if (max_value > 1.0f) {
        new_color /= max_value;
    }

    return new_color;
}


static float vignette_dist_mod;
int2 vignette_half_dims;
static uchar4 vignette(uchar4 color, uint32_t x, uint32_t y) {
    int2 xy = {x, y};
    xy -= vignette_half_dims;
    xy *= xy;

    float d = vignette_dist_mod * (xy.x + xy.y);
    ushort4 c = convert_ushort4(color);
    c *= vignette_table[(int)d];
    c >>= (ushort4)8;
    return convert_uchar4(c);
}

void root(uchar4 *out, uint32_t x, uint32_t y) {
    uchar Y = gYuvIn[(y * gWidth) + x];
    uchar *uv = &gYuvIn[gWidth * gHeight];
    uv += (((x>>1)<<1) + (y>>1) * gWidth);

    uchar4 p = rsYuvToRGBA_uchar4(Y, uv[1], uv[0]);
    p = crossProcess_i(p);
    p = vignette(p, x, y);

    out->rgba = p;
    out->a = 0xff;
}

float vignetteScale = 0.5f;
float vignetteShade = 0.85f;

static void precompute() {
    for(int i=0; i <256; i++) {
        float4 f = ((float)i) / 255.f;
        float4 res = crossProcess(f);
        res = colortemp(res);
        crossProcess_tableR[i] = (uchar)(res.r * 255.f);
        crossProcess_tableG[i] = (uchar)(res.g * 255.f);
        crossProcess_tableB[i] = (uchar)(res.b * 255.f);
    }

    for(int i=0; i <512; i++) {
        const float slope = 20.0f;
        float f = ((float)i) / 511.f;

        float range = 1.30f - sqrt(vignetteScale) * 0.7f;
        float lumen = vignetteShade / (1.0f + exp((sqrt(f) - range) * slope)) + (1.0f - vignetteShade);
        lumen = clamp(lumen, 0.f, 1.f);

        vignette_table[i] = (uchar)(lumen * 255.f + 0.5f);
    }
}

void init() {
    precompute();
}

void setSize(int w, int h) {
    gWidth = w;
    gHeight = h;
    vignette_half_dims = (int2){w / 2, h / 2};
    vignette_dist_mod = 512.f;
    vignette_dist_mod /= (float)(w*w + h*h) / 4.f;

}