diff options
Diffstat (limited to 'src/mari/1.4v1/ocio.py')
-rwxr-xr-x | src/mari/1.4v1/ocio.py | 789 |
1 files changed, 789 insertions, 0 deletions
diff --git a/src/mari/1.4v1/ocio.py b/src/mari/1.4v1/ocio.py new file mode 100755 index 0000000..4f0f61e --- /dev/null +++ b/src/mari/1.4v1/ocio.py @@ -0,0 +1,789 @@ +#------------------------------------------------------------------------------- +# OpenColorIO (color management) related Mari scripts +# coding: utf-8 +# Copyright (c) 2011 The Foundry Visionmongers Ltd. All Rights Reserved. +#------------------------------------------------------------------------------- + +import mari, time, PythonQt, os, math + +############################################################################################## + +# Enable to output extended debugging messages. +VERBOSE_ENABLED = False + +# Message type identifiers. +class MessageType: + DEBUG = 1 + INFO = 2 + WARNING = 3 + ERROR = 4 + +def printMessage(type, message): + if type == MessageType.DEBUG: + if VERBOSE_ENABLED: + mari.app.log('[ OpenColorIO ] %s' % message) + elif type == MessageType.INFO: + mari.app.log('[ OpenColorIO ] %s' % message) + elif type == MessageType.WARNING: + mari.app.log('[ OpenColorIO ] [ WARNING ] %s' % message) + elif type == MessageType.ERROR: + mari.app.log('[ OpenColorIO ] [ ERROR ] %s' % message) + +############################################################################################## + +def configFileFilter(): + return 'OpenColorIO Configuration (*.ocio)' + +#--------------------------------------------------------------------------------------------- + +def lutFileFilter(): + result = 'All LUT Files (*.3dl *.ccc *.cc *.csp *.cub *.cube *.hdl *.m3d *.mga *.spi1d *.spi3d *.spimtx *.vf);;' + result += 'Autodesk LUT (*.3dl);;' + result += 'ASC CDL Color Correction Collection LUT (*.ccc);;' + result += 'ASC CDL Color Correction LUT (*.cc);;' + result += 'Cinespace LUT (*.csp);;' + result += 'Truelight LUT (*.cub);;' + result += 'Iridas LUT (*.cube);;' + result += 'Houdini LUT (*.hdl);;' + result += 'Pandora LUT (*.m3d *.mga);;' + result += 'Imageworks LUT (*.spi1d *.spi3d *.spimtx);;' + result += 'Inventor LUT (*.vf)' + return result + +############################################################################################## + +# Make sure the OpenColorIO python bindings are okay. +try: + import PyOpenColorIO + printMessage(MessageType.INFO, 'Loaded Python bindings \'%s\' successfully' % PyOpenColorIO.__file__) +except ImportError, e: + PyOpenColorIO = None + printMessage(MessageType.ERROR, 'Failed to load Python bindings \'%s\'' % e) + +LUT_FILE_LIST_RESET = mari.FileList(mari.FileList.TYPE_SINGLE_FILE) +LUT_FILE_LIST_RESET.setAcceptNonExisting(True) +LUT_FILE_LIST_RESET.setFilter(lutFileFilter()) + +CONFIG_FILE_LIST_RESET = mari.FileList(mari.FileList.TYPE_SINGLE_FILE) +if mari.app.isRunning(): + CONFIG_FILE_LIST_RESET.append(mari.resources.path(mari.resources.COLOR) + '/OpenColorIO/nuke-default/config.ocio') +else: + CONFIG_FILE_LIST_RESET.append('/OpenColorIO/nuke-default/config.ocio') +CONFIG_FILE_LIST_RESET.setPickedFile(CONFIG_FILE_LIST_RESET.at(0)) +CONFIG_FILE_LIST_RESET.setAcceptNonExisting(True) +CONFIG_FILE_LIST_RESET.setFilter(configFileFilter()) + +SQRT_TWO = math.sqrt(2.0) +LUT_SIZE_TYPES = ['Small', 'Medium', 'Large'] +LUT_SIZE_VALUES = {'Small': 16, + 'Medium': 32, + 'Large': 64} +LUT_SIZE_RESET = LUT_SIZE_TYPES[1] +ENABLED_RESET = True +PROFILE_RESET = 'Color Space' +LUT_EXTRAPOLATE_RESET = True +COLOR_SPACE_RESET = 'sRGB' +DISPLAY_RESET = 'default' +VIEW_RESET = 'sRGB' +SWIZZLE_TYPES = ['Luminance', 'RGB', 'R', 'G', 'B', 'A'] +SWIZZLE_VALUES = {'Luminance': ( True, True, True, False), + 'RGB': ( True, True, True, True), + 'R': ( True, False, False, False), + 'G': (False, True, False, False), + 'B': (False, False, True, False), + 'A': (False, False, False, True)} +SWIZZLE_RESET = SWIZZLE_TYPES[1] +FSTOP_STEP_SIZE = 0.5 +FSTOP_CENTER_MIN = 1.0 +FSTOP_CENTER_MAX = 64.0 +FSTOP_CENTER_STEP_SIZE = 0.001 +FSTOP_CENTER_RESET = 8.0 +EXPOSURE_MIN = -6.0 +EXPOSURE_MAX = +6.0 +EXPOSURE_DELTA = EXPOSURE_MAX - EXPOSURE_MIN +EXPOSURE_STEP_SIZE = 0.1 +GAIN_RESET = 1.0 +GAIN_MIN = 2.0 ** EXPOSURE_MIN +GAIN_MAX = 2.0 ** EXPOSURE_MAX +GAIN_STEP_SIZE = 0.000001 +GAIN_PRECISION = 6 +GAMMA_RESET = 1.0 +GAMMA_MIN = 0.0 +GAMMA_MAX = 4.0 +GAMMA_STEP_SIZE = 0.01 +GAMMA_PRECISION = 2 + +enabled_default = ENABLED_RESET +profile_default = PROFILE_RESET +lut_file_list_default = mari.FileList(LUT_FILE_LIST_RESET) +lut_extrapolate_default = LUT_EXTRAPOLATE_RESET +config_file_list_default = mari.FileList(CONFIG_FILE_LIST_RESET) +color_space_default = COLOR_SPACE_RESET +display_default = DISPLAY_RESET +view_default = VIEW_RESET +swizzle_default = SWIZZLE_RESET +gain_default = GAIN_RESET +gamma_default = GAMMA_RESET +lut_size = LUT_SIZE_RESET +fstop_center = FSTOP_CENTER_RESET + +config_default = None + +lut_size_functions = [] +fstop_center_functions = [] + +############################################################################################## + +def registerLUTSizeChanged(function): + global lut_size_functions + lut_size_functions.append(function) + +#--------------------------------------------------------------------------------------------- + +def registerFStopCenterChanged(function): + global fstop_center_functions + fstop_center_functions.append(function) + +#--------------------------------------------------------------------------------------------- + +def _enabledDefaultChanged(): + global enabled_default + enabled_default = mari.prefs.get('/Color/Color Management Defaults/colorEnabledDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _profileDefaultChanged(): + global profile_default + profile_default = mari.prefs.get('/Color/Color Management Defaults/colorProfileDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _postFilterCollectionAdded(filter_collection): + mari.prefs.setItemList('/Color/Color Management Defaults/colorProfileDefault', mari.gl_render.postFilterCollectionNames()) + +#--------------------------------------------------------------------------------------------- + +def _postFilterCollectionRemoved(name): + collection_names = mari.gl_render.postFilterCollectionNames() + mari.prefs.setItemList('/Color/Color Management Defaults/colorProfileDefault', collection_names) + + global PROFILE_RESET + if name == PROFILE_RESET: + PROFILE_RESET = collection_names[0] + mari.prefs.setDefault('/Color/Color Management Defaults/colorProfileDefault', PROFILE_RESET) + + global profile_default + if name == profile_default: + profile_default = PROFILE_RESET + mari.prefs.set('/Color/Color Management Defaults/colorProfileDefault', profile_default) + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _lutPathDefaultChanged(): + global lut_file_list_default + lut_file_list_default = mari.FileList(mari.prefs.get('/Color/LUT Defaults/lutPathDefault')) + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _lutExtrapolateDefaultChanged(): + global lut_extrapolate_default + lut_extrapolate_default = mari.prefs.get('/Color/LUT Defaults/lutExtrapolateDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _configPathDefaultChanged(): + global config_file_list_default + + # Only replace the existing configuration file if the new one is valid! + config_file_list = mari.FileList(mari.prefs.get('/Color/Display Defaults/displayConfigPathDefault')) + + if not config_file_list.isEmpty(): + config = loadConfig(config_file_list.at(0), True) + if config is not None: + config_file_list_default = config_file_list + + global config_default + config_default = config + + _updateColorSpaceDefault() + _updateDisplayDefault() + _updateViewDefault() + + _savePreferences() + + else: + # Put back the existing configuration file that works... + mari.prefs.set('/Color/Display Defaults/displayConfigPathDefault', config_file_list_default) + else: + # Put back the existing configuration file that works... + mari.prefs.set('/Color/Display Defaults/displayConfigPathDefault', config_file_list_default) + +#--------------------------------------------------------------------------------------------- + +def _colorSpaceDefaultChanged(): + global color_space_default + color_space_default = mari.prefs.get('/Color/Display Defaults/displayColorSpaceDefault') + _updateDisplayDefault() + _updateViewDefault() + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _displayDefaultChanged(): + global display_default + display_default = mari.prefs.get('/Color/Display Defaults/displayDisplayDefault') + _updateViewDefault() + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _viewDefaultChanged(): + global view_default + view_default = mari.prefs.get('/Color/Display Defaults/displayViewDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _swizzleDefaultChanged(): + global swizzle_default + swizzle_default = mari.prefs.get('/Color/Display Defaults/displaySwizzleDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _gainDefaultChanged(): + global gain_default + gain_default = mari.prefs.get('/Color/Display Defaults/displayGainDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _gammaDefaultChanged(): + global gamma_default + gamma_default = mari.prefs.get('/Color/Display Defaults/displayGammaDefault') + _savePreferences() + +#--------------------------------------------------------------------------------------------- + +def _lutSizeChanged(): + global lut_size + global lut_size_functions + lut_size = mari.prefs.get('/Color/Display General/displayLutSize') + _savePreferences() + for function in lut_size_functions: + function() + +#--------------------------------------------------------------------------------------------- + +def _fstopCenterChanged(): + global fstop_center + global fstop_center_functions + fstop_center = mari.prefs.get('/Color/Display General/displayFStopCenter') + _savePreferences() + for function in fstop_center_functions: + function() + +#--------------------------------------------------------------------------------------------- + +def _registerPreferences(): + global enabled_default + mari.prefs.set('/Color/Color Management Defaults/colorEnabledDefault', enabled_default) + mari.prefs.setChangedScript('/Color/Color Management Defaults/colorEnabledDefault', 'mari.utils.ocio._enabledDefaultChanged()') + mari.prefs.setDisplayName('/Color/Color Management Defaults/colorEnabledDefault', 'Enabled') + mari.prefs.setDefault('/Color/Color Management Defaults/colorEnabledDefault', ENABLED_RESET) + + global profile_default + mari.prefs.set('/Color/Color Management Defaults/colorProfileDefault', profile_default) + mari.prefs.setChangedScript('/Color/Color Management Defaults/colorProfileDefault', 'mari.utils.ocio._profileDefaultChanged()') + mari.prefs.setDisplayName('/Color/Color Management Defaults/colorProfileDefault', 'Color Profile') + mari.prefs.setDefault('/Color/Color Management Defaults/colorProfileDefault', PROFILE_RESET) + mari.prefs.setItemList('/Color/Color Management Defaults/colorProfileDefault', mari.gl_render.postFilterCollectionNames()) + + global lut_file_list_default + if not lut_file_list_default.isEmpty() and not os.path.isfile(lut_file_list_default.at(0)): + message = 'LUT file \'%s\' does not exist' % lut_file_list_default.at(0) + printMessage(MessageType.ERROR, '%s' % message) + lut_file_list_default = mari.FileList(LUT_FILE_LIST_RESET) + + mari.prefs.set('/Color/LUT Defaults/lutPathDefault', lut_file_list_default) + mari.prefs.setChangedScript('/Color/LUT Defaults/lutPathDefault', 'mari.utils.ocio._lutPathDefaultChanged()') + mari.prefs.setDisplayName('/Color/LUT Defaults/lutPathDefault', 'File') + mari.prefs.setDefault('/Color/LUT Defaults/lutPathDefault', LUT_FILE_LIST_RESET) + + global lut_extrapolate_default + mari.prefs.set('/Color/LUT Defaults/lutExtrapolateDefault', lut_extrapolate_default) + mari.prefs.setChangedScript('/Color/LUT Defaults/lutExtrapolateDefault', 'mari.utils.ocio._lutExtrapolateDefaultChanged()') + mari.prefs.setDisplayName('/Color/LUT Defaults/lutExtrapolateDefault', 'Extrapolate') + mari.prefs.setDefault('/Color/LUT Defaults/lutExtrapolateDefault', LUT_EXTRAPOLATE_RESET) + + global config_file_list_default + global config_default + if not config_file_list_default.isEmpty(): + config = loadConfig(config_file_list_default.at(0), False) + if config is not None: + config_default = config + else: + config_file_list_default = mari.FileList(CONFIG_FILE_LIST_RESET) + else: + config_file_list_default = mari.FileList(CONFIG_FILE_LIST_RESET) + + mari.prefs.set('/Color/Display Defaults/displayConfigPathDefault', config_file_list_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displayConfigPathDefault', 'mari.utils.ocio._configPathDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displayConfigPathDefault', 'Configuration File') + mari.prefs.setDefault('/Color/Display Defaults/displayConfigPathDefault', CONFIG_FILE_LIST_RESET) + + color_spaces = [color_space.getName() for color_space in config_default.getColorSpaces()] + + color_space_reset = COLOR_SPACE_RESET + if color_spaces.count(color_space_reset) == 0: + color_space_reset = color_spaces[0] + + global color_space_default + if color_spaces.count(color_space_default) == 0: + color_space_default = color_space_reset + + mari.prefs.set('/Color/Display Defaults/displayColorSpaceDefault', color_space_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displayColorSpaceDefault', 'mari.utils.ocio._colorSpaceDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displayColorSpaceDefault', 'Input Color Space') + mari.prefs.setDefault('/Color/Display Defaults/displayColorSpaceDefault', color_space_reset) + mari.prefs.setItemList('/Color/Display Defaults/displayColorSpaceDefault', color_spaces) + + displays = config_default.getDisplays() + + display_reset = DISPLAY_RESET + if displays.count(display_reset) == 0: + display_reset = config_default.getDefaultDisplay() + + global display_default + if displays.count(display_default) == 0: + display_default = display_reset + + mari.prefs.set('/Color/Display Defaults/displayDisplayDefault', display_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displayDisplayDefault', 'mari.utils.ocio._displayDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displayDisplayDefault', 'Display') + mari.prefs.setDefault('/Color/Display Defaults/displayDisplayDefault', display_reset) + mari.prefs.setItemList('/Color/Display Defaults/displayDisplayDefault', displays) + + views = config_default.getViews(display_default) + + view_reset = VIEW_RESET + if views.count(view_reset) == 0: + view_reset = config_default.getDefaultView(display_default) + + global view_default + if views.count(view_default) == 0: + view_default = view_reset + + mari.prefs.set('/Color/Display Defaults/displayViewDefault', view_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displayViewDefault', 'mari.utils.ocio._viewDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displayViewDefault', 'View') + mari.prefs.setDefault('/Color/Display Defaults/displayViewDefault', view_reset) + mari.prefs.setItemList('/Color/Display Defaults/displayViewDefault', views) + + global swizzle_default + if SWIZZLE_TYPES.count(swizzle_default) == 0: + swizzle_default = SWIZZLE_RESET + + mari.prefs.set('/Color/Display Defaults/displaySwizzleDefault', swizzle_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displaySwizzleDefault', 'mari.utils.ocio._swizzleDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displaySwizzleDefault', 'Component') + mari.prefs.setDefault('/Color/Display Defaults/displaySwizzleDefault', SWIZZLE_RESET) + mari.prefs.setItemList('/Color/Display Defaults/displaySwizzleDefault', SWIZZLE_TYPES) + + global gain_default + mari.prefs.set('/Color/Display Defaults/displayGainDefault', gain_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displayGainDefault', 'mari.utils.ocio._gainDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displayGainDefault', 'Gain') + mari.prefs.setDefault('/Color/Display Defaults/displayGainDefault', GAIN_RESET) + mari.prefs.setRange('/Color/Display Defaults/displayGainDefault', GAIN_MIN, GAIN_MAX) + mari.prefs.setStep('/Color/Display Defaults/displayGainDefault', GAIN_STEP_SIZE) + + global gamma_default + mari.prefs.set('/Color/Display Defaults/displayGammaDefault', gamma_default) + mari.prefs.setChangedScript('/Color/Display Defaults/displayGammaDefault', 'mari.utils.ocio._gammaDefaultChanged()') + mari.prefs.setDisplayName('/Color/Display Defaults/displayGammaDefault', 'Gamma') + mari.prefs.setDefault('/Color/Display Defaults/displayGammaDefault', GAMMA_RESET) + mari.prefs.setRange('/Color/Display Defaults/displayGammaDefault', GAMMA_MIN, GAMMA_MAX) + mari.prefs.setStep('/Color/Display Defaults/displayGammaDefault', GAMMA_STEP_SIZE) + + global lut_size + mari.prefs.set('/Color/Display General/displayLutSize', lut_size) + mari.prefs.setChangedScript('/Color/Display General/displayLutSize', 'mari.utils.ocio._lutSizeChanged()') + mari.prefs.setDisplayName('/Color/Display General/displayLutSize', 'LUT Size') + mari.prefs.setDefault('/Color/Display General/displayLutSize', LUT_SIZE_RESET) + mari.prefs.setItemList('/Color/Display General/displayLutSize', LUT_SIZE_TYPES) + + global fstop_center + mari.prefs.set('/Color/Display General/displayFStopCenter', fstop_center) + mari.prefs.setChangedScript('/Color/Display General/displayFStopCenter', 'mari.utils.ocio._fstopCenterChanged()') + mari.prefs.setDisplayName('/Color/Display General/displayFStopCenter', 'Center F-Stop') + mari.prefs.setDefault('/Color/Display General/displayFStopCenter', FSTOP_CENTER_RESET) + mari.prefs.setRange('/Color/Display General/displayFStopCenter', FSTOP_CENTER_MIN, FSTOP_CENTER_MAX) + mari.prefs.setStep('/Color/Display General/displayFStopCenter', FSTOP_CENTER_STEP_SIZE) + + # Attach ourselves to the appropriate project signals so we can update widgets. + PythonQt.QtCore.QObject.connect(mari.gl_render.postFilterCollectionAdded.__self__, + mari.gl_render.postFilterCollectionAdded.__name__, + _postFilterCollectionAdded) + PythonQt.QtCore.QObject.connect(mari.gl_render.postFilterCollectionRemoved.__self__, + mari.gl_render.postFilterCollectionRemoved.__name__, + _postFilterCollectionRemoved) + +#--------------------------------------------------------------------------------------------- + +def _updateColorSpaceDefault(): + global config_default + global color_space_default + + color_spaces = [color_space.getName() for color_space in config_default.getColorSpaces()] + + color_space_reset = COLOR_SPACE_RESET + if color_spaces.count(color_space_reset) == 0: + color_space_reset = color_spaces[0] + + if color_spaces.count(color_space_default) == 0: + color_space_default = color_space_reset + + mari.prefs.setItemList('/Color/Display Defaults/displayColorSpaceDefault', color_spaces) + mari.prefs.set('/Color/Display Defaults/displayColorSpaceDefault', color_space_default) + mari.prefs.setDefault('/Color/Display Defaults/displayColorSpaceDefault', color_space_reset) + + +#--------------------------------------------------------------------------------------------- + +def _updateDisplayDefault(): + global config_default + global display_default + + displays = config_default.getDisplays() + + display_reset = DISPLAY_RESET + if displays.count(display_reset) == 0: + display_reset = config_default.getDefaultDisplay() + + if displays.count(display_default) == 0: + display_default = display_reset + + mari.prefs.setItemList('/Color/Display Defaults/displayDisplayDefault', displays) + mari.prefs.set('/Color/Display Defaults/displayDisplayDefault', display_default) + mari.prefs.setDefault('/Color/Display Defaults/displayDisplayDefault', display_reset) + +#--------------------------------------------------------------------------------------------- + +def _updateViewDefault(): + global config_default + global display_default + global view_default + + views = config_default.getViews(display_default) + + view_reset = VIEW_RESET + if views.count(view_reset) == 0: + view_reset = config_default.getDefaultView(display_default) + + if views.count(view_default) == 0: + view_default = view_reset + + mari.prefs.setItemList('/Color/Display Defaults/displayViewDefault', views) + mari.prefs.set('/Color/Display Defaults/displayViewDefault', view_default) + mari.prefs.setDefault('/Color/Display Defaults/displayViewDefault', view_reset) + +#--------------------------------------------------------------------------------------------- + +def _loadPreferences(): + settings = mari.Settings() + settings.beginGroup('OpenColorIO') + + try: + global enabled_default + global profile_default + global lut_file_list_default + global lut_extrapolate_default + global config_file_list_default + global color_space_default + global display_default + global view_default + global swizzle_default + global gain_default + global gamma_default + global lut_size + global fstop_center + + enabled_default = False if int(settings.value('enabledDefault', ENABLED_RESET)) == 0 else True + profile_default = str(settings.value('profileDefault', PROFILE_RESET)) + lut_path = buildLoadPath(str(settings.value('lutPathDefault', '' if LUT_FILE_LIST_RESET.isEmpty() else LUT_FILE_LIST_RESET.at(0)))) + lut_extrapolate_default = False if int(settings.value('lutExtrapolateDefault', LUT_EXTRAPOLATE_RESET)) == 0 else True + config_path = buildLoadPath(str(settings.value('configPathDefault', '' if CONFIG_FILE_LIST_RESET.isEmpty() else CONFIG_FILE_LIST_RESET.at(0)))) + color_space_default = str(settings.value('colorSpaceDefault', COLOR_SPACE_RESET)) + display_default = str(settings.value('displayDefault', DISPLAY_RESET)) + view_default = str(settings.value('viewDefault', VIEW_RESET)) + swizzle_default = str(settings.value('swizzleDefault', SWIZZLE_RESET)) + gain_default = max(min(float(settings.value('gainDefault', GAIN_RESET)), GAIN_MAX), GAIN_MIN) + gamma_default = max(min(float(settings.value('gammaDefault', GAMMA_RESET)), GAMMA_MAX), GAMMA_MIN) + lut_size = str(settings.value('lutSize', LUT_SIZE_RESET)) + fstop_center = max(min(float(settings.value('fstopCenter', FSTOP_CENTER_RESET)), FSTOP_CENTER_MAX), FSTOP_CENTER_MIN) + + if os.path.isfile(lut_path): + lut_file_list_default.clear() + lut_file_list_default.append(lut_path) + lut_file_list_default.setPickedFile(lut_path) + + if os.path.isfile(config_path): + config_file_list_default.clear() + config_file_list_default.append(config_path) + config_file_list_default.setPickedFile(config_path) + + except ValueError, e: + printMessage(MessageType.ERROR, 'Failed to load preferences \'%s\'' % e) + + settings.endGroup() + + _printPreferences(MessageType.DEBUG, 'Loaded Preferences:') + +#--------------------------------------------------------------------------------------------- + +def _savePreferences(): + settings = mari.Settings() + settings.beginGroup('OpenColorIO') + + global enabled_default + global profile_default + global lut_file_list_default + global lut_extrapolate_default + global config_file_list_default + global color_space_default + global display_default + global view_default + global swizzle_default + global gain_default + global gamma_default + global lut_size + global fstop_center + + settings.setValue( 'enabledDefault', 1 if enabled_default else 0) + settings.setValue( 'profileDefault', profile_default) + settings.setValue( 'lutPathDefault', '' if lut_file_list_default.isEmpty() else buildSavePath(lut_file_list_default.at(0))) + settings.setValue('lutExtrapolateDefault', 1 if lut_extrapolate_default else 0) + settings.setValue( 'configPathDefault', '' if config_file_list_default.isEmpty() else buildSavePath(config_file_list_default.at(0))) + settings.setValue( 'colorSpaceDefault', color_space_default) + settings.setValue( 'displayDefault', display_default) + settings.setValue( 'viewDefault', view_default) + settings.setValue( 'swizzleDefault', swizzle_default) + settings.setValue( 'gainDefault', gain_default) + settings.setValue( 'gammaDefault', gamma_default) + settings.setValue( 'lutSize', lut_size) + settings.setValue( 'fstopCenter', fstop_center) + + settings.endGroup() + + _printPreferences(MessageType.DEBUG, 'Saved Preferences:') + +#--------------------------------------------------------------------------------------------- + +def _printPreferences(type, title): + global enabled_default + global profile_default + global lut_file_list_default + global lut_extrapolate_default + global config_file_list_default + global color_space_default + global display_default + global view_default + global swizzle_default + global gain_default + global fstop_center + global lut_size + global gamma_default + + printMessage(type, '==============================================================') + printMessage(type, title) + printMessage(type, '==============================================================') + printMessage(type, ' Enabled: %s' % enabled_default) + printMessage(type, ' Profile: %s' % profile_default) + printMessage(type, ' LUT Path: %s' % '' if lut_file_list_default.isEmpty() else lut_file_list_default.at(0)) + printMessage(type, ' Extrapolate: %s' % lut_extrapolate_default) + printMessage(type, ' Config Path: %s' % '' if config_file_list_default.isEmpty() else config_file_list_default.at(0)) + printMessage(type, ' Color Space: %s' % color_space_default) + printMessage(type, ' Display: %s' % display_default) + printMessage(type, ' View: %s' % view_default) + printMessage(type, ' Swizzle: %s' % swizzle_default) + printMessage(type, ' F-Stop: %f; Center: %f' % (convertGainToFStop(gain_default), fstop_center)) + printMessage(type, ' Gain: %f' % gain_default) + printMessage(type, ' Gamma: %f' % gamma_default) + printMessage(type, ' LUT Size: %s' % lut_size) + printMessage(type, '==============================================================') + +############################################################################################## + +def convertExposureToGain(exposure): + return 2.0 ** exposure + +#--------------------------------------------------------------------------------------------- + +def convertGainToExposure(gain): + return math.log(gain, 2.0) + +#--------------------------------------------------------------------------------------------- + +def convertExposureToFStop(exposure): + global fstop_center + exposure_center = math.log(fstop_center, SQRT_TWO) + return math.pow(SQRT_TWO, exposure_center - exposure) + +#--------------------------------------------------------------------------------------------- + +def convertGainToFStop(gain): + exposure = convertGainToExposure(gain) + return convertExposureToFStop(exposure) + +#--------------------------------------------------------------------------------------------- + +def buildProcessorFilter(processor, filter, filter_cache_id, texture_cache_id, extrapolate = False, force_shader_build = False): + # Create a name, using the filter's name, that can be used in uniquely naming parameters and functions. + name = filter.name(); + name = name.lower() + name = name.replace(' ', '_') + + sampler_name = 'ocio_' + name + '_lut_$ID_' + function_name = 'ocio_' + name + '_$ID_' + + global lut_size + shader_desc = { 'language': PyOpenColorIO.Constants.GPU_LANGUAGE_GLSL_1_3, + 'functionName': function_name, + 'lut3DEdgeLen': LUT_SIZE_VALUES[lut_size]} + + cache_id = processor.getGpuShaderTextCacheID(shader_desc) + if cache_id != filter_cache_id or force_shader_build: + filter_cache_id = cache_id + printMessage(MessageType.DEBUG, 'Creating new GLSL filter...') + + desc = 'uniform sampler3D ' + sampler_name + ';\n' + desc += processor.getGpuShaderText(shader_desc) + body = '' + if extrapolate: + # The following code was taken from Nuke's 'LUT3D::Extrapolate' functionality. It attempts to estimate what + # the corresponding color value would be when the incoming color value is outside the normal range of [0-1], + # such as the case with HDR images. + rcp_lut_edge_length = 1.0 / float(LUT_SIZE_VALUES[lut_size]) + + body += '{\n' + body += ' if( 1.0 < Out.r || 1.0 < Out.g || 1.0 < Out.b )\n' + body += ' {\n' + body += ' vec4 closest;\n' + body += ' closest.rgb = clamp(Out.rgb, vec3(0.0), vec3(1.0));\n' + body += ' closest.a = Out.a;\n' + body += '\n' + body += ' vec3 offset = Out.rgb - closest.rgb;\n' + body += ' float offset_distance = length(offset);\n' + body += ' offset = normalize(offset);\n' + body += '\n' + body += ' vec4 nbr_position;\n' + body += ' nbr_position.rgb = closest.rgb - %f * offset;\n' % rcp_lut_edge_length + body += ' nbr_position.a = Out.a;\n' + body += '\n' + body += ' Out = ' + function_name + '(closest, ' + sampler_name + ');\n' + body += ' Out.rgb += (Out.rgb - ' + function_name + '(nbr_position, ' + sampler_name + ').rgb) / %f * offset_distance;\n' % rcp_lut_edge_length + body += ' }\n' + body += ' else\n' + body += ' {\n' + body += ' Out = ' + function_name + '(Out, ' + sampler_name + ');\n' + body += ' }\n' + body += '}\n' + else: + body += '{ Out = ' + function_name + '(Out, ' + sampler_name + '); }\n' + + filter.setDefinitionsSnippet(desc) + filter.setBodySnippet(body) + else: + printMessage(MessageType.DEBUG, 'No GLSL filter update required') + + cache_id = processor.getGpuLut3DCacheID(shader_desc) + if cache_id != texture_cache_id: + lut = processor.getGpuLut3D(shader_desc) + + printMessage(MessageType.DEBUG, 'Updating LUT...') + + if texture_cache_id is None: + filter.setTexture3D(sampler_name, + LUT_SIZE_VALUES[lut_size], + LUT_SIZE_VALUES[lut_size], + LUT_SIZE_VALUES[lut_size], + filter.FORMAT_RGB, + lut) + else: + filter.updateTexture3D(sampler_name, lut) + + texture_cache_id = cache_id + else: + printMessage(MessageType.DEBUG, 'No LUT update required') + + return (filter_cache_id, texture_cache_id, sampler_name) + +#--------------------------------------------------------------------------------------------- + +def buildLUTFilter(config, path, filter, filter_cache_id, texture_cache_id, extrapolate, force_shader_build = False): + file_transform = PyOpenColorIO.FileTransform() + file_transform.setSrc(path) + file_transform.setInterpolation('linear') + + processor = config.getProcessor(file_transform) + + return buildProcessorFilter(processor, filter, filter_cache_id, texture_cache_id, extrapolate, force_shader_build) + +#--------------------------------------------------------------------------------------------- + +def loadConfig(path, display_message_box = True): + try: + config = PyOpenColorIO.Config.CreateFromFile(path) + return config + + except Exception, e: + message = 'Failed to load configuration file \'%s\' due to \'%s\'' % (path, e) + printMessage(MessageType.ERROR, '%s' % message) + if display_message_box and not mari.app.inTerminalMode(): + mari.utils.misc.message(message, 'Color Space', 1024, 2) + + return None + +#--------------------------------------------------------------------------------------------- + +# This converts a path into a form which can be shared among different platforms and installations. +def buildSavePath(path): + result = path.replace(mari.resources.path(mari.resources.COLOR), '$MARI_COLOR_PATH', 1) + return result + +#--------------------------------------------------------------------------------------------- + +# This converts a path saved out to disk back into a form which can used by the application. +def buildLoadPath(path): + result = path.replace('$MARI_COLOR_PATH', mari.resources.path(mari.resources.COLOR), 1) + return result + +############################################################################################## + +if mari.app.isRunning(): + if PyOpenColorIO is not None: + # Attempt to load the default configuration file... without it we can't do nothing! + config_file_lists = [config_file_list_default, CONFIG_FILE_LIST_RESET] + for config_file_list in config_file_lists: + if not config_file_list.isEmpty(): + config_default = loadConfig(config_file_list.at(0), False) + if config_default is not None: + config_file_list_default = mari.FileList(config_file_list) + break + + if config_default is not None: + _loadPreferences() + _registerPreferences() + _savePreferences() + + else: + message = 'Failed to find a working configuration file. OpenColorIO will be disabled!' + printMessage(MessageType.ERROR, message) + if not mari.app.inTerminalMode(): + mari.utils.misc.message(message, 'OpenColorIO', 1024, 3) |