Home | History | Annotate | Download | only in skpdiff
      1 #!/usr/bin/python
      2 # -*- coding: utf-8 -*-
      3 
      4 from __future__ import print_function
      5 from math import *
      6 
      7 
      8 COPYRIGHT = '''/*
      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 
     16 HELP = '// To regenerate SkPMetricUtil_generated.h, simply run ./generate_pmetric_tables.py'
     17 
     18 
     19 # From Barten SPIE 1989
     20 def 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
     27 def 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
     55 def 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[]
     62 CUBE_ROOT_ACCESS_FUNCTION = '''
     63 static 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 '''
     69 def 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[]
     80 GAMMA_ACCESS_FUNCTION = '''
     81 static float get_gamma(unsigned char value) {
     82     return gGammaTable[value];
     83 }
     84 '''
     85 def 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[]
     96 TVI_ACCESS_FUNCTION = '''
     97 static 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 '''
    103 def 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[]
    114 VISUAL_MASK_DOMAIN = 4000
    115 VISUAL_MASK_ACCESS_FUNCTION = '''
    116 static float get_visual_mask(float value) {{
    117     SkASSERT(value >= 0.0f);
    118     SkASSERT(value < {}.0f);
    119     return gVisualMaskTable[(int)value];
    120 }}'''
    121 def 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 
    131 def 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 
    142 def main():
    143     pmetric_util_out = open('SkPMetricUtil_generated.h', 'wb')
    144     generate_lookup_tables(pmetric_util_out)
    145     pmetric_util_out.close()
    146 
    147 
    148 if __name__ == '__main__':
    149     main()
    150