158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger#!/usr/bin/python 258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# -*- coding: utf-8 -*- 358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerfrom __future__ import print_function 558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerfrom math import * 658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerCOPYRIGHT = '''/* 958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Copyright 2013 Google Inc. 1058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * 1158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 1258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger * found in the LICENSE file. 1358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger */''' 1458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 1558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 1658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerHELP = '// To regenerate SkPMetricUtil_generated.h, simply run ./generate_pmetric_tables.py' 1758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 1858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 1958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# From Barten SPIE 1989 2058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef contrast_sensitivity(cycles_per_degree, luminance): 2158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger a = 440.0 * pow(1.0 + 0.7 / luminance, -0.2) 2258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger b = 0.3 * pow(1 + 100.0 / luminance, 0.15) 2358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return a * cycles_per_degree * exp(-b * cycles_per_degree) * sqrt(1.0 + 0.06 * exp(b * cycles_per_degree)) 2458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 2558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 2658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# From Ward Larson Siggraph 1997 2758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef threshold_vs_intensity(adaptation_luminance): 2858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger log_lum = float('-inf') # Works in Python 2.6+ 2958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger try: 3058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger log_lum = log10(adaptation_luminance) 3158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger except ValueError: 3258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger pass 3358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = 0.0 3558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if log_lum < -3.94: 3758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = -2.86 3858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 3958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger elif log_lum < -1.44: 4058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = pow(0.405 * log_lum + 1.6, 2.18) - 2.86 4158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 4258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger elif log_lum < -0.0184: 4358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = log_lum - 0.395 4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 4558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger elif log_lum < 1.9: 4658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = pow(0.249 * log_lum + 0.65, 2.7) - 0.72 4758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 4858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger else: 4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = log_lum - 1.255 5058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return pow(10.0, x) 5258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# From Daly 1993 5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef visual_mask(contrast): 5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = pow(392.498 * contrast, 0.7) 5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger x = pow(0.0153 * x, 4.0) 5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return pow(1.0 + x, 0.25) 5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# float gCubeRootTable[] 6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerCUBE_ROOT_ACCESS_FUNCTION = ''' 6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic float get_cube_root(float value) { 6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(value >= 0.0f); 6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(value * 1023.0f < 1024.0f); 6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return gCubeRootTable[(int)(value * 1023.0f)]; 6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger''' 6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef generate_cube_root_table(stream): 7058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('static float gCubeRootTable[] = {', end='', file=stream) 7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for i in range(1024): 7258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if i % 6 == 0: 7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n ', end='', file=stream) 7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print("%.10f" % pow(i / 1024.0, 1.0 / 3.0), end='f,', file=stream) 7558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n};', end='', file=stream) 7658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print(CUBE_ROOT_ACCESS_FUNCTION, file=stream) 7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# float gGammaTable[] 8058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerGAMMA_ACCESS_FUNCTION = ''' 8158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic float get_gamma(unsigned char value) { 8258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return gGammaTable[value]; 8358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 8458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger''' 8558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef generate_gamma_table(stream): 8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('static float gGammaTable[] = {', end='', file=stream) 8758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for i in range(256): 8858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if i % 6 == 0: 8958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n ', end='', file=stream) 9058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print("%.10f" % pow(i / 255.0, 2.2), end='f,', file=stream) 9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n};', end='', file=stream) 9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print(GAMMA_ACCESS_FUNCTION, file=stream) 9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 9558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# float gTVITable[] 9658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerTVI_ACCESS_FUNCTION = ''' 9758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic float get_threshold_vs_intensity(float value) { 9858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(value >= 0.0f); 9958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(value < 100.0f); 10058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return gTVITable[(int)(value * 100.0f)]; 10158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 10258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger''' 10358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef generate_tvi_table(stream): 10458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('static float gTVITable[] = {', end='', file=stream) 10558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for i in range(10000): 10658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if i % 6 == 0: 10758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n ', end='', file=stream) 10858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print("%.10f" % threshold_vs_intensity(i / 100.0), end='f,', file=stream) 10958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n};', end='', file=stream) 11058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print(TVI_ACCESS_FUNCTION, file=stream) 11158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 11258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 11358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger# float gVisualMaskTable[] 11458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerVISUAL_MASK_DOMAIN = 4000 11558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerVISUAL_MASK_ACCESS_FUNCTION = ''' 11658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerstatic float get_visual_mask(float value) {{ 11758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(value >= 0.0f); 11858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(value < {}.0f); 11958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return gVisualMaskTable[(int)value]; 12058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger}}''' 12158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef generate_visual_mask_table(stream): 12258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('static float gVisualMaskTable[] = {', end='', file=stream) 12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger for i in range(VISUAL_MASK_DOMAIN): 12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if i % 6 == 0: 12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n ', end='', file=stream) 12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print("%.10f" % visual_mask(i), end='f,', file=stream) 12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('\n};', end='', file=stream) 12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print(VISUAL_MASK_ACCESS_FUNCTION.format(VISUAL_MASK_DOMAIN), file=stream) 12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef generate_lookup_tables(stream): 13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print(COPYRIGHT, file=stream) 13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print(HELP, file=stream) 13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('namespace SkPMetricUtil {', file=stream) 13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger generate_cube_root_table(stream) 13658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger generate_gamma_table(stream) 13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger generate_tvi_table(stream) 13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger generate_visual_mask_table(stream) 13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger print('}', file=stream) 14058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdef main(): 14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger pmetric_util_out = open('SkPMetricUtil_generated.h', 'wb') 14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger generate_lookup_tables(pmetric_util_out) 14558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger pmetric_util_out.close() 14658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 14758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 14858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerif __name__ == '__main__': 14958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger main() 150