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