1#!/usr/bin/python
2# -*- coding: utf-8 -*-
3
4from __future__ import print_function
5from math import *
6
7
8COPYRIGHT = '''/*
9 * Copyright 2013 Google Inc.
10 *
11 * Use of this source code is governed by a BSD-style license that can be
12 * found in the LICENSE file.
13 */'''
14
15
16HELP = '// To regenerate SkPMetricUtil_generated.h, simply run ./generate_pmetric_tables.py'
17
18
19# From Barten SPIE 1989
20def contrast_sensitivity(cycles_per_degree, luminance):
21    a = 440.0 * pow(1.0 + 0.7 / luminance, -0.2)
22    b = 0.3 * pow(1 + 100.0 / luminance, 0.15)
23    return a * cycles_per_degree * exp(-b * cycles_per_degree) * sqrt(1.0 + 0.06 * exp(b * cycles_per_degree))
24
25
26# From Ward Larson Siggraph 1997
27def threshold_vs_intensity(adaptation_luminance):
28    log_lum = float('-inf') # Works in Python 2.6+
29    try:
30        log_lum = log10(adaptation_luminance)
31    except ValueError:
32        pass
33
34    x = 0.0
35
36    if log_lum < -3.94:
37        x = -2.86
38
39    elif log_lum < -1.44:
40        x = pow(0.405 * log_lum + 1.6, 2.18) - 2.86
41
42    elif log_lum < -0.0184:
43        x = log_lum - 0.395
44
45    elif log_lum < 1.9:
46        x = pow(0.249 * log_lum + 0.65, 2.7) - 0.72
47
48    else:
49        x = log_lum - 1.255
50
51    return pow(10.0, x)
52
53
54# From Daly 1993
55def visual_mask(contrast):
56    x = pow(392.498 * contrast, 0.7)
57    x = pow(0.0153 * x, 4.0)
58    return pow(1.0 + x, 0.25)
59
60
61# float gCubeRootTable[]
62CUBE_ROOT_ACCESS_FUNCTION = '''
63static float get_cube_root(float value) {
64    SkASSERT(value >= 0.0f);
65    SkASSERT(value * 1023.0f < 1024.0f);
66    return gCubeRootTable[(int)(value * 1023.0f)];
67}
68'''
69def generate_cube_root_table(stream):
70    print('static float gCubeRootTable[] = {', end='', file=stream)
71    for i in range(1024):
72        if i % 6 == 0:
73            print('\n    ', end='', file=stream)
74        print("%.10f" % pow(i / 1024.0, 1.0 / 3.0), end='f,', file=stream)
75    print('\n};', end='', file=stream)
76    print(CUBE_ROOT_ACCESS_FUNCTION, file=stream)
77
78
79# float gGammaTable[]
80GAMMA_ACCESS_FUNCTION = '''
81static float get_gamma(unsigned char value) {
82    return gGammaTable[value];
83}
84'''
85def generate_gamma_table(stream):
86    print('static float gGammaTable[] = {', end='', file=stream)
87    for i in range(256):
88        if i % 6 == 0:
89            print('\n    ', end='', file=stream)
90        print("%.10f" % pow(i / 255.0, 2.2), end='f,', file=stream)
91    print('\n};', end='', file=stream)
92    print(GAMMA_ACCESS_FUNCTION, file=stream)
93
94
95# float gTVITable[]
96TVI_ACCESS_FUNCTION = '''
97static float get_threshold_vs_intensity(float value) {
98    SkASSERT(value >= 0.0f);
99    SkASSERT(value < 100.0f);
100    return gTVITable[(int)(value * 100.0f)];
101}
102'''
103def generate_tvi_table(stream):
104    print('static float gTVITable[] = {', end='', file=stream)
105    for i in range(10000):
106        if i % 6 == 0:
107            print('\n    ', end='', file=stream)
108        print("%.10f" % threshold_vs_intensity(i / 100.0), end='f,', file=stream)
109    print('\n};', end='', file=stream)
110    print(TVI_ACCESS_FUNCTION, file=stream)
111
112
113# float gVisualMaskTable[]
114VISUAL_MASK_DOMAIN = 4000
115VISUAL_MASK_ACCESS_FUNCTION = '''
116static float get_visual_mask(float value) {{
117    SkASSERT(value >= 0.0f);
118    SkASSERT(value < {}.0f);
119    return gVisualMaskTable[(int)value];
120}}'''
121def generate_visual_mask_table(stream):
122    print('static float gVisualMaskTable[] = {', end='', file=stream)
123    for i in range(VISUAL_MASK_DOMAIN):
124        if i % 6 == 0:
125            print('\n    ', end='', file=stream)
126        print("%.10f" % visual_mask(i), end='f,', file=stream)
127    print('\n};', end='', file=stream)
128    print(VISUAL_MASK_ACCESS_FUNCTION.format(VISUAL_MASK_DOMAIN), file=stream)
129
130
131def generate_lookup_tables(stream):
132    print(COPYRIGHT, file=stream)
133    print(HELP, file=stream)
134    print('namespace SkPMetricUtil {', file=stream)
135    generate_cube_root_table(stream)
136    generate_gamma_table(stream)
137    generate_tvi_table(stream)
138    generate_visual_mask_table(stream)
139    print('}', file=stream)
140
141
142def main():
143    pmetric_util_out = open('SkPMetricUtil_generated.h', 'wb')
144    generate_lookup_tables(pmetric_util_out)
145    pmetric_util_out.close()
146
147
148if __name__ == '__main__':
149    main()
150