X-Git-Url: http://users.mur.at/ms/git/gitweb/?a=blobdiff_plain;f=aces_1.0.0%2Fpython%2Faces_ocio%2Fcreate_aces_config.py;h=e83896a1ed60c323804c991c256df6e5f01d1704;hb=334e8bd4d18f6b4ad0bd616638f349825e9610b8;hp=18f2d8d4f3baa1fda910749ec18f5e4f5f34b78f;hpb=8a160c48f21fd063b5a59e702a9d5ffdaaefe3b3;p=OpenColorIO-Configs.git diff --git a/aces_1.0.0/python/aces_ocio/create_aces_config.py b/aces_1.0.0/python/aces_ocio/create_aces_config.py index 18f2d8d..e83896a 100755 --- a/aces_1.0.0/python/aces_ocio/create_aces_config.py +++ b/aces_1.0.0/python/aces_ocio/create_aces_config.py @@ -2,275 +2,313 @@ # -*- coding: utf-8 -*- """ -usage from python - -import sys -sys.path.append("/path/to/script") -import create_aces_config as cac -acesReleaseCTLDir = "/path/to/github/checkout/releases/v0.7.1/transforms/ctl" -configDir = "/path/to/config/dir" -cac.createACESConfig(acesReleaseCTLDir, configDir, 1024, 33, True) - -usage from command line, from the directory with 'create_aces_config.py' -python create_aces_config.py -a "/path/to/github/checkout/releases/v0.7.1/transforms/ctl" -c "/path/to/config/dir" --lutResolution1d 1024 --lutResolution3d 33 --keepTempImages - - - -build instructions for osx for needed packages. - -#opencolorio -brew install -vd opencolorio --with-python - -#openimageio -brew tap homebrew/science - -# optional installs -brew install -vd libRaw -brew install -vd OpenCV - -brew install -vd openimageio --with-python - -#ctl -brew install -vd CTL - -#opencolorio - again. -# this time, 'ociolutimage' will build because openimageio is installed -brew uninstall -vd opencolorio -brew install -vd opencolorio --with-python +Defines objects creating the *ACES* configuration. """ import math import numpy import os +import pprint import shutil import string import sys -# TODO: This restores the capability of running the script without having -# added the package to PYTHONPATH, this is ugly and should ideally replaced by -# dedicated executable in a /bin directory. -sys.path.append(os.path.join(os.path.dirname(__file__), '..')) - -import PyOpenColorIO as OCIO +import PyOpenColorIO as ocio -import aces_ocio.createARRIColorSpaces as arri -import aces_ocio.createCanonColorSpaces as canon -import aces_ocio.createREDColorSpaces as red -import aces_ocio.createSonyColorSpaces as sony -import aces_ocio.generateLUT as genlut +import aces_ocio.create_arri_colorspaces as arri +import aces_ocio.create_canon_colorspaces as canon +import aces_ocio.create_red_colorspaces as red +import aces_ocio.create_sony_colorspaces as sony +from aces_ocio.generate_lut import ( + generate_1d_LUT_from_CTL, + generate_3d_LUT_from_CTL, + write_SPI_1d) from aces_ocio.process import Process -from aces_ocio.util import ColorSpace, mat44FromMat33 +from aces_ocio.utilities import ColorSpace, mat44_from_mat33, sanitize_path + +__author__ = 'ACES Developers' +__copyright__ = 'Copyright (C) 2014 - 2015 - ACES Developers' +__license__ = '' +__maintainer__ = 'ACES Developers' +__email__ = 'aces@oscars.org' +__status__ = 'Production' + +__all__ = ['ACES_OCIO_CTL_DIRECTORY_ENVIRON', + 'ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON', + 'set_config_default_roles', + 'write_config', + 'generate_OCIO_transform', + 'create_config', + 'generate_LUTs', + 'generate_baked_LUTs', + 'create_config_dir', + 'get_transform_info', + 'get_ODT_info', + 'get_LMT_info', + 'create_ACES_config', + 'main'] ACES_OCIO_CTL_DIRECTORY_ENVIRON = 'ACES_OCIO_CTL_DIRECTORY' ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON = 'ACES_OCIO_CONFIGURATION_DIRECTORY' -# -# Utility functions -# -def setConfigDefaultRoles(config, - color_picking="", - color_timing="", - compositing_log="", - data="", - default="", - matte_paint="", - reference="", - scene_linear="", - texture_paint=""): - # Add Roles + +def set_config_default_roles(config, + color_picking='', + color_timing='', + compositing_log='', + data='', + default='', + matte_paint='', + reference='', + scene_linear='', + texture_paint=''): + """ + Sets given *OCIO* configuration default roles. + + Parameters + ---------- + config : config + *OCIO* configuration. + color_picking : str or unicode + Color picking role title. + color_timing : str or unicode + Color timing role title. + compositing_log : str or unicode + Compositing log role title. + data : str or unicode + Data role title. + default : str or unicode + Default role title. + matte_paint : str or unicode + Matte painting role title. + reference : str or unicode + Reference role title. + scene_linear : str or unicode + Scene linear role title. + texture_paint : str or unicode + Texture painting role title. + + Returns + ------- + bool + Definition success. + """ + if color_picking: - config.setRole(OCIO.Constants.ROLE_COLOR_PICKING, color_picking) + config.setRole(ocio.Constants.ROLE_COLOR_PICKING, color_picking) if color_timing: - config.setRole(OCIO.Constants.ROLE_COLOR_TIMING, color_timing) + config.setRole(ocio.Constants.ROLE_COLOR_TIMING, color_timing) if compositing_log: - config.setRole(OCIO.Constants.ROLE_COMPOSITING_LOG, compositing_log) + config.setRole(ocio.Constants.ROLE_COMPOSITING_LOG, compositing_log) if data: - config.setRole(OCIO.Constants.ROLE_DATA, data) + config.setRole(ocio.Constants.ROLE_DATA, data) if default: - config.setRole(OCIO.Constants.ROLE_DEFAULT, default) + config.setRole(ocio.Constants.ROLE_DEFAULT, default) if matte_paint: - config.setRole(OCIO.Constants.ROLE_MATTE_PAINT, matte_paint) + config.setRole(ocio.Constants.ROLE_MATTE_PAINT, matte_paint) if reference: - config.setRole(OCIO.Constants.ROLE_REFERENCE, reference) + config.setRole(ocio.Constants.ROLE_REFERENCE, reference) if scene_linear: - config.setRole(OCIO.Constants.ROLE_SCENE_LINEAR, scene_linear) + config.setRole(ocio.Constants.ROLE_SCENE_LINEAR, scene_linear) if texture_paint: - config.setRole(OCIO.Constants.ROLE_TEXTURE_PAINT, texture_paint) + config.setRole(ocio.Constants.ROLE_TEXTURE_PAINT, texture_paint) + + return True + +def write_config(config, config_path, sanity_check=True): + """ + Writes the configuration to given path. -# Write config to disk -def writeConfig(config, configPath, sanityCheck=True): - if sanityCheck: + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + if sanity_check: try: config.sanityCheck() except Exception, e: print e - print "Configuration was not written due to a failed Sanity Check" + print 'Configuration was not written due to a failed Sanity Check' return - # sys.exit() - fileHandle = open(configPath, mode='w') - fileHandle.write(config.serialize()) - fileHandle.close() + with open(config_path, mode='w') as fp: + fp.write(config.serialize()) + +def generate_OCIO_transform(transforms): + """ + Object description. -def generateOCIOTransform(transforms): - # print("Generating transforms") + Parameters + ---------- + parameter : type + Parameter description. - interpolationOptions = { - 'linear': OCIO.Constants.INTERP_LINEAR, - 'nearest': OCIO.Constants.INTERP_NEAREST, - 'tetrahedral': OCIO.Constants.INTERP_TETRAHEDRAL + Returns + ------- + type + Return value description. + """ + + interpolation_options = { + 'linear': ocio.Constants.INTERP_LINEAR, + 'nearest': ocio.Constants.INTERP_NEAREST, + 'tetrahedral': ocio.Constants.INTERP_TETRAHEDRAL } - directionOptions = { - 'forward': OCIO.Constants.TRANSFORM_DIR_FORWARD, - 'inverse': OCIO.Constants.TRANSFORM_DIR_INVERSE + direction_options = { + 'forward': ocio.Constants.TRANSFORM_DIR_FORWARD, + 'inverse': ocio.Constants.TRANSFORM_DIR_INVERSE } - ocioTransforms = [] + ocio_transforms = [] for transform in transforms: if transform['type'] == 'lutFile': - ocioTransform = OCIO.FileTransform( + ocio_transform = ocio.FileTransform( src=transform['path'], - interpolation=interpolationOptions[transform['interpolation']], - direction=directionOptions[transform['direction']]) - ocioTransforms.append(ocioTransform) + interpolation=interpolation_options[ + transform['interpolation']], + direction=direction_options[transform['direction']]) + ocio_transforms.append(ocio_transform) elif transform['type'] == 'matrix': - ocioTransform = OCIO.MatrixTransform() - # MatrixTransform member variables can't be initialized directly. - # Each must be set individually. - ocioTransform.setMatrix(transform['matrix']) + ocio_transform = ocio.MatrixTransform() + # MatrixTransform member variables can't be initialized directly + # and must be set individually. + ocio_transform.setMatrix(transform['matrix']) if 'offset' in transform: - ocioTransform.setOffset(transform['offset']) + ocio_transform.setOffset(transform['offset']) if 'direction' in transform: - ocioTransform.setDirection( - directionOptions[transform['direction']]) + ocio_transform.setDirection( + direction_options[transform['direction']]) - ocioTransforms.append(ocioTransform) + ocio_transforms.append(ocio_transform) elif transform['type'] == 'exponent': - ocioTransform = OCIO.ExponentTransform() - ocioTransform.setValue(transform['value']) - ocioTransforms.append(ocioTransform) + ocio_transform = ocio.ExponentTransform() + ocio_transform.setValue(transform['value']) + ocio_transforms.append(ocio_transform) elif transform['type'] == 'log': - ocioTransform = OCIO.LogTransform( + ocio_transform = ocio.LogTransform( base=transform['base'], - direction=directionOptions[transform['direction']]) + direction=direction_options[transform['direction']]) - ocioTransforms.append(ocioTransform) + ocio_transforms.append(ocio_transform) else: - print("Ignoring unknown transform type : %s" % transform['type']) - - # Build a group transform if necessary - if len(ocioTransforms) > 1: - transformG = OCIO.GroupTransform() - for transform in ocioTransforms: - transformG.push_back(transform) - transform = transformG + print('Ignoring unknown transform type : %s' % transform['type']) - # Or take the first transform from the list + if len(ocio_transforms) > 1: + group_transform = ocio.GroupTransform() + for transform in ocio_transforms: + group_transform.push_back(transform) + transform = group_transform else: - transform = ocioTransforms[0] + transform = ocio_transforms[0] return transform -def createConfig(configData, nuke=False): - # Create the config - config = OCIO.Config() - - # - # Set config wide values - # - config.setDescription("An ACES config generated from python") - config.setSearchPath("luts") - - # - # Define the reference color space - # - referenceData = configData['referenceColorSpace'] - print("Adding the reference color space : %s" % referenceData.name) - - # Create a color space - reference = OCIO.ColorSpace( - name=referenceData.name, - bitDepth=referenceData.bitDepth, - description=referenceData.description, - equalityGroup=referenceData.equalityGroup, - family=referenceData.family, - isData=referenceData.isData, - allocation=referenceData.allocationType, - allocationVars=referenceData.allocationVars) - - # Add to config +def create_config(config_data, nuke=False): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + # Creating the *OCIO* configuration. + config = ocio.Config() + + # Setting configuration overall values. + config.setDescription('An ACES config generated from python') + config.setSearchPath('luts') + + # Defining the reference colorspace. + reference_data = config_data['referenceColorSpace'] + print('Adding the reference color space : %s' % reference_data.name) + + reference = ocio.ColorSpace( + name=reference_data.name, + bitDepth=reference_data.bit_depth, + description=reference_data.description, + equalityGroup=reference_data.equality_group, + family=reference_data.family, + isData=reference_data.is_data, + allocation=reference_data.allocation_type, + allocationVars=reference_data.allocation_vars) + config.addColorSpace(reference) - # - # Create the rest of the color spaces - # - for colorspace in sorted(configData['colorSpaces']): - print("Creating new color space : %s" % colorspace.name) + # Creating the remaining colorspaces. + for colorspace in sorted(config_data['colorSpaces']): + print('Creating new color space : %s' % colorspace.name) - ocioColorspace = OCIO.ColorSpace( + ocio_colorspace = ocio.ColorSpace( name=colorspace.name, - bitDepth=colorspace.bitDepth, + bitDepth=colorspace.bit_depth, description=colorspace.description, - equalityGroup=colorspace.equalityGroup, + equalityGroup=colorspace.equality_group, family=colorspace.family, - isData=colorspace.isData, - allocation=colorspace.allocationType, - allocationVars=colorspace.allocationVars) - - if colorspace.toReferenceTransforms != []: - print("Generating To-Reference transforms") - ocioTransform = generateOCIOTransform( - colorspace.toReferenceTransforms) - ocioColorspace.setTransform( - ocioTransform, - OCIO.Constants.COLORSPACE_DIR_TO_REFERENCE) - - if colorspace.fromReferenceTransforms != []: - print("Generating From-Reference transforms") - ocioTransform = generateOCIOTransform( - colorspace.fromReferenceTransforms) - ocioColorspace.setTransform( - ocioTransform, - OCIO.Constants.COLORSPACE_DIR_FROM_REFERENCE) - - config.addColorSpace(ocioColorspace) - - print("") - - # - # Define the views and displays - # + isData=colorspace.is_data, + allocation=colorspace.allocation_type, + allocationVars=colorspace.allocation_vars) + + if colorspace.to_reference_transforms: + print('Generating To-Reference transforms') + ocio_transform = generate_OCIO_transform( + colorspace.to_reference_transforms) + ocio_colorspace.setTransform( + ocio_transform, + ocio.Constants.COLORSPACE_DIR_TO_REFERENCE) + + if colorspace.from_reference_transforms: + print('Generating From-Reference transforms') + ocio_transform = generate_OCIO_transform( + colorspace.from_reference_transforms) + ocio_colorspace.setTransform( + ocio_transform, + ocio.Constants.COLORSPACE_DIR_FROM_REFERENCE) + + config.addColorSpace(ocio_colorspace) + + print('') + + # Defining the *views* and *displays*. displays = [] views = [] - # Generic display and view setup + # Defining a *generic* *display* and *view* setup. if not nuke: - for display, viewList in configData['displays'].iteritems(): - for viewName, colorspace in viewList.iteritems(): - config.addDisplay(display, viewName, colorspace.name) - if not (viewName in views): - views.append(viewName) + for display, view_list in config_data['displays'].iteritems(): + for view_name, colorspace in view_list.iteritems(): + config.addDisplay(display, view_name, colorspace.name) + if not (view_name in views): + views.append(view_name) displays.append(display) - # A Nuke specific set of views and displays - # - # XXX - # A few names: Output Transform, ACES, ACEScc, are hard-coded here. - # Would be better to automate. - # + # Defining the *Nuke* specific set of *views* and *displays*. else: - for display, viewList in configData['displays'].iteritems(): - for viewName, colorspace in viewList.iteritems(): - if (viewName == 'Output Transform'): - viewName = 'View' - config.addDisplay(display, viewName, colorspace.name) - if not (viewName in views): - views.append(viewName) + for display, view_list in config_data['displays'].iteritems(): + for view_name, colorspace in view_list.iteritems(): + if view_name == 'Output Transform': + view_name = 'View' + config.addDisplay(display, view_name, colorspace.name) + if not (view_name in views): + views.append(view_name) displays.append(display) config.addDisplay('linear', 'View', 'ACES2065-1') @@ -278,243 +316,236 @@ def createConfig(configData, nuke=False): config.addDisplay('log', 'View', 'ACEScc') displays.append('log') - # Set active displays and views + # Setting the active *displays* and *views*. config.setActiveDisplays(','.join(sorted(displays))) config.setActiveViews(','.join(views)) - # - # Need to generalize this at some point - # - - # Add Default Roles - setConfigDefaultRoles(config, - color_picking=reference.getName(), - color_timing=reference.getName(), - compositing_log=reference.getName(), - data=reference.getName(), - default=reference.getName(), - matte_paint=reference.getName(), - reference=reference.getName(), - scene_linear=reference.getName(), - texture_paint=reference.getName()) - - # Check to make sure we didn't screw something up + set_config_default_roles( + config, + color_picking=reference.getName(), + color_timing=reference.getName(), + compositing_log=reference.getName(), + data=reference.getName(), + default=reference.getName(), + matte_paint=reference.getName(), + reference=reference.getName(), + scene_linear=reference.getName(), + texture_paint=reference.getName()) + config.sanityCheck() return config -# -# Functions to generate color space definitions and LUTs for transforms for a -# specific ACES release. -# - -# Output is a list of colorspaces and transforms that convert between those -# colorspaces and reference color space, ACES -def generateLUTs(odtInfo, - lmtInfo, - shaperName, - acesCTLReleaseDir, - lutDir, - lutResolution1d=4096, - lutResolution3d=64, - cleanup=True): - print("generateLUTs - begin") - configData = {} - - # - # Define the reference color space - # +def generate_LUTs(odt_info, + lmt_info, + shaper_name, + aces_CTL_directory, + lut_directory, + lut_resolution_1d=4096, + lut_resolution_3d=64, + cleanup=True): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + dict + Colorspaces and transforms converting between those colorspaces and + the reference colorspace, *ACES*. + """ + + print('generateLUTs - begin') + config_data = {} + + # Defining the reference colorspace. ACES = ColorSpace('ACES2065-1') ACES.description = ( 'The Academy Color Encoding System reference color space') - ACES.equalityGroup = '' + ACES.equality_group = '' ACES.family = 'ACES' - ACES.isData = False - ACES.allocationType = OCIO.Constants.ALLOCATION_LG2 - ACES.allocationVars = [-15, 6] - - configData['referenceColorSpace'] = ACES - - # - # Define the displays - # - configData['displays'] = {} - - # - # Define the other color spaces - # - configData['colorSpaces'] = [] - - # Matrix converting ACES AP1 primaries to AP0 - acesAP1toAP0 = [0.6954522414, 0.1406786965, 0.1638690622, - 0.0447945634, 0.8596711185, 0.0955343182, - -0.0055258826, 0.0040252103, 1.0015006723] - - # Matrix converting ACES AP0 primaries to XYZ - acesAP0toXYZ = [0.9525523959, 0.0000000000, 0.0000936786, - 0.3439664498, 0.7281660966, -0.0721325464, - 0.0000000000, 0.0000000000, 1.0088251844] - - # - # ACEScc - # - def createACEScc(name='ACEScc', - minValue=0.0, - maxValue=1.0, - inputScale=1.0): + ACES.is_data = False + ACES.allocation_type = ocio.Constants.ALLOCATION_LG2 + ACES.allocation_vars = [-15, 6] + + config_data['referenceColorSpace'] = ACES + + config_data['displays'] = {} + config_data['colorSpaces'] = [] + + # Matrix converting *ACES AP1* primaries to *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 *XYZ*. + 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(name='ACEScc', + min_value=0.0, + max_value=1.0, + input_scale=1.0): cs = ColorSpace(name) - cs.description = "The %s color space" % name - cs.equalityGroup = '' + cs.description = 'The %s color space' % name + cs.equality_group = '' cs.family = 'ACES' - cs.isData = False - - ctls = [ - '%s/ACEScc/ACEScsc.ACEScc_to_ACES.a1.0.0.ctl' % acesCTLReleaseDir, - # 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 - '%s/ACEScg/ACEScsc.ACES_to_ACEScg.a1.0.0.ctl' % acesCTLReleaseDir - ] - lut = "%s_to_ACES.spi1d" % name - - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') - - genlut.generate1dLUTFromCTL( - lutDir + "/" + lut, + cs.is_data = False + + 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 + + lut = sanitize_path(lut) + + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, lut), ctls, - lutResolution1d, + lut_resolution_1d, 'float', - inputScale, + input_scale, 1.0, {}, cleanup, - acesCTLReleaseDir, - minValue, - maxValue) + aces_CTL_directory, + min_value, + max_value) - cs.toReferenceTransforms = [] - cs.toReferenceTransforms.append({ + 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.toReferenceTransforms.append({ + # *AP1* primaries to *AP0* primaries. + cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44FromMat33(acesAP1toAP0), - 'direction': 'forward' - }) + 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), + 'direction': 'forward'}) - cs.fromReferenceTransforms = [] + cs.from_reference_transforms = [] return cs - ACEScc = createACEScc() - configData['colorSpaces'].append(ACEScc) + ACEScc = create_ACEScc() + config_data['colorSpaces'].append(ACEScc) - # - # ACESproxy - # - def createACESProxy(name='ACESproxy'): + # ------------------------------------------------------------------------- + # *ACESproxy* + # ------------------------------------------------------------------------- + def create_ACESproxy(name='ACESproxy'): cs = ColorSpace(name) - cs.description = "The %s color space" % name - cs.equalityGroup = '' + cs.description = 'The %s color space' % name + cs.equality_group = '' cs.family = 'ACES' - cs.isData = False - - ctls = [ - '%s/ACESproxy/ACEScsc.ACESproxy10i_to_ACES.a1.0.0.ctl' % ( - acesCTLReleaseDir), - # 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 - '%s/ACEScg/ACEScsc.ACES_to_ACEScg.a1.0.0.ctl' % acesCTLReleaseDir - ] - lut = "%s_to_aces.spi1d" % name - - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') - - genlut.generate1dLUTFromCTL( - lutDir + "/" + lut, + cs.is_data = False + + 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 + + lut = sanitize_path(lut) + + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, lut), ctls, - lutResolution1d, + lut_resolution_1d, 'uint16', 64.0, 1.0, {}, cleanup, - acesCTLReleaseDir) + aces_CTL_directory) - cs.toReferenceTransforms = [] - cs.toReferenceTransforms.append({ + cs.to_reference_transforms = [] + cs.to_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'linear', 'direction': 'forward' }) - # AP1 primaries to AP0 primaries - cs.toReferenceTransforms.append({ + # *AP1* primaries to *AP0* primaries. + cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44FromMat33(acesAP1toAP0), + 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), 'direction': 'forward' }) - cs.fromReferenceTransforms = [] + cs.from_reference_transforms = [] return cs - ACESproxy = createACESProxy() - configData['colorSpaces'].append(ACESproxy) + ACESproxy = create_ACESproxy() + config_data['colorSpaces'].append(ACESproxy) - # - # ACEScg - # - def createACEScg(name='ACEScg'): + # ------------------------------------------------------------------------- + # *ACEScg* + # ------------------------------------------------------------------------- + def create_ACEScg(name='ACEScg'): cs = ColorSpace(name) - cs.description = "The %s color space" % name - cs.equalityGroup = '' + cs.description = 'The %s color space' % name + cs.equality_group = '' cs.family = 'ACES' - cs.isData = False + cs.is_data = False - cs.toReferenceTransforms = [] + cs.to_reference_transforms = [] - # AP1 primaries to AP0 primaries - cs.toReferenceTransforms.append({ + # *AP1* primaries to *AP0* primaries. + cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44FromMat33(acesAP1toAP0), + 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), 'direction': 'forward' }) - cs.fromReferenceTransforms = [] + cs.from_reference_transforms = [] return cs - ACEScg = createACEScg() - configData['colorSpaces'].append(ACEScg) + ACEScg = create_ACEScg() + config_data['colorSpaces'].append(ACEScg) - # - # ADX - # - def createADX(bitdepth=10, name='ADX'): - name = "%s%s" % (name, bitdepth) + # ------------------------------------------------------------------------- + # *ADX* + # ------------------------------------------------------------------------- + def create_ADX(bit_depth=10, name='ADX'): + name = '%s%s' % (name, bit_depth) cs = ColorSpace(name) - cs.description = "%s color space - used for film scans" % name - cs.equalityGroup = '' + cs.description = '%s color space - used for film scans' % name + cs.equality_group = '' cs.family = 'ADX' - cs.isData = False + cs.is_data = False - if bitdepth == 10: - cs.bitDepth = bitDepth = OCIO.Constants.BIT_DEPTH_UINT10 + 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] - elif bitdepth == 16: - cs.bitDepth = bitDepth = OCIO.Constants.BIT_DEPTH_UINT16 + 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, @@ -522,29 +553,28 @@ def generateLUTs(odtInfo, offset = [-1520.0 / 8000.0, -1520.0 / 8000.0, -1520.0 / 8000.0, 0.0] - cs.toReferenceTransforms = [] + cs.to_reference_transforms = [] - # Convert from ADX to Channel-Dependent Density - cs.toReferenceTransforms.append({ + # Converting from *ADX* to *Channel-Dependent Density*. + cs.to_reference_transforms.append({ 'type': 'matrix', 'matrix': adx_to_cdd, 'offset': offset, - 'direction': 'forward' - }) + 'direction': 'forward'}) # Convert from Channel-Dependent Density to Channel-Independent Density - cs.toReferenceTransforms.append({ + cs.to_reference_transforms.append({ 'type': 'matrix', '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], - 'direction': 'forward' - }) + 'direction': 'forward'}) - # Copied from Alex Fry's adx_cid_to_rle.py - def createCIDtoRLELUT(): - def interpolate1D(x, xp, fp): + # Copied from *Alex Fry*'s *adx_cid_to_rle.py* + def create_CID_to_RLE_LUT(): + + def interpolate_1D(x, xp, fp): return numpy.interp(x, xp, fp) LUT_1D_xp = [-0.190000000000000, @@ -576,1025 +606,1097 @@ def generateLUTs(odtInfo, def cid_to_rle(x): if x <= 0.6: - return interpolate1D(x, LUT_1D_xp, LUT_1D_fp) + return interpolate_1D(x, LUT_1D_xp, LUT_1D_fp) return (100.0 / 55.0) * x - REF_PT - def Fit(value, fromMin, fromMax, toMin, toMax): - if fromMin == fromMax: - raise ValueError("fromMin == fromMax") - return (value - fromMin) / (fromMax - fromMin) * ( - toMax - toMin) + toMin + def fit(value, from_min, from_max, to_min, to_max): + if from_min == from_max: + raise ValueError('from_min == from_max') + return (value - from_min) / (from_max - from_min) * ( + to_max - to_min) + to_min NUM_SAMPLES = 2 ** 12 RANGE = (-0.19, 3.0) data = [] for i in xrange(NUM_SAMPLES): x = i / (NUM_SAMPLES - 1.0) - x = Fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) + x = fit(x, 0.0, 1.0, RANGE[0], RANGE[1]) data.append(cid_to_rle(x)) lut = 'ADX_CID_to_RLE.spi1d' - genlut.writeSPI1D(lutDir + "/" + lut, RANGE[0], RANGE[1], data, - NUM_SAMPLES, 1) + write_SPI_1d(os.path.join(lut_directory, lut), + RANGE[0], + RANGE[1], + data, + NUM_SAMPLES, 1) return lut - # Convert Channel Independent Density values to Relative Log Exposure - # values. - lut = createCIDtoRLELUT() - cs.toReferenceTransforms.append({ + # Converting *Channel Independent Density* values to + # *Relative Log Exposure* values. + lut = create_CID_to_RLE_LUT() + cs.to_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'linear', - 'direction': 'forward' - }) + 'direction': 'forward'}) - # Convert Relative Log Exposure values to Relative Exposure values - cs.toReferenceTransforms.append({ + # Converting *Relative Log Exposure* values to + # *Relative Exposure* values. + cs.to_reference_transforms.append({ 'type': 'log', 'base': 10, - 'direction': 'inverse' - }) + 'direction': 'inverse'}) - # Convert Relative Exposure values to ACES values - cs.toReferenceTransforms.append({ + # Convert *Relative Exposure* values to *ACES* values. + cs.to_reference_transforms.append({ 'type': 'matrix', '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], - 'direction': 'forward' - }) + 'direction': 'forward'}) - cs.fromReferenceTransforms = [] + cs.from_reference_transforms = [] return cs - ADX10 = createADX(bitdepth=10) - configData['colorSpaces'].append(ADX10) - - ADX16 = createADX(bitdepth=16) - configData['colorSpaces'].append(ADX16) - - # - # Camera Input Transforms - # - - # RED color spaces to ACES - redColorSpaces = red.createColorSpaces(lutDir, lutResolution1d) - for cs in redColorSpaces: - configData['colorSpaces'].append(cs) - - # Canon-Log to ACES - canonColorSpaces = canon.createColorSpaces(lutDir, lutResolution1d) - for cs in canonColorSpaces: - configData['colorSpaces'].append(cs) - - # SLog to ACES - sonyColorSpaces = sony.createColorSpaces(lutDir, lutResolution1d) - for cs in sonyColorSpaces: - configData['colorSpaces'].append(cs) - - # LogC to ACES - arriColorSpaces = arri.createColorSpaces(lutDir, lutResolution1d) - for cs in arriColorSpaces: - configData['colorSpaces'].append(cs) - - # - # Generic log transform - # - def createGenericLog(name='log', - minValue=0.0, - maxValue=1.0, - inputScale=1.0, - middleGrey=0.18, - minExposure=-6.0, - maxExposure=6.5, - lutResolution1d=lutResolution1d): + ADX10 = create_ADX(bit_depth=10) + config_data['colorSpaces'].append(ADX10) + + ADX16 = create_ADX(bit_depth=16) + config_data['colorSpaces'].append(ADX16) + + # ------------------------------------------------------------------------- + # *Camera Input Transforms* + # ------------------------------------------------------------------------- + + # *RED* colorspaces to *ACES*. + red_colorspaces = red.create_colorspaces(lut_directory, lut_resolution_1d) + for cs in red_colorspaces: + config_data['colorSpaces'].append(cs) + + # *Canon-Log* to *ACES*. + canon_colorspaces = canon.create_colorspaces(lut_directory, + lut_resolution_1d) + for cs in canon_colorspaces: + config_data['colorSpaces'].append(cs) + + # *S-Log* to *ACES*. + sony_colorSpaces = sony.create_colorspaces(lut_directory, + lut_resolution_1d) + for cs in sony_colorSpaces: + config_data['colorSpaces'].append(cs) + + # *Log-C* to *ACES*. + arri_colorSpaces = arri.create_colorspaces(lut_directory, + lut_resolution_1d) + for cs in arri_colorSpaces: + config_data['colorSpaces'].append(cs) + + # ------------------------------------------------------------------------- + # *Generic Log Transform* + # ------------------------------------------------------------------------- + def create_generic_log(name='log', + min_value=0.0, + max_value=1.0, + input_scale=1.0, + middle_grey=0.18, + min_exposure=-6.0, + max_exposure=6.5, + lut_resolution_1d=lut_resolution_1d): cs = ColorSpace(name) - cs.description = "The %s color space" % name - cs.equalityGroup = name + cs.description = 'The %s color space' % name + cs.equality_group = name cs.family = 'Utility' - cs.isData = False + cs.is_data = False - ctls = [ - '%s/utilities/ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl' % ( - acesCTLReleaseDir) - ] - lut = "%s_to_aces.spi1d" % name + ctls = [os.path.join( + aces_CTL_directory, + 'utilities', + 'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl')] + lut = '%s_to_aces.spi1d' % name - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') + lut = sanitize_path(lut) - genlut.generate1dLUTFromCTL( - lutDir + "/" + lut, + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, lut), ctls, - lutResolution1d, + lut_resolution_1d, 'float', - inputScale, + input_scale, 1.0, - { - 'middleGrey': middleGrey, - 'minExposure': minExposure, - 'maxExposure': maxExposure - }, + {'middleGrey': middle_grey, + 'minExposure': min_exposure, + 'maxExposure': max_exposure}, cleanup, - acesCTLReleaseDir, - minValue, - maxValue) + aces_CTL_directory, + min_value, + max_value) - cs.toReferenceTransforms = [] - cs.toReferenceTransforms.append({ + cs.to_reference_transforms = [] + cs.to_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'linear', - 'direction': 'forward' - }) + 'direction': 'forward'}) - cs.fromReferenceTransforms = [] + cs.from_reference_transforms = [] return cs - # - # ACES LMTs - # - def createACESLMT(lmtName, - lmtValues, - shaperInfo, - lutResolution1d=1024, - lutResolution3d=64, - cleanup=True): - cs = ColorSpace("%s" % lmtName) - cs.description = "The ACES Look Transform: %s" % lmtName - cs.equalityGroup = '' + # ------------------------------------------------------------------------- + # *ACES LMTs* + # ------------------------------------------------------------------------- + def create_ACES_LMT(lmt_name, + lmt_values, + shaper_info, + lut_resolution_1d=1024, + lut_resolution_3d=64, + cleanup=True): + cs = ColorSpace('%s' % lmt_name) + cs.description = 'The ACES Look Transform: %s' % lmt_name + cs.equality_group = '' cs.family = 'Look' - cs.isData = False - - import pprint + cs.is_data = False - pprint.pprint(lmtValues) + pprint.pprint(lmt_values) - # - # Generate the shaper transform - # - (shaperName, - shaperToACESCTL, - shaperFromACESCTL, - shaperInputScale, - shaperParams) = shaperInfo + # Generating the *shaper* transform. + (shaper_name, + shaper_to_ACES_CTL, + shaper_from_ACES_CTL, + shaper_input_scale, + shaper_params) = shaper_info - shaperLut = "%s_to_aces.spi1d" % shaperName - if (not os.path.exists(lutDir + "/" + shaperLut)): - ctls = [ - shaperToACESCTL % acesCTLReleaseDir - ] + 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] - # Remove spaces and parentheses - shaperLut = shaperLut.replace( - ' ', '_').replace(')', '_').replace('(', '_') + shaper_lut = sanitize_path(shaper_lut) - genlut.generate1dLUTFromCTL( - lutDir + "/" + shaperLut, + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, shaper_lut), ctls, - lutResolution1d, + lut_resolution_1d, 'float', - 1.0 / shaperInputScale, + 1.0 / shaper_input_scale, 1.0, - shaperParams, + shaper_params, cleanup, - acesCTLReleaseDir) + aces_CTL_directory) - shaperOCIOTransform = { + shaper_OCIO_transform = { 'type': 'lutFile', - 'path': shaperLut, + 'path': shaper_lut, 'interpolation': 'linear', - 'direction': 'inverse' - } + 'direction': 'inverse'} - # - # Generate the forward transform - # - cs.fromReferenceTransforms = [] + # Generating the forward transform. + cs.from_reference_transforms = [] - if 'transformCTL' in lmtValues: - ctls = [ - shaperToACESCTL % acesCTLReleaseDir, - '%s/%s' % (acesCTLReleaseDir, lmtValues['transformCTL']) - ] - lut = "%s.%s.spi3d" % (shaperName, lmtName) + if 'transformCTL' in lmt_values: + 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) - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') + lut = sanitize_path(lut) - genlut.generate3dLUTFromCTL( - lutDir + "/" + lut, + generate_3d_LUT_from_CTL( + os.path.join(lut_directory, lut), ctls, - lutResolution3d, + lut_resolution_3d, 'float', - 1.0 / shaperInputScale, + 1.0 / shaper_input_scale, 1.0, - shaperParams, + shaper_params, cleanup, - acesCTLReleaseDir) + aces_CTL_directory) - cs.fromReferenceTransforms.append(shaperOCIOTransform) - cs.fromReferenceTransforms.append({ + cs.from_reference_transforms.append(shaper_OCIO_transform) + cs.from_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'tetrahedral', 'direction': 'forward' }) - # - # Generate the inverse transform - # - cs.toReferenceTransforms = [] + # Generating the inverse transform. + cs.to_reference_transforms = [] - if 'transformCTLInverse' in lmtValues: - ctls = [ - '%s/%s' % ( - acesCTLReleaseDir, odtValues['transformCTLInverse']), - shaperFromACESCTL % acesCTLReleaseDir - ] - lut = "Inverse.%s.%s.spi3d" % (odtName, shaperName) + if 'transformCTLInverse' in lmt_values: + ctls = [os.path.join(aces_CTL_directory, + odt_values['transformCTLInverse']), + shaper_from_ACES_CTL % aces_CTL_directory] + lut = 'Inverse.%s.%s.spi3d' % (odt_name, shaper_name) - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') + lut = sanitize_path(lut) - genlut.generate3dLUTFromCTL( - lutDir + "/" + lut, + generate_3d_LUT_from_CTL( + os.path.join(lut_directory, lut), ctls, - lutResolution3d, + lut_resolution_3d, 'half', 1.0, - shaperInputScale, - shaperParams, + shaper_input_scale, + shaper_params, cleanup, - acesCTLReleaseDir) + aces_CTL_directory) - cs.toReferenceTransforms.append({ + cs.to_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'tetrahedral', - 'direction': 'forward' - }) + 'direction': 'forward'}) - shaperInverse = shaperOCIOTransform.copy() - shaperInverse['direction'] = 'forward' - cs.toReferenceTransforms.append(shaperInverse) + shaper_inverse = shaper_OCIO_transform.copy() + shaper_inverse['direction'] = 'forward' + cs.to_reference_transforms.append(shaper_inverse) return cs - # - # LMT Shaper - # + # ------------------------------------------------------------------------- + # *LMT Shaper* + # ------------------------------------------------------------------------- - lmtLutResolution1d = max(4096, lutResolution1d) - lmtLutResolution3d = max(65, lutResolution3d) + lmt_lut_resolution_1d = max(4096, lut_resolution_1d) + lmt_lut_resolution_3d = max(65, lut_resolution_3d) - # Log 2 shaper - lmtShaperName = 'LMT Shaper' - lmtParams = { + # Defining the *Log 2* shaper. + lmt_shaper_name = 'LMT Shaper' + lmt_params = { 'middleGrey': 0.18, 'minExposure': -10.0, - 'maxExposure': 6.5 - } - lmtShaper = createGenericLog(name=lmtShaperName, - middleGrey=lmtParams['middleGrey'], - minExposure=lmtParams['minExposure'], - maxExposure=lmtParams['maxExposure'], - lutResolution1d=lmtLutResolution1d) - configData['colorSpaces'].append(lmtShaper) - - shaperInputScale_genericLog2 = 1.0 - - # Log 2 shaper name and CTL transforms bundled up - lmtShaperData = [ - lmtShaperName, - '%s/utilities/ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl', - '%s/utilities/ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl', - shaperInputScale_genericLog2, - lmtParams - ] - - sortedLMTs = sorted(lmtInfo.iteritems(), key=lambda x: x[1]) - print(sortedLMTs) - for lmt in sortedLMTs: - (lmtName, lmtValues) = lmt - cs = createACESLMT( - lmtValues['transformUserName'], - lmtValues, - lmtShaperData, - lmtLutResolution1d, - lmtLutResolution3d, + 'maxExposure': 6.5} + + lmt_shaper = create_generic_log(name=lmt_shaper_name, + middle_grey=lmt_params['middleGrey'], + min_exposure=lmt_params['minExposure'], + max_exposure=lmt_params['maxExposure'], + lut_resolution_1d=lmt_lut_resolution_1d) + config_data['colorSpaces'].append(lmt_shaper) + + shaper_input_scale_generic_log2 = 1.0 + + # *Log 2* shaper name and *CTL* transforms bundled up. + lmt_shaper_data = [ + lmt_shaper_name, + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl'), + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl'), + shaper_input_scale_generic_log2, + lmt_params] + + sorted_LMTs = sorted(lmt_info.iteritems(), key=lambda x: x[1]) + print(sorted_LMTs) + for lmt in sorted_LMTs: + (lmt_name, lmt_values) = lmt + cs = create_ACES_LMT( + lmt_values['transformUserName'], + lmt_values, + lmt_shaper_data, + lmt_lut_resolution_1d, + lmt_lut_resolution_3d, cleanup) - configData['colorSpaces'].append(cs) - - # - # ACES RRT with the supplied ODT - # - def createACESRRTplusODT(odtName, - odtValues, - shaperInfo, - lutResolution1d=1024, - lutResolution3d=64, - cleanup=True): - cs = ColorSpace("%s" % odtName) - cs.description = "%s - %s Output Transform" % ( - odtValues['transformUserNamePrefix'], odtName) - cs.equalityGroup = '' + config_data['colorSpaces'].append(cs) + + # ------------------------------------------------------------------------- + # *ACES RRT* with supplied *ODT*. + # ------------------------------------------------------------------------- + def create_ACES_RRT_plus_ODT(odt_name, + odt_values, + shaper_info, + lut_resolution_1d=1024, + lut_resolution_3d=64, + cleanup=True): + cs = ColorSpace('%s' % odt_name) + cs.description = '%s - %s Output Transform' % ( + odt_values['transformUserNamePrefix'], odt_name) + cs.equality_group = '' cs.family = 'Output' - cs.isData = False - - import pprint + cs.is_data = False - pprint.pprint(odtValues) + pprint.pprint(odt_values) - # - # Generate the shaper transform - # - # if 'shaperCTL' in odtValues: - (shaperName, - shaperToACESCTL, - shaperFromACESCTL, - shaperInputScale, - shaperParams) = shaperInfo + # Generating the *shaper* transform. + (shaper_name, + shaper_to_ACES_CTL, + shaper_from_ACES_CTL, + shaper_input_scale, + shaper_params) = shaper_info - if 'legalRange' in odtValues: - shaperParams['legalRange'] = odtValues['legalRange'] + if 'legalRange' in odt_values: + shaper_params['legalRange'] = odt_values['legalRange'] else: - shaperParams['legalRange'] = 0 + shaper_params['legalRange'] = 0 - shaperLut = "%s_to_aces.spi1d" % shaperName - if (not os.path.exists(lutDir + "/" + shaperLut)): - ctls = [ - shaperToACESCTL % acesCTLReleaseDir - ] + 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] - # Remove spaces and parentheses - shaperLut = shaperLut.replace( - ' ', '_').replace(')', '_').replace('(', '_') + shaper_lut = sanitize_path(shaper_lut) - genlut.generate1dLUTFromCTL( - lutDir + "/" + shaperLut, + generate_1d_LUT_from_CTL( + os.path.join(lut_directory, shaper_lut), ctls, - lutResolution1d, + lut_resolution_1d, 'float', - 1.0 / shaperInputScale, + 1.0 / shaper_input_scale, 1.0, - shaperParams, + shaper_params, cleanup, - acesCTLReleaseDir) + aces_CTL_directory) - shaperOCIOTransform = { + shaper_OCIO_transform = { 'type': 'lutFile', - 'path': shaperLut, + 'path': shaper_lut, 'interpolation': 'linear', - 'direction': 'inverse' - } - - # - # Generate the forward transform - # - cs.fromReferenceTransforms = [] - - if 'transformLUT' in odtValues: - # Copy into the lut dir - transformLUTFileName = os.path.basename(odtValues['transformLUT']) - lut = lutDir + "/" + transformLUTFileName - shutil.copy(odtValues['transformLUT'], lut) - - cs.fromReferenceTransforms.append(shaperOCIOTransform) - cs.fromReferenceTransforms.append({ + 'direction': 'inverse'} + + # Generating the *forward* transform. + cs.from_reference_transforms = [] + + if 'transformLUT' in odt_values: + transform_LUT_file_name = os.path.basename( + odt_values['transformLUT']) + lut = os.path.join(lut_directory, transform_LUT_file_name) + shutil.copy(odt_values['transformLUT'], lut) + + cs.from_reference_transforms.append(shaper_OCIO_transform) + cs.from_reference_transforms.append({ 'type': 'lutFile', - 'path': transformLUTFileName, + 'path': transform_LUT_file_name, 'interpolation': 'tetrahedral', - 'direction': 'forward' - }) - elif 'transformCTL' in odtValues: - # shaperLut - + 'direction': 'forward'}) + elif 'transformCTL' in odt_values: ctls = [ - shaperToACESCTL % acesCTLReleaseDir, - '%s/rrt/RRT.a1.0.0.ctl' % acesCTLReleaseDir, - '%s/odt/%s' % (acesCTLReleaseDir, odtValues['transformCTL']) - ] - lut = "%s.RRT.a1.0.0.%s.spi3d" % (shaperName, odtName) - - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') - - genlut.generate3dLUTFromCTL(lutDir + "/" + lut, - # shaperLUT, - ctls, - lutResolution3d, - 'float', - 1.0 / shaperInputScale, - 1.0, - shaperParams, - cleanup, - acesCTLReleaseDir) - - cs.fromReferenceTransforms.append(shaperOCIOTransform) - cs.fromReferenceTransforms.append({ + 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, + 'odt', + odt_values['transformCTL'])] + lut = '%s.RRT.a1.0.0.%s.spi3d' % (shaper_name, odt_name) + + lut = sanitize_path(lut) + + generate_3d_LUT_from_CTL( + os.path.join(lut_directory, lut), + # shaperLUT, + ctls, + lut_resolution_3d, + 'float', + 1.0 / shaper_input_scale, + 1.0, + shaper_params, + cleanup, + 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'}) - # - # Generate the inverse transform - # - cs.toReferenceTransforms = [] + # Generating the *inverse* transform. + cs.to_reference_transforms = [] - if 'transformLUTInverse' in odtValues: - # Copy into the lut dir - transformLUTInverseFileName = os.path.basename( - odtValues['transformLUTInverse']) - lut = lutDir + "/" + transformLUTInverseFileName - shutil.copy(odtValues['transformLUTInverse'], lut) + if 'transformLUTInverse' in odt_values: + transform_LUT_inverse_file_name = os.path.basename( + odt_values['transformLUTInverse']) + lut = os.path.join(lut_directory, transform_LUT_inverse_file_name) + shutil.copy(odt_values['transformLUTInverse'], lut) - cs.toReferenceTransforms.append({ + cs.to_reference_transforms.append({ 'type': 'lutFile', - 'path': transformLUTInverseFileName, + 'path': transform_LUT_inverse_file_name, 'interpolation': 'tetrahedral', - 'direction': 'forward' - }) - - shaperInverse = shaperOCIOTransform.copy() - shaperInverse['direction'] = 'forward' - cs.toReferenceTransforms.append(shaperInverse) - elif 'transformCTLInverse' in odtValues: - ctls = [ - '%s/odt/%s' % ( - acesCTLReleaseDir, odtValues['transformCTLInverse']), - '%s/rrt/InvRRT.a1.0.0.ctl' % acesCTLReleaseDir, - shaperFromACESCTL % acesCTLReleaseDir - ] - lut = "InvRRT.a1.0.0.%s.%s.spi3d" % (odtName, shaperName) - - # Remove spaces and parentheses - lut = lut.replace(' ', '_').replace(')', '_').replace('(', '_') - - genlut.generate3dLUTFromCTL( - lutDir + "/" + lut, + 'direction': 'forward'}) + + shaper_inverse = shaper_OCIO_transform.copy() + shaper_inverse['direction'] = 'forward' + cs.to_reference_transforms.append(shaper_inverse) + elif 'transformCTLInverse' in odt_values: + ctls = [os.path.join(aces_CTL_directory, + 'odt', + odt_values['transformCTLInverse']), + os.path.join(aces_CTL_directory, + 'rrt', + 'InvRRT.a1.0.0.ctl'), + shaper_from_ACES_CTL % aces_CTL_directory] + lut = 'InvRRT.a1.0.0.%s.%s.spi3d' % (odt_name, shaper_name) + + lut = sanitize_path(lut) + + generate_3d_LUT_from_CTL( + os.path.join(lut_directory, lut), # None, ctls, - lutResolution3d, + lut_resolution_3d, 'half', 1.0, - shaperInputScale, - shaperParams, + shaper_input_scale, + shaper_params, cleanup, - acesCTLReleaseDir) + aces_CTL_directory) - cs.toReferenceTransforms.append({ + cs.to_reference_transforms.append({ 'type': 'lutFile', 'path': lut, 'interpolation': 'tetrahedral', - 'direction': 'forward' - }) + 'direction': 'forward'}) - shaperInverse = shaperOCIOTransform.copy() - shaperInverse['direction'] = 'forward' - cs.toReferenceTransforms.append(shaperInverse) + shaper_inverse = shaper_OCIO_transform.copy() + shaper_inverse['direction'] = 'forward' + cs.to_reference_transforms.append(shaper_inverse) return cs - # - # RRT/ODT shaper options - # - shaperData = {} + # ------------------------------------------------------------------------- + # *RRT / ODT* Shaper Options + # ------------------------------------------------------------------------- + shaper_data = {} - # Log 2 shaper - log2ShaperName = shaperName - log2Params = { + # Defining the *Log 2* shaper. + log2_shaper_name = shaper_name + log2_params = { 'middleGrey': 0.18, 'minExposure': -6.0, - 'maxExposure': 6.5 - } - log2Shaper = createGenericLog(name=log2ShaperName, - middleGrey=log2Params['middleGrey'], - minExposure=log2Params['minExposure'], - maxExposure=log2Params['maxExposure']) - configData['colorSpaces'].append(log2Shaper) - - shaperInputScale_genericLog2 = 1.0 - - # Log 2 shaper name and CTL transforms bundled up - log2ShaperData = [ - log2ShaperName, - '%s/utilities/ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl', - '%s/utilities/ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl', - shaperInputScale_genericLog2, - log2Params - ] - - shaperData[log2ShaperName] = log2ShaperData - - # - # Shaper that also includes the AP1 primaries - # - Needed for some LUT baking steps - # - log2ShaperAP1 = createGenericLog(name=log2ShaperName, - middleGrey=log2Params['middleGrey'], - minExposure=log2Params['minExposure'], - maxExposure=log2Params['maxExposure']) - log2ShaperAP1.name = "%s - AP1" % log2ShaperAP1.name - # AP1 primaries to AP0 primaries - log2ShaperAP1.toReferenceTransforms.append({ + 'maxExposure': 6.5} + + log2_shaper = create_generic_log( + name=log2_shaper_name, + middle_grey=log2_params['middleGrey'], + min_exposure=log2_params['minExposure'], + max_exposure=log2_params['maxExposure']) + config_data['colorSpaces'].append(log2_shaper) + + shaper_input_scale_generic_log2 = 1.0 + + # *Log 2* shaper name and *CTL* transforms bundled up. + log2_shaper_data = [ + log2_shaper_name, + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_log2_to_lin_param.a1.0.0.ctl'), + os.path.join('%s', + 'utilities', + 'ACESlib.OCIO_shaper_lin_to_log2_param.a1.0.0.ctl'), + shaper_input_scale_generic_log2, + log2_params] + + shaper_data[log2_shaper_name] = log2_shaper_data + + # Shaper that also includes the AP1 primaries. + # Needed for some LUT baking steps. + log2_shaper_AP1 = create_generic_log( + name=log2_shaper_name, + middle_grey=log2_params['middleGrey'], + min_exposure=log2_params['minExposure'], + max_exposure=log2_params['maxExposure']) + log2_shaper_AP1.name = '%s - AP1' % log2_shaper_AP1.name + + # *AP1* primaries to *AP0* primaries. + log2_shaper_AP1.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44FromMat33(acesAP1toAP0), + 'matrix': mat44_from_mat33(ACES_AP1_to_AP0), 'direction': 'forward' }) - configData['colorSpaces'].append(log2ShaperAP1) - - # - # Choose your shaper - # - rrtShaperName = log2ShaperName - rrtShaper = log2ShaperData - - # - # RRT + ODT Combinations - # - sortedOdts = sorted(odtInfo.iteritems(), key=lambda x: x[1]) - print(sortedOdts) - for odt in sortedOdts: - (odtName, odtValues) = odt - - # Have to handle ODTs that can generate either legal or full output - if odtName in ['Academy.Rec2020_100nits_dim.a1.0.0', - 'Academy.Rec709_100nits_dim.a1.0.0', - 'Academy.Rec709_D60sim_100nits_dim.a1.0.0']: - odtNameLegal = '%s - Legal' % odtValues['transformUserName'] + config_data['colorSpaces'].append(log2_shaper_AP1) + + rrt_shaper = log2_shaper_data + + # *RRT + ODT* combinations. + sorted_odts = sorted(odt_info.iteritems(), key=lambda x: x[1]) + print(sorted_odts) + for odt in sorted_odts: + (odt_name, odt_values) = odt + + # Handling *ODTs* that can generate either *legal* or *full* output. + if odt_name in ['Academy.Rec2020_100nits_dim.a1.0.0', + 'Academy.Rec709_100nits_dim.a1.0.0', + 'Academy.Rec709_D60sim_100nits_dim.a1.0.0']: + odt_name_legal = '%s - Legal' % odt_values['transformUserName'] else: - odtNameLegal = odtValues['transformUserName'] + odt_name_legal = odt_values['transformUserName'] - odtLegal = odtValues.copy() - odtLegal['legalRange'] = 1 + odt_legal = odt_values.copy() + odt_legal['legalRange'] = 1 - cs = createACESRRTplusODT( - odtNameLegal, - odtLegal, - rrtShaper, - lutResolution1d, - lutResolution3d, + cs = create_ACES_RRT_plus_ODT( + odt_name_legal, + odt_legal, + rrt_shaper, + lut_resolution_1d, + lut_resolution_3d, cleanup) - configData['colorSpaces'].append(cs) + config_data['colorSpaces'].append(cs) - # Create a display entry using this color space - configData['displays'][odtNameLegal] = { + config_data['displays'][odt_name_legal] = { 'Linear': ACES, 'Log': ACEScc, 'Output Transform': cs} - if odtName in ['Academy.Rec2020_100nits_dim.a1.0.0', - 'Academy.Rec709_100nits_dim.a1.0.0', - 'Academy.Rec709_D60sim_100nits_dim.a1.0.0']: - print("Generating full range ODT for %s" % odtName) - - odtNameFull = "%s - Full" % odtValues['transformUserName'] - odtFull = odtValues.copy() - odtFull['legalRange'] = 0 - - csFull = createACESRRTplusODT( - odtNameFull, - odtFull, - rrtShaper, - lutResolution1d, - lutResolution3d, + if odt_name in ['Academy.Rec2020_100nits_dim.a1.0.0', + 'Academy.Rec709_100nits_dim.a1.0.0', + 'Academy.Rec709_D60sim_100nits_dim.a1.0.0']: + print('Generating full range ODT for %s' % odt_name) + + odt_name_full = '%s - Full' % odt_values['transformUserName'] + odt_full = odt_values.copy() + odt_full['legalRange'] = 0 + + cs_full = create_ACES_RRT_plus_ODT( + odt_name_full, + odt_full, + rrt_shaper, + lut_resolution_1d, + lut_resolution_3d, cleanup) - configData['colorSpaces'].append(csFull) + config_data['colorSpaces'].append(cs_full) - # Create a display entry using this color space - configData['displays'][odtNameFull] = { + config_data['displays'][odt_name_full] = { 'Linear': ACES, 'Log': ACEScc, - 'Output Transform': csFull} + 'Output Transform': cs_full} - # + # ------------------------------------------------------------------------- # Generic Matrix transform - # - def createGenericMatrix(name='matrix', - fromReferenceValues=[], - toReferenceValues=[]): + # ------------------------------------------------------------------------- + def create_generic_matrix(name='matrix', + from_reference_values=None, + to_reference_values=None): + + if from_reference_values is None: + from_reference_values = [] + if to_reference_values is None: + to_reference_values = [] + cs = ColorSpace(name) - cs.description = "The %s color space" % name - cs.equalityGroup = name + cs.description = 'The %s color space' % name + cs.equality_group = name cs.family = 'Utility' - cs.isData = False + cs.is_data = False - cs.toReferenceTransforms = [] - if toReferenceValues != []: - for matrix in toReferenceValues: - cs.toReferenceTransforms.append({ + cs.to_reference_transforms = [] + if to_reference_values: + for matrix in to_reference_values: + cs.to_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44FromMat33(matrix), - 'direction': 'forward' - }) - - cs.fromReferenceTransforms = [] - if fromReferenceValues != []: - for matrix in fromReferenceValues: - cs.fromReferenceTransforms.append({ + 'matrix': mat44_from_mat33(matrix), + 'direction': 'forward'}) + + cs.from_reference_transforms = [] + if from_reference_values: + for matrix in from_reference_values: + cs.from_reference_transforms.append({ 'type': 'matrix', - 'matrix': mat44FromMat33(matrix), - 'direction': 'forward' - }) + 'matrix': mat44_from_mat33(matrix), + 'direction': 'forward'}) return cs - cs = createGenericMatrix('XYZ', fromReferenceValues=[acesAP0toXYZ]) - configData['colorSpaces'].append(cs) - - cs = createGenericMatrix('Linear - AP1', toReferenceValues=[acesAP1toAP0]) - configData['colorSpaces'].append(cs) - - # ACES to Linear, P3D60 primaries - xyzToP3D60 = [2.4027414142, -0.8974841639, -0.3880533700, - -0.8325796487, 1.7692317536, 0.0237127115, - 0.0388233815, -0.0824996856, 1.0363685997] - - cs = createGenericMatrix('Linear - P3-D60', - fromReferenceValues=[acesAP0toXYZ, xyzToP3D60]) - configData['colorSpaces'].append(cs) - - # ACES to Linear, P3D60 primaries - xyzToP3DCI = [2.7253940305, -1.0180030062, -0.4401631952, - -0.7951680258, 1.6897320548, 0.0226471906, - 0.0412418914, -0.0876390192, 1.1009293786] - - cs = createGenericMatrix('Linear - P3-DCI', - fromReferenceValues=[acesAP0toXYZ, xyzToP3DCI]) - configData['colorSpaces'].append(cs) - - # ACES to Linear, Rec 709 primaries - xyzToRec709 = [3.2409699419, -1.5373831776, -0.4986107603, - -0.9692436363, 1.8759675015, 0.0415550574, - 0.0556300797, -0.2039769589, 1.0569715142] - - cs = createGenericMatrix('Linear - Rec.709', - fromReferenceValues=[acesAP0toXYZ, xyzToRec709]) - configData['colorSpaces'].append(cs) - - # ACES to Linear, Rec 2020 primaries - xyzToRec2020 = [1.7166511880, -0.3556707838, -0.2533662814, - -0.6666843518, 1.6164812366, 0.0157685458, - 0.0176398574, -0.0427706133, 0.9421031212] - - cs = createGenericMatrix('Linear - Rec.2020', - fromReferenceValues=[acesAP0toXYZ, xyzToRec2020]) - configData['colorSpaces'].append(cs) - - print("generateLUTs - end") - return configData - - -def generateBakedLUTs(odtInfo, - shaperName, - bakedDir, - configPath, - lutResolution1d, - lutResolution3d, - lutResolutionShaper=1024): - # Add the legal and full variations into this list - odtInfoC = dict(odtInfo) - for odtCTLName, odtValues in odtInfo.iteritems(): - if odtCTLName in ['Academy.Rec2020_100nits_dim.a1.0.0', - 'Academy.Rec709_100nits_dim.a1.0.0', - 'Academy.Rec709_D60sim_100nits_dim.a1.0.0']: - odtName = odtValues["transformUserName"] - - odtValuesLegal = dict(odtValues) - odtValuesLegal["transformUserName"] = "%s - Legal" % odtName - odtInfoC["%s - Legal" % odtCTLName] = odtValuesLegal - - odtValuesFull = dict(odtValues) - odtValuesFull["transformUserName"] = "%s - Full" % odtName - odtInfoC["%s - Full" % odtCTLName] = odtValuesFull - - del (odtInfoC[odtCTLName]) - - for odtCTLName, odtValues in odtInfoC.iteritems(): - odtPrefix = odtValues["transformUserNamePrefix"] - odtName = odtValues["transformUserName"] - - # For Photoshop - for inputspace in ["ACEScc", "ACESproxy"]: - args = ["--iconfig", configPath, "-v", "--inputspace", inputspace] - args += ["--outputspace", "%s" % odtName] - args += ["--description", - "%s - %s for %s data" % (odtPrefix, odtName, inputspace)] - args += ["--shaperspace", shaperName, "--shapersize", - str(lutResolutionShaper)] - args += ["--cubesize", str(lutResolution3d)] - args += ["--format", "icc", "%s/photoshop/%s for %s.icc" % ( - bakedDir, odtName, inputspace)] - - bakeLUT = Process(description="bake a LUT", cmd="ociobakelut", - args=args) - bakeLUT.execute() - - # For Flame, Lustre - for inputspace in ["ACEScc", "ACESproxy"]: - args = ["--iconfig", configPath, "-v", "--inputspace", inputspace] - args += ["--outputspace", "%s" % odtName] - args += ["--description", - "%s - %s for %s data" % (odtPrefix, odtName, inputspace)] - args += ["--shaperspace", shaperName, "--shapersize", - str(lutResolutionShaper)] - args += ["--cubesize", str(lutResolution3d)] - - fargs = ["--format", "flame", "%s/flame/%s for %s Flame.3dl" % ( - bakedDir, odtName, inputspace)] - bakeLUT = Process(description="bake a LUT", cmd="ociobakelut", - args=(args + fargs)) - bakeLUT.execute() - - largs = ["--format", "lustre", "%s/lustre/%s for %s Lustre.3dl" % ( - bakedDir, odtName, inputspace)] - bakeLUT = Process(description="bake a LUT", cmd="ociobakelut", - args=(args + largs)) - bakeLUT.execute() - - # For Maya, Houdini - for inputspace in ["ACEScg", "ACES2065-1"]: - args = ["--iconfig", configPath, "-v", "--inputspace", inputspace] - args += ["--outputspace", "%s" % odtName] - args += ["--description", - "%s - %s for %s data" % (odtPrefix, odtName, inputspace)] - if inputspace == 'ACEScg': - linShaperName = "%s - AP1" % shaperName + cs = create_generic_matrix('XYZ', from_reference_values=[ACES_AP0_to_XYZ]) + config_data['colorSpaces'].append(cs) + + cs = create_generic_matrix( + 'Linear - AP1', to_reference_values=[ACES_AP1_to_AP0]) + config_data['colorSpaces'].append(cs) + + # *ACES* to *Linear*, *P3D60* primaries. + XYZ_to_P3D60 = [2.4027414142, -0.8974841639, -0.3880533700, + -0.8325796487, 1.7692317536, 0.0237127115, + 0.0388233815, -0.0824996856, 1.0363685997] + + cs = create_generic_matrix( + 'Linear - P3-D60', + from_reference_values=[ACES_AP0_to_XYZ, XYZ_to_P3D60]) + config_data['colorSpaces'].append(cs) + + # *ACES* to *Linear*, *P3DCI* primaries. + XYZ_to_P3DCI = [2.7253940305, -1.0180030062, -0.4401631952, + -0.7951680258, 1.6897320548, 0.0226471906, + 0.0412418914, -0.0876390192, 1.1009293786] + + cs = create_generic_matrix( + 'Linear - P3-DCI', + from_reference_values=[ACES_AP0_to_XYZ, XYZ_to_P3DCI]) + config_data['colorSpaces'].append(cs) + + # *ACES* to *Linear*, *Rec. 709* primaries. + XYZ_to_Rec709 = [3.2409699419, -1.5373831776, -0.4986107603, + -0.9692436363, 1.8759675015, 0.0415550574, + 0.0556300797, -0.2039769589, 1.0569715142] + + cs = create_generic_matrix( + 'Linear - Rec.709', + from_reference_values=[ACES_AP0_to_XYZ, XYZ_to_Rec709]) + config_data['colorSpaces'].append(cs) + + # *ACES* to *Linear*, *Rec. 2020* primaries. + XYZ_to_Rec2020 = [1.7166511880, -0.3556707838, -0.2533662814, + -0.6666843518, 1.6164812366, 0.0157685458, + 0.0176398574, -0.0427706133, 0.9421031212] + + cs = create_generic_matrix( + 'Linear - Rec.2020', + from_reference_values=[ACES_AP0_to_XYZ, XYZ_to_Rec2020]) + config_data['colorSpaces'].append(cs) + + print('generateLUTs - end') + return config_data + + +def generate_baked_LUTs(odt_info, + shaper_name, + baked_directory, + config_path, + lut_resolution_1d, + lut_resolution_3d, + lut_resolution_shaper=1024): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + odt_info_C = dict(odt_info) + for odt_CTL_name, odt_values in odt_info.iteritems(): + if odt_CTL_name in ['Academy.Rec2020_100nits_dim.a1.0.0', + 'Academy.Rec709_100nits_dim.a1.0.0', + 'Academy.Rec709_D60sim_100nits_dim.a1.0.0']: + odt_name = odt_values['transformUserName'] + + odt_values_legal = dict(odt_values) + odt_values_legal['transformUserName'] = '%s - Legal' % odt_name + odt_info_C['%s - Legal' % odt_CTL_name] = odt_values_legal + + odt_values_full = dict(odt_values) + odt_values_full['transformUserName'] = '%s - Full' % odt_name + odt_info_C['%s - Full' % odt_CTL_name] = odt_values_full + + del (odt_info_C[odt_CTL_name]) + + for odt_CTL_name, odt_values in odt_info_C.iteritems(): + odt_prefix = odt_values['transformUserNamePrefix'] + odt_name = odt_values['transformUserName'] + + # *Photoshop* + for input_space in ['ACEScc', 'ACESproxy']: + args = ['--iconfig', config_path, + '-v', + '--inputspace', input_space] + args += ['--outputspace', '%s' % odt_name] + args += ['--description', + '%s - %s for %s data' % (odt_prefix, + odt_name, + input_space)] + args += ['--shaperspace', shaper_name, + '--shapersize', str(lut_resolution_shaper)] + args += ['--cubesize', str(lut_resolution_3d)] + args += ['--format', + 'icc', + os.path.join(baked_directory, + 'photoshop', + '%s for %s.icc' % (odt_name, input_space))] + + bake_LUT = Process(description='bake a LUT', + cmd='ociobakelut', + args=args) + bake_LUT.execute() + + # *Flame*, *Lustre* + for input_space in ['ACEScc', 'ACESproxy']: + args = ['--iconfig', config_path, + '-v', + '--inputspace', input_space] + args += ['--outputspace', '%s' % odt_name] + args += ['--description', + '%s - %s for %s data' % ( + odt_prefix, odt_name, input_space)] + args += ['--shaperspace', shaper_name, + '--shapersize', str(lut_resolution_shaper)] + args += ['--cubesize', str(lut_resolution_3d)] + + fargs = ['--format', + 'flame', + os.path.join( + baked_directory, + 'flame', + '%s for %s Flame.3dl' % (odt_name, input_space))] + bake_LUT = Process(description='bake a LUT', + cmd='ociobakelut', + args=(args + fargs)) + bake_LUT.execute() + + largs = ['--format', + 'lustre', + os.path.join( + baked_directory, + 'lustre', + '%s for %s Lustre.3dl' % (odt_name, input_space))] + bake_LUT = Process(description='bake a LUT', + cmd='ociobakelut', + args=(args + largs)) + bake_LUT.execute() + + # *Maya*, *Houdini* + for input_space in ['ACEScg', 'ACES2065-1']: + args = ['--iconfig', config_path, + '-v', + '--inputspace', input_space] + args += ['--outputspace', '%s' % odt_name] + args += ['--description', + '%s - %s for %s data' % ( + odt_prefix, odt_name, input_space)] + if input_space == 'ACEScg': + lin_shaper_name = '%s - AP1' % shaper_name else: - linShaperName = shaperName - args += ["--shaperspace", linShaperName, "--shapersize", - str(lutResolutionShaper)] - - args += ["--cubesize", str(lutResolution3d)] - - margs = ["--format", "cinespace", "%s/maya/%s for %s Maya.csp" % ( - bakedDir, odtName, inputspace)] - bakeLUT = Process(description="bake a LUT", cmd="ociobakelut", - args=(args + margs)) - bakeLUT.execute() - - hargs = ["--format", "houdini", - "%s/houdini/%s for %s Houdini.lut" % ( - bakedDir, odtName, inputspace)] - bakeLUT = Process(description="bake a LUT", cmd="ociobakelut", - args=(args + hargs)) - bakeLUT.execute() - - -def createConfigDir(configDir, bakeSecondaryLUTs): - dirs = [configDir, "%s/luts" % configDir] - if bakeSecondaryLUTs: - dirs.extend(["%s/baked" % configDir, - "%s/baked/flame" % configDir, - "%s/baked/photoshop" % configDir, - "%s/baked/houdini" % configDir, - "%s/baked/lustre" % configDir, - "%s/baked/maya" % configDir]) + lin_shaper_name = shaper_name + args += ['--shaperspace', lin_shaper_name, + '--shapersize', str(lut_resolution_shaper)] + + args += ['--cubesize', str(lut_resolution_3d)] + + margs = ['--format', + 'cinespace', + os.path.join( + baked_directory, + 'maya', + '%s for %s Maya.csp' % (odt_name, input_space))] + bake_LUT = Process(description='bake a LUT', + cmd='ociobakelut', + args=(args + margs)) + bake_LUT.execute() + + hargs = ['--format', + 'houdini', + os.path.join( + baked_directory, + 'houdini', + '%s for %s Houdini.lut' % (odt_name, input_space))] + bake_LUT = Process(description='bake a LUT', + cmd='ociobakelut', + args=(args + hargs)) + bake_LUT.execute() + + +def create_config_dir(config_directory, bake_secondary_LUTs): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + dirs = [config_directory, os.path.join(config_directory, 'luts')] + if bake_secondary_LUTs: + dirs.extend([os.path.join(config_directory, 'baked'), + os.path.join(config_directory, 'baked', 'flame'), + os.path.join(config_directory, 'baked', 'photoshop'), + os.path.join(config_directory, 'baked', 'houdini'), + os.path.join(config_directory, 'baked', 'lustre'), + os.path.join(config_directory, 'baked', 'maya')]) for d in dirs: - if not os.path.exists(d): - os.mkdir(d) + not os.path.exists(d) and os.mkdir(d) -def getTransformInfo(ctlTransform): - fp = open(ctlTransform, 'rb') +def get_transform_info(ctl_transform): + """ + Object description. - # Read lines - lines = fp.readlines() + Parameters + ---------- + parameter : type + Parameter description. - # Grab transform ID and User Name - transformID = lines[1][3:].split('<')[1].split('>')[1].lstrip().rstrip() - # print(transformID) - transformUserName = '-'.join( - lines[2][3:].split('<')[1].split('>')[1].split('-')[ - 1:]).lstrip().rstrip() - transformUserNamePrefix = \ - lines[2][3:].split('<')[1].split('>')[1].split('-')[ - 0].lstrip().rstrip() - # print(transformUserName) - fp.close() + Returns + ------- + type + Return value description. + """ - return transformID, transformUserName, transformUserNamePrefix + with open(ctl_transform, 'rb') as fp: + lines = fp.readlines() + # Retrieving the *transform ID* and *User Name*. + transform_id = lines[1][3:].split('<')[1].split('>')[1].strip() + transform_user_name = '-'.join( + lines[2][3:].split('<')[1].split('>')[1].split('-')[1:]).strip() + transform_user_name_prefix = ( + lines[2][3:].split('<')[1].split('>')[1].split('-')[0].strip()) -# For versions after WGR9 -def getODTInfo(acesCTLReleaseDir): - # Credit to Alex Fry for the original approach here - odtDir = os.path.join(acesCTLReleaseDir, "odt") - allodt = [] - for dirName, subdirList, fileList in os.walk(odtDir): - for fname in fileList: - allodt.append((os.path.join(dirName, fname))) + return transform_id, transform_user_name, transform_user_name_prefix + + +def get_ODT_info(aces_CTL_directory): + """ + Object description. + + For versions after WGR9. - odtCTLs = [x for x in allodt if - ("InvODT" not in x) and (os.path.split(x)[-1][0] != '.')] + Parameters + ---------- + parameter : type + Parameter description. - # print odtCTLs + Returns + ------- + type + Return value description. + """ + + # 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') + all_odt = [] + for dir_name, subdir_list, file_list in os.walk(odt_dir): + for fname in file_list: + all_odt.append((os.path.join(dir_name, fname))) + + odt_CTLs = [x for x in all_odt if + ('InvODT' not in x) and (os.path.split(x)[-1][0] != '.')] odts = {} - for odtCTL in odtCTLs: - odtTokens = os.path.split(odtCTL) - # print(odtTokens) - - # Handle nested directories - odtPathTokens = os.path.split(odtTokens[-2]) - odtDir = odtPathTokens[-1] - while odtPathTokens[-2][-3:] != 'odt': - odtPathTokens = os.path.split(odtPathTokens[-2]) - odtDir = os.path.join(odtPathTokens[-1], odtDir) - - # Build full name - # print("odtDir : %s" % odtDir) - transformCTL = odtTokens[-1] - # print(transformCTL) - odtName = string.join(transformCTL.split('.')[1:-1], '.') - # print(odtName) - - # Find id, user name and user name prefix - (transformID, transformUserName, - transformUserNamePrefix) = getTransformInfo( - "%s/odt/%s/%s" % (acesCTLReleaseDir, odtDir, transformCTL)) - - # Find inverse - transformCTLInverse = "InvODT.%s.ctl" % odtName + for odt_CTL in odt_CTLs: + odt_tokens = os.path.split(odt_CTL) + + # Handling nested directories. + odt_path_tokens = os.path.split(odt_tokens[-2]) + odt_dir = odt_path_tokens[-1] + while odt_path_tokens[-2][-3:] != 'odt': + odt_path_tokens = os.path.split(odt_path_tokens[-2]) + odt_dir = os.path.join(odt_path_tokens[-1], odt_dir) + + # Building full name, + transform_CTL = odt_tokens[-1] + odt_name = string.join(transform_CTL.split('.')[1:-1], '.') + + # Finding id, user name and user name prefix. + (transform_ID, + transform_user_name, + transform_user_name_prefix) = get_transform_info( + os.path.join(aces_CTL_directory, 'odt', odt_dir, transform_CTL)) + + # Finding inverse. + transform_CTL_inverse = 'InvODT.%s.ctl' % odt_name if not os.path.exists( - os.path.join(odtTokens[-2], transformCTLInverse)): - transformCTLInverse = None - # print(transformCTLInverse) + os.path.join(odt_tokens[-2], transform_CTL_inverse)): + transform_CTL_inverse = None # Add to list of ODTs - odts[odtName] = {} - odts[odtName]['transformCTL'] = os.path.join(odtDir, transformCTL) - if transformCTLInverse != None: - odts[odtName]['transformCTLInverse'] = os.path.join( - odtDir, transformCTLInverse) - - odts[odtName]['transformID'] = transformID - odts[odtName]['transformUserNamePrefix'] = transformUserNamePrefix - odts[odtName]['transformUserName'] = transformUserName - - print("ODT : %s" % odtName) - print("\tTransform ID : %s" % transformID) - print("\tTransform User Name Prefix : %s" % transformUserNamePrefix) - print("\tTransform User Name : %s" % transformUserName) - print("\tForward ctl : %s" % ( - odts[odtName]['transformCTL'])) - if 'transformCTLInverse' in odts[odtName]: - print("\tInverse ctl : %s" % ( - odts[odtName]['transformCTLInverse'])) + odts[odt_name] = {} + odts[odt_name]['transformCTL'] = os.path.join(odt_dir, transform_CTL) + if transform_CTL_inverse is not None: + odts[odt_name]['transformCTLInverse'] = os.path.join( + odt_dir, transform_CTL_inverse) + + odts[odt_name]['transformID'] = transform_ID + odts[odt_name]['transformUserNamePrefix'] = transform_user_name_prefix + odts[odt_name]['transformUserName'] = transform_user_name + + forward_CTL = odts[odt_name]['transformCTL'] + + print('ODT : %s' % odt_name) + 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('\tForward ctl : %s' % forward_CTL) + if 'transformCTLInverse' in odts[odt_name]: + inverse_CTL = odts[odt_name]['transformCTLInverse'] + print('\tInverse ctl : %s' % inverse_CTL) else: - print("\tInverse ctl : %s" % "None") + print('\tInverse ctl : %s' % 'None') - print("\n") + print('\n') return odts -# For versions after WGR9 -def getLMTInfo(acesCTLReleaseDir): - # Credit to Alex Fry for the original approach here - lmtDir = os.path.join(acesCTLReleaseDir, "lmt") - alllmt = [] - for dirName, subdirList, fileList in os.walk(lmtDir): - for fname in fileList: - alllmt.append((os.path.join(dirName, fname))) +def get_LMT_info(aces_CTL_directory): + """ + Object description. - lmtCTLs = [x for x in alllmt if - ("InvLMT" not in x) and ("README" not in x) and ( - os.path.split(x)[-1][0] != '.')] + For versions after WGR9. - # print lmtCTLs + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + # TODO: Investigate refactoring with previous definition. + + # Credit to Alex Fry for the original approach here + 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: + all_lmt.append((os.path.join(dir_name, fname))) + + lmt_CTLs = [x for x in all_lmt if + ('InvLMT' not in x) and ('README' not in x) and ( + os.path.split(x)[-1][0] != '.')] lmts = {} - for lmtCTL in lmtCTLs: - lmtTokens = os.path.split(lmtCTL) - # print(lmtTokens) - - # Handle nested directories - lmtPathTokens = os.path.split(lmtTokens[-2]) - lmtDir = lmtPathTokens[-1] - while lmtPathTokens[-2][-3:] != 'ctl': - lmtPathTokens = os.path.split(lmtPathTokens[-2]) - lmtDir = os.path.join(lmtPathTokens[-1], lmtDir) - - # Build full name - # print("lmtDir : %s" % lmtDir) - transformCTL = lmtTokens[-1] - # print(transformCTL) - lmtName = string.join(transformCTL.split('.')[1:-1], '.') - # print(lmtName) - - # Find id, user name and user name prefix - (transformID, transformUserName, - transformUserNamePrefix) = getTransformInfo( - "%s/%s/%s" % (acesCTLReleaseDir, lmtDir, transformCTL)) - - # Find inverse - transformCTLInverse = "InvLMT.%s.ctl" % lmtName + for lmt_CTL in lmt_CTLs: + lmt_tokens = os.path.split(lmt_CTL) + + # Handlimg nested directories. + lmt_path_tokens = os.path.split(lmt_tokens[-2]) + lmt_dir = lmt_path_tokens[-1] + while lmt_path_tokens[-2][-3:] != 'ctl': + lmt_path_tokens = os.path.split(lmt_path_tokens[-2]) + lmt_dir = os.path.join(lmt_path_tokens[-1], lmt_dir) + + # Building full name. + transform_CTL = lmt_tokens[-1] + lmt_name = string.join(transform_CTL.split('.')[1:-1], '.') + + # Finding id, user name and user name prefix. + (transform_ID, + transform_user_name, + transform_user_name_prefix) = get_transform_info( + os.path.join(aces_CTL_directory, lmt_dir, transform_CTL)) + + # Finding inverse. + transform_CTL_inverse = 'InvLMT.%s.ctl' % lmt_name if not os.path.exists( - os.path.join(lmtTokens[-2], transformCTLInverse)): - transformCTLInverse = None - # print(transformCTLInverse) - - # Add to list of LMTs - lmts[lmtName] = {} - lmts[lmtName]['transformCTL'] = os.path.join(lmtDir, transformCTL) - if transformCTLInverse != None: - # TODO: Check unresolved *odtName* referemce. - lmts[odtName]['transformCTLInverse'] = os.path.join( - lmtDir, transformCTLInverse) - - lmts[lmtName]['transformID'] = transformID - lmts[lmtName]['transformUserNamePrefix'] = transformUserNamePrefix - lmts[lmtName]['transformUserName'] = transformUserName - - print("LMT : %s" % lmtName) - print("\tTransform ID : %s" % transformID) - print("\tTransform User Name Prefix : %s" % transformUserNamePrefix) - print("\tTransform User Name : %s" % transformUserName) - print("\t Forward ctl : %s" % lmts[lmtName]['transformCTL']) - if 'transformCTLInverse' in lmts[lmtName]: - print("\t Inverse ctl : %s" % ( - lmts[lmtName]['transformCTLInverse'])) + os.path.join(lmt_tokens[-2], transform_CTL_inverse)): + transform_CTL_inverse = None + + lmts[lmt_name] = {} + lmts[lmt_name]['transformCTL'] = os.path.join(lmt_dir, transform_CTL) + if transform_CTL_inverse is not None: + lmts[lmt_name]['transformCTLInverse'] = os.path.join( + lmt_dir, transform_CTL_inverse) + + lmts[lmt_name]['transformID'] = transform_ID + lmts[lmt_name]['transformUserNamePrefix'] = transform_user_name_prefix + lmts[lmt_name]['transformUserName'] = transform_user_name + + forward_CTL = lmts[lmt_name]['transformCTL'] + + print('LMT : %s' % lmt_name) + 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('\t Forward ctl : %s' % forward_CTL) + if 'transformCTLInverse' in lmts[lmt_name]: + inverse_CTL = lmts[lmt_name]['transformCTLInverse'] + print('\t Inverse ctl : %s' % inverse_CTL) else: - print("\t Inverse ctl : %s" % "None") + print('\t Inverse ctl : %s' % 'None') - print("\n") + print('\n') return lmts -# -# Create the ACES config -# -def createACESConfig(acesCTLReleaseDir, - configDir, - lutResolution1d=4096, - lutResolution3d=64, - bakeSecondaryLUTs=True, - cleanup=True): - # Get ODT names and CTL paths - odtInfo = getODTInfo(acesCTLReleaseDir) - - # Get ODT names and CTL paths - lmtInfo = getLMTInfo(acesCTLReleaseDir) - - # Create config dir - createConfigDir(configDir, bakeSecondaryLUTs) - - # Generate config data and LUTs for different transforms - lutDir = "%s/luts" % configDir - shaperName = 'Output Shaper' - configData = generateLUTs(odtInfo, - lmtInfo, - shaperName, - acesCTLReleaseDir, - lutDir, - lutResolution1d, - lutResolution3d, - cleanup) - - # Create the config using the generated LUTs - print("Creating generic config") - config = createConfig(configData) - print("\n\n\n") - - # Write the config to disk - writeConfig(config, "%s/config.ocio" % configDir) - - # Create a config that will work well with Nuke using the previously - # generated LUTs. - print("Creating Nuke-specific config") - nuke_config = createConfig(configData, nuke=True) - print("\n\n\n") - - # Write the config to disk - writeConfig(nuke_config, "%s/nuke_config.ocio" % configDir) - - # Bake secondary LUTs using the config - if bakeSecondaryLUTs: - generateBakedLUTs(odtInfo, - shaperName, - "%s/baked" % configDir, - "%s/config.ocio" % configDir, - lutResolution1d, - lutResolution3d, - lutResolution1d) +def create_ACES_config(aces_CTL_directory, + config_directory, + lut_resolution_1d=4096, + lut_resolution_3d=64, + bake_secondary_LUTs=True, + cleanup=True): + """ + Creates the ACES configuration. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + + odt_info = get_ODT_info(aces_CTL_directory) + lmt_info = get_LMT_info(aces_CTL_directory) + + create_config_dir(config_directory, bake_secondary_LUTs) + + lut_directory = os.path.join(config_directory, 'luts') + shaper_name = 'Output Shaper' + config_data = generate_LUTs(odt_info, + lmt_info, + shaper_name, + aces_CTL_directory, + lut_directory, + lut_resolution_1d, + lut_resolution_3d, + cleanup) + + print('Creating "generic" config') + config = create_config(config_data) + print('\n\n\n') + + write_config(config, + os.path.join(config_directory, 'config.ocio')) + + print('Creating "Nuke" config') + nuke_config = create_config(config_data, nuke=True) + print('\n\n\n') + + write_config(nuke_config, + os.path.join(config_directory, 'nuke_config.ocio')) + + if bake_secondary_LUTs: + generate_baked_LUTs(odt_info, + shaper_name, + os.path.join(config_directory, 'baked'), + os.path.join(config_directory, 'config.ocio'), + lut_resolution_1d, + lut_resolution_3d, + lut_resolution_1d) return True -# -# Main -# def main(): + """ + Object description. + + Parameters + ---------- + parameter : type + Parameter description. + + Returns + ------- + type + Return value description. + """ + import optparse p = optparse.OptionParser(description='An OCIO config generation script', @@ -1602,53 +1704,50 @@ def main(): version='createACESConfig 0.1', usage='%prog [options]') p.add_option('--acesCTLDir', '-a', default=os.environ.get( - 'ACES_OCIO_CTL_DIRECTORY', None)) + ACES_OCIO_CTL_DIRECTORY_ENVIRON, None)) p.add_option('--configDir', '-c', default=os.environ.get( - 'ACES_OCIO_CONFIGURATION_DIRECTORY', None)) + ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON, None)) p.add_option('--lutResolution1d', default=4096) p.add_option('--lutResolution3d', default=64) - p.add_option('--dontBakeSecondaryLUTs', action="store_true") - p.add_option('--keepTempImages', action="store_true") + p.add_option('--dontBakeSecondaryLUTs', action='store_true') + p.add_option('--keepTempImages', action='store_true') options, arguments = p.parse_args() - # - # Get options - # - acesCTLDir = options.acesCTLDir - configDir = options.configDir - lutResolution1d = int(options.lutResolution1d) - lutResolution3d = int(options.lutResolution3d) - bakeSecondaryLUTs = not (options.dontBakeSecondaryLUTs) - cleanupTempImages = not (options.keepTempImages) + aces_CTL_directory = options.acesCTLDir + config_directory = options.configDir + lut_resolution_1d = int(options.lutResolution1d) + lut_resolution_3d = int(options.lutResolution3d) + bake_secondary_LUTs = not options.dontBakeSecondaryLUTs + cleanup_temp_images = not options.keepTempImages + # TODO: Investigate the following statements. try: - argsStart = sys.argv.index('--') + 1 - args = sys.argv[argsStart:] + args_start = sys.argv.index('--') + 1 + args = sys.argv[args_start:] except: - argsStart = len(sys.argv) + 1 + args_start = len(sys.argv) + 1 args = [] - print("command line : \n%s\n" % " ".join(sys.argv)) - - # TODO: Use assertion and mention environment variables. - if not acesCTLDir: - print("process: No ACES CTL directory specified") - return - if not configDir: - print("process: No configuration directory specified") - return - # - # Generate the configuration - # - return createACESConfig(acesCTLDir, - configDir, - lutResolution1d, - lutResolution3d, - bakeSecondaryLUTs, - cleanupTempImages) - -# main + print('command line : \n%s\n' % ' '.join(sys.argv)) + + assert aces_CTL_directory is not None, ( + 'process: No "{0}" environment variable defined or no "ACES CTL" ' + 'directory specified'.format( + ACES_OCIO_CTL_DIRECTORY_ENVIRON)) + + assert config_directory is not None, ( + 'process: No "{0}" environment variable defined or no configuration ' + 'directory specified'.format( + ACES_OCIO_CONFIGURATION_DIRECTORY_ENVIRON)) + + return create_ACES_config(aces_CTL_directory, + config_directory, + lut_resolution_1d, + lut_resolution_3d, + bake_secondary_LUTs, + cleanup_temp_images) + if __name__ == '__main__': main()