X-Git-Url: http://users.mur.at/ms/git/gitweb/?a=blobdiff_plain;f=aces_1.0.0%2Fpython%2Faces_ocio%2Fcreate_aces_colorspaces.py;h=54b6708cdc902bebe077b353b53ffe171ec178c8;hb=24460c4f42d9e44101d414ef15579e5f7d250bb7;hp=606b160f60ad492c26602f3a28beb8a36e96d15c;hpb=e5585b6c874b61aaad7a48bfc1d2092a77f403d9;p=OpenColorIO-Configs.git diff --git a/aces_1.0.0/python/aces_ocio/create_aces_colorspaces.py b/aces_1.0.0/python/aces_ocio/create_aces_colorspaces.py index 606b160..54b6708 100644 --- a/aces_1.0.0/python/aces_ocio/create_aces_colorspaces.py +++ b/aces_1.0.0/python/aces_ocio/create_aces_colorspaces.py @@ -5,21 +5,26 @@ Implements support for *ACES* colorspaces conversions and transfer functions. """ -import array +from __future__ import division + import math import numpy import os import pprint import string +import shutil import PyOpenColorIO as ocio -import aces_ocio.generate_lut as genlut from aces_ocio.generate_lut import ( generate_1d_LUT_from_CTL, generate_3d_LUT_from_CTL, write_SPI_1d) -from aces_ocio.utilities import ColorSpace, mat44_from_mat33, sanitize_path, compact +from aces_ocio.utilities import ( + ColorSpace, + mat44_from_mat33, + sanitize, + compact) __author__ = 'ACES Developers' @@ -29,65 +34,110 @@ __maintainer__ = 'ACES Developers' __email__ = 'aces@oscars.org' __status__ = 'Production' -__all__ = ['create_ACEScc', +__all__ = ['ACES_AP1_TO_AP0', + 'ACES_AP0_TO_XYZ', + 'create_ACES', + 'create_ACEScc', 'create_ACESproxy', 'create_ACEScg', 'create_ADX', - 'create_generic_log', 'create_ACES_LMT', - 'create_lmts', 'create_ACES_RRT_plus_ODT', - 'create_odts', - 'create_aces', + 'create_generic_log', + 'create_LMTs', + 'create_ODTs', 'get_transform_info', - 'get_ODT_info', - 'get_LMT_info', + 'get_ODTs_info', + 'get_LMTs_info', 'create_colorspaces'] -# ------------------------------------------------------------------------- -# *Matrices* -# ------------------------------------------------------------------------- - -# Matrix converting *ACES AP1* primaries to *AP0*. -ACES_AP1_to_AP0 = [0.6954522414, 0.1406786965, 0.1638690622, +# Matrix converting *ACES AP1* primaries to *ACES AP0*. +ACES_AP1_TO_AP0 = [0.6954522414, 0.1406786965, 0.1638690622, 0.0447945634, 0.8596711185, 0.0955343182, -0.0055258826, 0.0040252103, 1.0015006723] +# Matrix converting *ACES AP0* primaries to *ACES AP1*. +ACES_AP0_TO_AP1 = [1.4514393161, -0.2365107469, -0.2149285693, + -0.0765537734, 1.1762296998, -0.0996759264, + 0.0083161484, -0.0060324498, 0.9977163014] + # Matrix converting *ACES AP0* primaries to *XYZ*. -ACES_AP0_to_XYZ = [0.9525523959, 0.0000000000, 0.0000936786, +ACES_AP0_TO_XYZ = [0.9525523959, 0.0000000000, 0.0000936786, 0.3439664498, 0.7281660966, -0.0721325464, 0.0000000000, 0.0000000000, 1.0088251844] -# ------------------------------------------------------------------------- -# *ACEScc* -# ------------------------------------------------------------------------- -def create_ACEScc(aces_CTL_directory, - lut_directory, +# Matrix converting *ACES AP0* primaries to *XYZ*. +ACES_XYZ_TO_AP0 = [1.0498110175, 0.0000000000, -0.0000974845, + -0.4959030231, 1.3733130458, 0.0982400361, + 0.0000000000, 0.0000000000, 0.9912520182] + + +def create_ACES(): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + # Defining the reference colorspace. + aces2065_1 = ColorSpace('ACES2065-1') + aces2065_1.description = ( + 'The Academy Color Encoding System reference color space') + aces2065_1.equality_group = '' + aces2065_1.aliases = ["lin_ap0", "aces"] + aces2065_1.family = 'ACES' + aces2065_1.is_data = False + aces2065_1.allocation_type = ocio.Constants.ALLOCATION_LG2 + aces2065_1.allocation_vars = [-8, 5, 0.00390625] + + return aces2065_1 + + +def create_ACEScc(aces_ctl_directory, + lut_directory, lut_resolution_1d, cleanup, name='ACEScc', - min_value=0.0, - max_value=1.0, - input_scale=1.0): + min_value=0, + max_value=1, + input_scale=1): + """ + Creates the *ACEScc* colorspace. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + Colorspace + *ACEScc* colorspace. + """ + cs = ColorSpace(name) cs.description = 'The %s color space' % name cs.aliases = ["acescc_ap1"] cs.equality_group = '' cs.family = 'ACES' cs.is_data = False + cs.allocation_type = ocio.Constants.ALLOCATION_UNIFORM + cs.allocation_vars = [min_value, max_value] - ctls = [os.path.join(aces_CTL_directory, + ctls = [os.path.join(aces_ctl_directory, 'ACEScc', - 'ACEScsc.ACEScc_to_ACES.a1.0.0.ctl'), - # This transform gets back to the *AP1* primaries. - # Useful as the 1d LUT is only covering the transfer function. - # The primaries switch is covered by the matrix below: - os.path.join(aces_CTL_directory, - 'ACEScg', - 'ACEScsc.ACES_to_ACEScg.a1.0.0.ctl')] - lut = '%s_to_ACES.spi1d' % name + 'ACEScsc.ACEScc_to_ACES.a1.0.0.ctl')] + lut = '%s_to_linear.spi1d' % name - lut = sanitize_path(lut) + lut = sanitize(lut) generate_1d_LUT_from_CTL( os.path.join(lut_directory, lut), @@ -95,12 +145,13 @@ def create_ACEScc(aces_CTL_directory, lut_resolution_1d, 'float', input_scale, - 1.0, - {}, + 1, + {'transferFunctionOnly':1}, cleanup, - aces_CTL_directory, + aces_ctl_directory, min_value, - max_value) + max_value, + 1) cs.to_reference_transforms = [] cs.to_reference_transforms.append({ @@ -112,21 +163,32 @@ def create_ACEScc(aces_CTL_directory, # *AP1* primaries to *AP0* primaries. cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), + 'matrix': mat44_from_mat33(ACES_AP1_TO_AP0), 'direction': 'forward'}) cs.from_reference_transforms = [] return cs -# ------------------------------------------------------------------------- -# *ACESproxy* -# ------------------------------------------------------------------------- -def create_ACESproxy(aces_CTL_directory, - lut_directory, +def create_ACESproxy(aces_ctl_directory, + lut_directory, lut_resolution_1d, cleanup, name='ACESproxy'): + """ + Creates the *ACESproxy* colorspace. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + Colorspace + *ACESproxy* colorspace. + """ + cs = ColorSpace(name) cs.description = 'The %s color space' % name cs.aliases = ["acesproxy_ap1"] @@ -134,82 +196,114 @@ def create_ACESproxy(aces_CTL_directory, cs.family = 'ACES' cs.is_data = False - ctls = [os.path.join(aces_CTL_directory, + ctls = [os.path.join(aces_ctl_directory, 'ACESproxy', 'ACEScsc.ACESproxy10i_to_ACES.a1.0.0.ctl'), - # This transform gets back to the *AP1* primaries. - # Useful as the 1d LUT is only covering the transfer function. - # The primaries switch is covered by the matrix below: - os.path.join(aces_CTL_directory, - 'ACEScg', - 'ACEScsc.ACES_to_ACEScg.a1.0.0.ctl')] - lut = '%s_to_aces.spi1d' % name + # This transform gets back to the *AP1* primaries. + # Useful as the 1d LUT is only covering the transfer function. + # The primaries switch is covered by the matrix below: + os.path.join(aces_ctl_directory, + 'ACEScg', + 'ACEScsc.ACES_to_ACEScg.a1.0.0.ctl')] + lut = '%s_to_linear.spi1d' % name - lut = sanitize_path(lut) + lut = sanitize(lut) generate_1d_LUT_from_CTL( os.path.join(lut_directory, lut), ctls, lut_resolution_1d, 'uint16', - 64.0, - 1.0, + 64, + 1, {}, cleanup, - aces_CTL_directory) + aces_ctl_directory, + 0, + 1, + 1) cs.to_reference_transforms = [] cs.to_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'linear', - 'direction': 'forward' - }) + 'direction': 'forward'}) # *AP1* primaries to *AP0* primaries. cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), - 'direction': 'forward' - }) + 'matrix': mat44_from_mat33(ACES_AP1_TO_AP0), + 'direction': 'forward'}) cs.from_reference_transforms = [] return cs + # ------------------------------------------------------------------------- # *ACEScg* # ------------------------------------------------------------------------- -def create_ACEScg(aces_CTL_directory, - lut_directory, +def create_ACEScg(aces_ctl_directory, + lut_directory, lut_resolution_1d, cleanup, name='ACEScg'): + """ + Creates the *ACEScg* colorspace. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + Colorspace + *ACEScg* colorspace. + """ + cs = ColorSpace(name) cs.description = 'The %s color space' % name cs.aliases = ["lin_ap1"] cs.equality_group = '' cs.family = 'ACES' cs.is_data = False + cs.allocation_type = ocio.Constants.ALLOCATION_LG2 + cs.allocation_vars = [-8, 5, 0.00390625] cs.to_reference_transforms = [] # *AP1* primaries to *AP0* primaries. cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), - 'direction': 'forward' - }) + 'matrix': mat44_from_mat33(ACES_AP1_TO_AP0), + 'direction': 'forward'}) cs.from_reference_transforms = [] return cs + # ------------------------------------------------------------------------- # *ADX* # ------------------------------------------------------------------------- -def create_ADX(lut_directory, +def create_ADX(lut_directory, lut_resolution_1d, - bit_depth=10, + bit_depth=10, name='ADX'): + """ + Creates the *ADX* colorspace. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + Colorspace + *ADX* colorspace. + """ + name = '%s%s' % (name, bit_depth) cs = ColorSpace(name) cs.description = '%s color space - used for film scans' % name @@ -220,26 +314,25 @@ def create_ADX(lut_directory, if bit_depth == 10: cs.bit_depth = ocio.Constants.BIT_DEPTH_UINT10 - adx_to_cdd = [1023.0 / 500.0, 0.0, 0.0, 0.0, - 0.0, 1023.0 / 500.0, 0.0, 0.0, - 0.0, 0.0, 1023.0 / 500.0, 0.0, - 0.0, 0.0, 0.0, 1.0] - offset = [-95.0 / 500.0, -95.0 / 500.0, -95.0 / 500.0, 0.0] + ADX_to_CDD = [1023 / 500, 0, 0, 0, + 0, 1023 / 500, 0, 0, + 0, 0, 1023 / 500, 0, + 0, 0, 0, 1] + offset = [-95 / 500, -95 / 500, -95 / 500, 0] elif bit_depth == 16: cs.bit_depth = ocio.Constants.BIT_DEPTH_UINT16 - adx_to_cdd = [65535.0 / 8000.0, 0.0, 0.0, 0.0, - 0.0, 65535.0 / 8000.0, 0.0, 0.0, - 0.0, 0.0, 65535.0 / 8000.0, 0.0, - 0.0, 0.0, 0.0, 1.0] - offset = [-1520.0 / 8000.0, -1520.0 / 8000.0, -1520.0 / 8000.0, - 0.0] + ADX_to_CDD = [65535 / 8000, 0, 0, 0, + 0, 65535 / 8000, 0, 0, + 0, 0, 65535 / 8000, 0, + 0, 0, 0, 1] + offset = [-1520 / 8000, -1520 / 8000, -1520 / 8000, 0] cs.to_reference_transforms = [] # Converting from *ADX* to *Channel-Dependent Density*. cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': adx_to_cdd, + 'matrix': ADX_to_CDD, 'offset': offset, 'direction': 'forward'}) @@ -249,7 +342,7 @@ def create_ADX(lut_directory, 'matrix': [0.75573, 0.22197, 0.02230, 0, 0.05901, 0.96928, -0.02829, 0, 0.16134, 0.07406, 0.76460, 0, - 0.0, 0.0, 0.0, 1.0], + 0, 0, 0, 1], 'direction': 'forward'}) # Copied from *Alex Fry*'s *adx_cid_to_rle.py* @@ -282,13 +375,13 @@ def create_ADX(lut_directory, -1.121718645000000, -0.926545676714876] - REF_PT = ((7120.0 - 1520.0) / 8000.0 * (100.0 / 55.0) - - math.log(0.18, 10.0)) + REF_PT = ((7120 - 1520) / 8000 * (100 / 55) - + math.log(0.18, 10)) def cid_to_rle(x): if x <= 0.6: return interpolate_1D(x, LUT_1D_xp, LUT_1D_fp) - return (100.0 / 55.0) * x - REF_PT + return (100 / 55) * x - REF_PT def fit(value, from_min, from_max, to_min, to_max): if from_min == from_max: @@ -296,20 +389,20 @@ def create_ADX(lut_directory, return (value - from_min) / (from_max - from_min) * ( to_max - to_min) + to_min - NUM_SAMPLES = 2 ** 12 - RANGE = (-0.19, 3.0) + num_samples = 2 ** 12 + domain = (-0.19, 3) data = [] - for i in xrange(NUM_SAMPLES): - x = i / (NUM_SAMPLES - 1.0) - x = fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) + for i in xrange(num_samples): + x = i / (num_samples - 1) + x = fit(x, 0, 1, domain[0], domain[1]) data.append(cid_to_rle(x)) lut = 'ADX_CID_to_RLE.spi1d' write_SPI_1d(os.path.join(lut_directory, lut), - RANGE[0], - RANGE[1], + domain[0], + domain[1], data, - NUM_SAMPLES, 1) + num_samples, 1) return lut @@ -335,7 +428,7 @@ def create_ADX(lut_directory, 'matrix': [0.72286, 0.12630, 0.15084, 0, 0.11923, 0.76418, 0.11659, 0, 0.01427, 0.08213, 0.90359, 0, - 0.0, 0.0, 0.0, 1.0], + 0, 0, 0, 1], 'direction': 'forward'}) cs.from_reference_transforms = [] @@ -344,18 +437,32 @@ def create_ADX(lut_directory, # ------------------------------------------------------------------------- # *Generic Log Transform* # ------------------------------------------------------------------------- -def create_generic_log(aces_CTL_directory, +def create_generic_log(aces_ctl_directory, lut_directory, lut_resolution_1d, cleanup, name='log', aliases=[], - min_value=0.0, - max_value=1.0, - input_scale=1.0, + min_value=0, + max_value=1, + input_scale=1, middle_grey=0.18, - min_exposure=-6.0, + min_exposure=-6, max_exposure=6.5): + """ + Creates the *Generic Log* colorspace. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + Colorspace + *Generic Log* colorspace. + """ + cs = ColorSpace(name) cs.description = 'The %s color space' % name cs.aliases = aliases @@ -364,12 +471,12 @@ def create_generic_log(aces_CTL_directory, cs.is_data = False ctls = [os.path.join( - aces_CTL_directory, + aces_ctl_directory, 'utilities', 'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl')] - lut = '%s_to_aces.spi1d' % name + lut = '%s_to_linear.spi1d' % name - lut = sanitize_path(lut) + lut = sanitize(lut) generate_1d_LUT_from_CTL( os.path.join(lut_directory, lut), @@ -377,11 +484,62 @@ def create_generic_log(aces_CTL_directory, lut_resolution_1d, 'float', input_scale, - 1.0, + 1, {'middleGrey': middle_grey, 'minExposure': min_exposure, 'maxExposure': max_exposure}, cleanup, + aces_ctl_directory, + min_value, + max_value, + 1) + + cs.to_reference_transforms = [] + cs.to_reference_transforms.append({ + 'type': 'lutFile', + 'path': lut, + 'interpolation': 'linear', + 'direction': 'forward'}) + + cs.from_reference_transforms = [] + return cs + +# ------------------------------------------------------------------------- +# *base Dolby PQ Transform* +# ------------------------------------------------------------------------- +def create_dolbypq(aces_CTL_directory, + lut_directory, + lut_resolution_1d, + cleanup, + name='pq', + aliases=[], + min_value=0.0, + max_value=1.0, + input_scale=1.0): + cs = ColorSpace(name) + cs.description = 'The %s color space' % name + cs.aliases = aliases + cs.equality_group = name + cs.family = 'Utility' + cs.is_data = False + + ctls = [os.path.join( + aces_CTL_directory, + 'utilities', + 'ACESlib.OCIO_shaper_dolbypq_to_lin.a1.0.0.ctl')] + lut = '%s_to_linear.spi1d' % name + + lut = sanitize(lut) + + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, lut), + ctls, + lut_resolution_1d, + 'float', + input_scale, + 1.0, + {}, + cleanup, aces_CTL_directory, min_value, max_value) @@ -396,25 +554,98 @@ def create_generic_log(aces_CTL_directory, cs.from_reference_transforms = [] return cs +# ------------------------------------------------------------------------- +# *Dolby PQ Transform that considers a fixed linear range* +# ------------------------------------------------------------------------- +def create_dolbypq_scaled(aces_CTL_directory, + lut_directory, + lut_resolution_1d, + cleanup, + name='pq', + aliases=[], + min_value=0.0, + max_value=1.0, + input_scale=1.0, + middle_grey=0.18, + min_exposure=-6.0, + max_exposure=6.5): + cs = ColorSpace(name) + cs.description = 'The %s color space' % name + cs.aliases = aliases + cs.equality_group = name + cs.family = 'Utility' + cs.is_data = False + + ctls = [os.path.join( + aces_CTL_directory, + 'utilities', + 'ACESlib.OCIO_shaper_dolbypq_to_lin_param.a1.0.0.ctl')] + lut = '%s_to_linear.spi1d' % name + + lut = sanitize(lut) + + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, lut), + ctls, + lut_resolution_1d, + 'float', + input_scale, + 1.0, + {'middleGrey': middle_grey, + 'minExposure': min_exposure, + 'maxExposure': max_exposure}, + cleanup, + aces_CTL_directory, + min_value, + max_value) + + cs.to_reference_transforms = [] + cs.to_reference_transforms.append({ + 'type': 'lutFile', + 'path': lut, + 'interpolation': 'linear', + 'direction': 'forward'}) + + cs.from_reference_transforms = [] + return cs # ------------------------------------------------------------------------- -# *Individual LMTs* +# *Individual LMT* # ------------------------------------------------------------------------- def create_ACES_LMT(lmt_name, lmt_values, shaper_info, - aces_CTL_directory, + aces_ctl_directory, lut_directory, lut_resolution_1d=1024, lut_resolution_3d=64, cleanup=True, - aliases=[]): + aliases=None): + """ + Creates the *ACES LMT* colorspace. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + Colorspace + *ACES LMT* colorspace. + """ + + if aliases is None: + aliases = [] + cs = ColorSpace('%s' % lmt_name) cs.description = 'The ACES Look Transform: %s' % lmt_name cs.aliases = aliases cs.equality_group = '' cs.family = 'Look' cs.is_data = False + cs.allocation_type = ocio.Constants.ALLOCATION_LG2 + cs.allocation_vars = [-8, 5, 0.00390625] pprint.pprint(lmt_values) @@ -425,22 +656,9 @@ def create_ACES_LMT(lmt_name, shaper_input_scale, shaper_params) = shaper_info - shaper_lut = '%s_to_aces.spi1d' % shaper_name - if not os.path.exists(os.path.join(lut_directory, shaper_lut)): - ctls = [shaper_to_ACES_CTL % aces_CTL_directory] - - shaper_lut = sanitize_path(shaper_lut) - - generate_1d_LUT_from_CTL( - os.path.join(lut_directory, shaper_lut), - ctls, - lut_resolution_1d, - 'float', - 1.0 / shaper_input_scale, - 1.0, - shaper_params, - cleanup, - aces_CTL_directory) + # Add the shaper transform + shaper_lut = '%s_to_linear.spi1d' % shaper_name + shaper_lut = sanitize(shaper_lut) shaper_OCIO_transform = { 'type': 'lutFile', @@ -452,53 +670,55 @@ def create_ACES_LMT(lmt_name, cs.from_reference_transforms = [] if 'transformCTL' in lmt_values: - ctls = [shaper_to_ACES_CTL % aces_CTL_directory, - os.path.join(aces_CTL_directory, + ctls = [shaper_to_ACES_CTL % aces_ctl_directory, + os.path.join(aces_ctl_directory, lmt_values['transformCTL'])] lut = '%s.%s.spi3d' % (shaper_name, lmt_name) - lut = sanitize_path(lut) + lut = sanitize(lut) generate_3d_LUT_from_CTL( os.path.join(lut_directory, lut), ctls, lut_resolution_3d, 'float', - 1.0 / shaper_input_scale, - 1.0, + 1 / shaper_input_scale, + 1, shaper_params, cleanup, - aces_CTL_directory) + aces_ctl_directory) cs.from_reference_transforms.append(shaper_OCIO_transform) cs.from_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'tetrahedral', - 'direction': 'forward' - }) + 'direction': 'forward'}) # Generating the inverse transform. cs.to_reference_transforms = [] if 'transformCTLInverse' in lmt_values: - ctls = [os.path.join(aces_CTL_directory, - odt_values['transformCTLInverse']), - shaper_from_ACES_CTL % aces_CTL_directory] + ctls = [os.path.join(aces_ctl_directory, + lmt_values['transformCTLInverse']), + shaper_from_ACES_CTL % aces_ctl_directory] lut = 'Inverse.%s.%s.spi3d' % (odt_name, shaper_name) - lut = sanitize_path(lut) + lut = sanitize(lut) generate_3d_LUT_from_CTL( os.path.join(lut_directory, lut), ctls, lut_resolution_3d, 'half', - 1.0, + 1, shaper_input_scale, shaper_params, cleanup, - aces_CTL_directory) + aces_ctl_directory, + 0, + 1, + 1) cs.to_reference_transforms.append({ 'type': 'lutFile', @@ -515,13 +735,26 @@ def create_ACES_LMT(lmt_name, # ------------------------------------------------------------------------- # *LMTs* # ------------------------------------------------------------------------- -def create_lmts(aces_CTL_directory, - lut_directory, +def create_LMTs(aces_ctl_directory, + lut_directory, lut_resolution_1d, lut_resolution_3d, lmt_info, shaper_name, cleanup): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ colorspaces = [] @@ -536,10 +769,10 @@ def create_lmts(aces_CTL_directory, lmt_shaper_name_aliases = ['crv_lmtshaper'] lmt_params = { 'middleGrey': 0.18, - 'minExposure': -10.0, + 'minExposure': -10, 'maxExposure': 6.5} - lmt_shaper = create_generic_log(aces_CTL_directory, + lmt_shaper = create_generic_log(aces_ctl_directory, lut_directory, lmt_lut_resolution_1d, cleanup, @@ -550,7 +783,7 @@ def create_lmts(aces_CTL_directory, aliases=lmt_shaper_name_aliases) colorspaces.append(lmt_shaper) - shaper_input_scale_generic_log2 = 1.0 + shaper_input_scale_generic_log2 = 1 # *Log 2* shaper name and *CTL* transforms bundled up. lmt_shaper_data = [ @@ -567,13 +800,13 @@ def create_lmts(aces_CTL_directory, sorted_LMTs = sorted(lmt_info.iteritems(), key=lambda x: x[1]) print(sorted_LMTs) for lmt in sorted_LMTs: - (lmt_name, lmt_values) = lmt + lmt_name, lmt_values = lmt lmt_aliases = ["look_%s" % compact(lmt_values['transformUserName'])] cs = create_ACES_LMT( lmt_values['transformUserName'], lmt_values, lmt_shaper_data, - aces_CTL_directory, + aces_ctl_directory, lut_directory, lmt_lut_resolution_1d, lmt_lut_resolution_3d, @@ -589,12 +822,29 @@ def create_lmts(aces_CTL_directory, def create_ACES_RRT_plus_ODT(odt_name, odt_values, shaper_info, - aces_CTL_directory, + aces_ctl_directory, lut_directory, lut_resolution_1d=1024, lut_resolution_3d=64, cleanup=True, - aliases=[]): + aliases=None): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + if aliases is None: + aliases = [] + cs = ColorSpace('%s' % odt_name) cs.description = '%s - %s Output Transform' % ( odt_values['transformUserNamePrefix'], odt_name) @@ -617,22 +867,9 @@ def create_ACES_RRT_plus_ODT(odt_name, else: shaper_params['legalRange'] = 0 - shaper_lut = '%s_to_aces.spi1d' % shaper_name - if not os.path.exists(os.path.join(lut_directory, shaper_lut)): - ctls = [shaper_to_ACES_CTL % aces_CTL_directory] - - shaper_lut = sanitize_path(shaper_lut) - - generate_1d_LUT_from_CTL( - os.path.join(lut_directory, shaper_lut), - ctls, - lut_resolution_1d, - 'float', - 1.0 / shaper_input_scale, - 1.0, - shaper_params, - cleanup, - aces_CTL_directory) + # Add the shaper transform + shaper_lut = '%s_to_linear.spi1d' % shaper_name + shaper_lut = sanitize(shaper_lut) shaper_OCIO_transform = { 'type': 'lutFile', @@ -657,16 +894,16 @@ def create_ACES_RRT_plus_ODT(odt_name, 'direction': 'forward'}) elif 'transformCTL' in odt_values: ctls = [ - shaper_to_ACES_CTL % aces_CTL_directory, - os.path.join(aces_CTL_directory, + shaper_to_ACES_CTL % aces_ctl_directory, + os.path.join(aces_ctl_directory, 'rrt', 'RRT.a1.0.0.ctl'), - os.path.join(aces_CTL_directory, + os.path.join(aces_ctl_directory, 'odt', odt_values['transformCTL'])] lut = '%s.RRT.a1.0.0.%s.spi3d' % (shaper_name, odt_name) - lut = sanitize_path(lut) + lut = sanitize(lut) generate_3d_LUT_from_CTL( os.path.join(lut_directory, lut), @@ -674,11 +911,11 @@ def create_ACES_RRT_plus_ODT(odt_name, ctls, lut_resolution_3d, 'float', - 1.0 / shaper_input_scale, - 1.0, + 1 / shaper_input_scale, + 1, shaper_params, cleanup, - aces_CTL_directory) + aces_ctl_directory) cs.from_reference_transforms.append(shaper_OCIO_transform) cs.from_reference_transforms.append({ @@ -706,16 +943,16 @@ def create_ACES_RRT_plus_ODT(odt_name, shaper_inverse['direction'] = 'forward' cs.to_reference_transforms.append(shaper_inverse) elif 'transformCTLInverse' in odt_values: - ctls = [os.path.join(aces_CTL_directory, + ctls = [os.path.join(aces_ctl_directory, 'odt', odt_values['transformCTLInverse']), - os.path.join(aces_CTL_directory, + os.path.join(aces_ctl_directory, 'rrt', 'InvRRT.a1.0.0.ctl'), - shaper_from_ACES_CTL % aces_CTL_directory] + shaper_from_ACES_CTL % aces_ctl_directory] lut = 'InvRRT.a1.0.0.%s.%s.spi3d' % (odt_name, shaper_name) - lut = sanitize_path(lut) + lut = sanitize(lut) generate_3d_LUT_from_CTL( os.path.join(lut_directory, lut), @@ -723,11 +960,11 @@ def create_ACES_RRT_plus_ODT(odt_name, ctls, lut_resolution_3d, 'half', - 1.0, + 1, shaper_input_scale, shaper_params, cleanup, - aces_CTL_directory) + aces_ctl_directory) cs.to_reference_transforms.append({ 'type': 'lutFile', @@ -744,8 +981,8 @@ def create_ACES_RRT_plus_ODT(odt_name, # ------------------------------------------------------------------------- # *ODTs* # ------------------------------------------------------------------------- -def create_odts(aces_CTL_directory, - lut_directory, +def create_ODTs(aces_ctl_directory, + lut_directory, lut_resolution_1d, lut_resolution_3d, odt_info, @@ -753,6 +990,19 @@ def create_odts(aces_CTL_directory, cleanup, linear_display_space, log_display_space): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ colorspaces = [] displays = {} @@ -764,14 +1014,14 @@ def create_odts(aces_CTL_directory, # Defining the *Log 2* shaper. log2_shaper_name = shaper_name - log2_shaper_name_aliases = ["crv_%s" % compact(shaper_name)] + log2_shaper_name_aliases = ["crv_%s" % compact(log2_shaper_name)] log2_params = { 'middleGrey': 0.18, - 'minExposure': -6.0, + 'minExposure': -6, 'maxExposure': 6.5} - log2_shaper = create_generic_log( - aces_CTL_directory, + log2_shaper_colorspace = create_generic_log( + aces_ctl_directory, lut_directory, lut_resolution_1d, cleanup, @@ -780,9 +1030,9 @@ def create_odts(aces_CTL_directory, min_exposure=log2_params['minExposure'], max_exposure=log2_params['maxExposure'], aliases=log2_shaper_name_aliases) - colorspaces.append(log2_shaper) + colorspaces.append(log2_shaper_colorspace) - shaper_input_scale_generic_log2 = 1.0 + shaper_input_scale_generic_log2 = 1 # *Log 2* shaper name and *CTL* transforms bundled up. log2_shaper_data = [ @@ -798,30 +1048,99 @@ def create_odts(aces_CTL_directory, shaper_data[log2_shaper_name] = log2_shaper_data - # Shaper that also includes the AP1 primaries. + # Space with a more user-friendly name. Direct copy otherwise. + log2_shaper_copy_name = "Log2 Shaper" + log2_shaper_copy_colorspace = ColorSpace(log2_shaper_copy_name) + log2_shaper_copy_colorspace.description = 'The %s color space' % log2_shaper_copy_name + log2_shaper_copy_colorspace.aliases = [compact(log2_shaper_copy_name)] + log2_shaper_copy_colorspace.equality_group = log2_shaper_copy_name + log2_shaper_copy_colorspace.family = log2_shaper_colorspace.family + log2_shaper_copy_colorspace.is_data = log2_shaper_colorspace.is_data + log2_shaper_copy_colorspace.to_reference_transforms = list(log2_shaper_colorspace.to_reference_transforms) + log2_shaper_copy_colorspace.from_reference_transforms = list(log2_shaper_colorspace.from_reference_transforms) + colorspaces.append(log2_shaper_copy_colorspace) + + # Defining the *Log2 shaper that includes the AP1* primaries. # Needed for some LUT baking steps. - log2_shaper_api1_name_aliases = ["%s_ap1" % compact(shaper_name)] - log2_shaper_AP1 = create_generic_log( - aces_CTL_directory, - lut_directory, - lut_resolution_1d, - cleanup, - name=log2_shaper_name, - middle_grey=log2_params['middleGrey'], - min_exposure=log2_params['minExposure'], - max_exposure=log2_params['maxExposure'], - aliases=log2_shaper_api1_name_aliases) - log2_shaper_AP1.name = '%s - AP1' % log2_shaper_AP1.name + log2_shaper_api1_name = "%s - AP1" % "Log2 Shaper" + log2_shaper_api1_colorspace = ColorSpace(log2_shaper_api1_name) + log2_shaper_api1_colorspace.description = 'The %s color space' % log2_shaper_api1_name + log2_shaper_api1_colorspace.aliases = ["%s_ap1" % compact(log2_shaper_copy_name)] + log2_shaper_api1_colorspace.equality_group = log2_shaper_api1_name + log2_shaper_api1_colorspace.family = log2_shaper_colorspace.family + log2_shaper_api1_colorspace.is_data = log2_shaper_colorspace.is_data + log2_shaper_api1_colorspace.to_reference_transforms = list(log2_shaper_colorspace.to_reference_transforms) + log2_shaper_api1_colorspace.from_reference_transforms = list(log2_shaper_colorspace.from_reference_transforms) # *AP1* primaries to *AP0* primaries. - log2_shaper_AP1.to_reference_transforms.append({ + log2_shaper_api1_colorspace.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), + 'matrix': mat44_from_mat33(ACES_AP1_TO_AP0), 'direction': 'forward' }) - colorspaces.append(log2_shaper_AP1) + colorspaces.append(log2_shaper_api1_colorspace) + + # Define the base *Dolby PQ Shaper* + # + dolbypq_shaper_name = "Dolby PQ 10000" + dolbypq_shaper_name_aliases = ["crv_%s" % "dolbypq_10000"] + dolbypq_shaper_colorspace = create_dolbypq( + aces_ctl_directory, + lut_directory, + lut_resolution_1d, + cleanup, + name=dolbypq_shaper_name, + aliases=dolbypq_shaper_name_aliases) + colorspaces.append(dolbypq_shaper_colorspace) + + # *Dolby PQ* shaper name and *CTL* transforms bundled up. + dolbypq_shaper_data = [ + dolbypq_shaper_name, + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_dolbypq_to_lin.a1.0.0.ctl'), + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_lin_to_dolbypq.a1.0.0.ctl'), + 1.0, + {}] + + shaper_data[dolbypq_shaper_name] = dolbypq_shaper_data + + # Define the *Dolby PQ Shaper that considers a fixed linear range* + # + dolbypq_scaled_shaper_name = "Dolby PQ Scaled" + dolbypq_scaled_shaper_name_aliases = ["crv_%s" % "dolbypq_scaled"] + + dolbypq_scaled_shaper_colorspace = create_dolbypq_scaled( + aces_ctl_directory, + lut_directory, + lut_resolution_1d, + cleanup, + name=dolbypq_scaled_shaper_name, + aliases=dolbypq_scaled_shaper_name_aliases) + colorspaces.append(dolbypq_scaled_shaper_colorspace) + + # *Dolby PQ* shaper name and *CTL* transforms bundled up. + dolbypq_scaled_shaper_data = [ + dolbypq_scaled_shaper_name, + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_dolbypq_to_lin_param.a1.0.0.ctl'), + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_lin_to_dolbypq_param.a1.0.0.ctl'), + 1.0, + log2_params] + + shaper_data[dolbypq_scaled_shaper_name] = dolbypq_scaled_shaper_data + + # + # Pick a specific shaper + # rrt_shaper = log2_shaper_data + #rrt_shaper = dolbypq_scaled_shaper_data # *RRT + ODT* combinations. sorted_odts = sorted(odt_info.iteritems(), key=lambda x: x[1]) @@ -845,7 +1164,7 @@ def create_odts(aces_CTL_directory, odt_name_legal, odt_legal, rrt_shaper, - aces_CTL_directory, + aces_ctl_directory, lut_directory, lut_resolution_1d, lut_resolution_3d, @@ -874,7 +1193,7 @@ def create_odts(aces_CTL_directory, odt_name_full, odt_full, rrt_shaper, - aces_CTL_directory, + aces_ctl_directory, lut_directory, lut_resolution_1d, lut_resolution_3d, @@ -889,20 +1208,6 @@ def create_odts(aces_CTL_directory, return (colorspaces, displays) -def create_aces(): - # Defining the reference colorspace. - ACES = ColorSpace('ACES2065-1') - ACES.description = ( - 'The Academy Color Encoding System reference color space') - ACES.equality_group = '' - ACES.aliases = ["lin_ap0", "aces"] - ACES.family = 'ACES' - ACES.is_data = False - ACES.allocation_type = ocio.Constants.ALLOCATION_LG2 - ACES.allocation_vars = [-15, 6] - - return ACES - def get_transform_info(ctl_transform): """ @@ -933,13 +1238,15 @@ def get_transform_info(ctl_transform): transform_full_legal_switch = False for line in lines: if line.strip() == "input varying int legalRange = 0": - #print( "%s has legal range flag" % transform_user_name) + # print( "%s has legal range flag" % transform_user_name) transform_full_legal_switch = True break - return (transform_id, transform_user_name, transform_user_name_prefix, transform_full_legal_switch) + return (transform_id, transform_user_name, transform_user_name_prefix, + transform_full_legal_switch) + -def get_ODT_info(aces_CTL_directory): +def get_ODTs_info(aces_ctl_directory): """ Object description. @@ -958,7 +1265,7 @@ def get_ODT_info(aces_CTL_directory): # TODO: Investigate usage of *files_walker* definition here. # Credit to *Alex Fry* for the original approach here. - odt_dir = os.path.join(aces_CTL_directory, 'odt') + odt_dir = os.path.join(aces_ctl_directory, 'odt') all_odt = [] for dir_name, subdir_list, file_list in os.walk(odt_dir): for fname in file_list: @@ -988,7 +1295,7 @@ def get_ODT_info(aces_CTL_directory): transform_user_name, transform_user_name_prefix, transform_full_legal_switch) = get_transform_info( - os.path.join(aces_CTL_directory, 'odt', odt_dir, transform_CTL)) + os.path.join(aces_ctl_directory, 'odt', odt_dir, transform_CTL)) # Finding inverse. transform_CTL_inverse = 'InvODT.%s.ctl' % odt_name @@ -1006,7 +1313,8 @@ def get_ODT_info(aces_CTL_directory): odts[odt_name]['transformID'] = transform_ID odts[odt_name]['transformUserNamePrefix'] = transform_user_name_prefix odts[odt_name]['transformUserName'] = transform_user_name - odts[odt_name]['transformHasFullLegalSwitch'] = transform_full_legal_switch + odts[odt_name][ + 'transformHasFullLegalSwitch'] = transform_full_legal_switch forward_CTL = odts[odt_name]['transformCTL'] @@ -1014,7 +1322,8 @@ def get_ODT_info(aces_CTL_directory): print('\tTransform ID : %s' % transform_ID) print('\tTransform User Name Prefix : %s' % transform_user_name_prefix) print('\tTransform User Name : %s' % transform_user_name) - print('\tHas Full / Legal Switch : %s' % transform_full_legal_switch) + print( + '\tHas Full / Legal Switch : %s' % transform_full_legal_switch) print('\tForward ctl : %s' % forward_CTL) if 'transformCTLInverse' in odts[odt_name]: inverse_CTL = odts[odt_name]['transformCTLInverse'] @@ -1027,7 +1336,7 @@ def get_ODT_info(aces_CTL_directory): return odts -def get_LMT_info(aces_CTL_directory): +def get_LMTs_info(aces_ctl_directory): """ Object description. @@ -1047,7 +1356,7 @@ def get_LMT_info(aces_CTL_directory): # TODO: Investigate refactoring with previous definition. # Credit to Alex Fry for the original approach here - lmt_dir = os.path.join(aces_CTL_directory, 'lmt') + lmt_dir = os.path.join(aces_ctl_directory, 'lmt') all_lmt = [] for dir_name, subdir_list, file_list in os.walk(lmt_dir): for fname in file_list: @@ -1078,7 +1387,7 @@ def get_LMT_info(aces_CTL_directory): transform_user_name, transform_user_name_prefix, transform_full_legal_switch) = get_transform_info( - os.path.join(aces_CTL_directory, lmt_dir, transform_CTL)) + os.path.join(aces_ctl_directory, lmt_dir, transform_CTL)) # Finding inverse. transform_CTL_inverse = 'InvLMT.%s.ctl' % lmt_name @@ -1113,9 +1422,10 @@ def get_LMT_info(aces_CTL_directory): return lmts -def create_colorspaces(aces_CTL_directory, - lut_directory, - lut_resolution_1d, + +def create_colorspaces(aces_ctl_directory, + lut_directory, + lut_resolution_1d, lut_resolution_3d, lmt_info, odt_info, @@ -1137,15 +1447,19 @@ def create_colorspaces(aces_CTL_directory, colorspaces = [] - ACES = create_aces() + ACES = create_ACES() - ACEScc = create_ACEScc(aces_CTL_directory, lut_directory, lut_resolution_1d, cleanup) + ACEScc = create_ACEScc(aces_ctl_directory, lut_directory, + lut_resolution_1d, cleanup, + min_value=-0.35840, max_value=1.468) colorspaces.append(ACEScc) - ACESproxy = create_ACESproxy(aces_CTL_directory, lut_directory, lut_resolution_1d, cleanup) + ACESproxy = create_ACESproxy(aces_ctl_directory, lut_directory, + lut_resolution_1d, cleanup) colorspaces.append(ACESproxy) - ACEScg = create_ACEScg(aces_CTL_directory, lut_directory, lut_resolution_1d, cleanup) + ACEScg = create_ACEScg(aces_ctl_directory, lut_directory, + lut_resolution_1d, cleanup) colorspaces.append(ACEScg) ADX10 = create_ADX(lut_directory, lut_resolution_1d, bit_depth=10) @@ -1154,24 +1468,35 @@ def create_colorspaces(aces_CTL_directory, ADX16 = create_ADX(lut_directory, lut_resolution_1d, bit_depth=16) colorspaces.append(ADX16) - lmts = create_lmts(aces_CTL_directory, - lut_directory, - lut_resolution_1d, + lmts = create_LMTs(aces_ctl_directory, + lut_directory, + lut_resolution_1d, lut_resolution_3d, lmt_info, shaper_name, cleanup) colorspaces.extend(lmts) - (odts, displays) = create_odts(aces_CTL_directory, - lut_directory, - lut_resolution_1d, - lut_resolution_3d, - odt_info, - shaper_name, - cleanup, - ACES, - ACEScc) + odts, displays = create_ODTs(aces_ctl_directory, + lut_directory, + lut_resolution_1d, + lut_resolution_3d, + odt_info, + shaper_name, + cleanup, + ACES, + ACEScc) colorspaces.extend(odts) - return (ACES, colorspaces, displays, ACEScc) + roles = {'color_picking' : ACEScg.name, + 'color_timing' : ACEScc.name, + 'compositing_log' : ACEScc.name, + 'data' : '', + 'default' : ACES.name, + 'matte_paint' : ACEScc.name, + 'reference' : '', + 'scene_linear' : ACEScg.name, + 'texture_paint' : ''} + + + return ACES, colorspaces, displays, ACEScc, roles