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