def testPluginDescProps(): """ Test the 'SupportedExtensions' and 'Evaluation' properties of plugins pluginTurboJpeg and pluginImageMagick. """ # test evaluation for pluginTurboJpeg turboJpeg_plugin = tuttle.core().getImageEffectPluginCache( ).getPluginByLabel("TuttleTurboJpegReader") turboJpeg_plugin.loadAndDescribeActions() turboJpeg_desc = turboJpeg_plugin.getDescriptor() assert (turboJpeg_desc.getProperties().hasProperty( 'TuttleOfxImageEffectPropSupportedExtensions', True)) assert (turboJpeg_desc.getProperties().hasProperty( 'TuttleOfxImageEffectPropEvaluation', True)) turboJpeg_evaluation = turboJpeg_desc.getProperties().getDoubleProperty( "TuttleOfxImageEffectPropEvaluation") assert_equal(turboJpeg_evaluation, 90) # test evaluation for pluginImageMagick imageMagick_plugin = tuttle.core().getImageEffectPluginCache( ).getPluginByLabel("TuttleImageMagickReader") imageMagick_plugin.loadAndDescribeActions() imageMagick_desc = imageMagick_plugin.getDescriptor() assert (imageMagick_desc.getProperties().hasProperty( 'TuttleOfxImageEffectPropSupportedExtensions', True)) assert (imageMagick_desc.getProperties().hasProperty( 'TuttleOfxImageEffectPropEvaluation', True)) imageMagick_evaluation = imageMagick_desc.getProperties( ).getDoubleProperty("TuttleOfxImageEffectPropEvaluation") assert_equal(imageMagick_evaluation, 0)
def generateThumbnail(imgFile): from pyTuttle import tuttle tuttle.core().preload(False) tuttle.compute([ tuttle.NodeInit( "tuttle.pngreader", filename=imgFile), tuttle.NodeInit( "tuttle.resize", width=256, keepRatio=1), tuttle.NodeInit( "tuttle.pngwriter", filename=imgFile + "-thumbnail"), ])
def generateThumbnail(imgFile): from pyTuttle import tuttle tuttle.core().preload(False) tuttle.compute([ tuttle.NodeInit("tuttle.pngreader", filename=imgFile), tuttle.NodeInit("tuttle.resize", width=256, keepRatio=1), tuttle.NodeInit("tuttle.pngwriter", filename=imgFile + "-thumbnail"), ])
def configLocalPluginPath(ofxPluginPaths): tuttle.core().getPluginCache().addDirectoryToPath(globalOfxPluginPath) for ofxPluginPath in ofxPluginPaths: logging.info("ofxPluginPath:" + str(ofxPluginPath)) tuttle.core().getPluginCache().addDirectoryToPath(str(ofxPluginPath)) pluginCache = tuttle.core().getPluginCache() tuttle.core().getFormatter().setLogLevel_int(5) tuttle.core().preload(False) logging.debug('Number of Plugins:' + str(len(pluginCache.getPlugins())))
def samDoCompleter(prefix, parsed_args, **kwargs): """ Custom Completer to manage auto competion when looking for openFX nodes. @warning The autocompletion works only for TuttleOFX plugins. """ # preload OFX plugins (to have auto completion of plugins name, their parameters...) tuttle.core().preload(True) # get plugins pluginsId = tuttle.core().getImageEffectPluginCache().getPluginsByID() pluginsStr = [str(id).replace('tuttle.', '') for id in pluginsId] # check last input in command line if len(parsed_args.inputs): lastInput = parsed_args.inputs[-1] # if last input is a plugin, return its parameters if lastInput in pluginsStr: graph = tuttle.Graph() node = graph.createNode('tuttle.' + lastInput) params = node.getParams() paramsStr = [str(param.getScriptName()) for param in params] return paramsStr elif lastInput == '//': return pluginsStr else: for input in reversed(parsed_args.inputs): # if an input is a plugin, get its parameters if input in pluginsStr: graph = tuttle.Graph() node = graph.createNode('tuttle.' + input) params = node.getParams() paramsStr = [ str(param.getScriptName()) for param in params ] # if last input is one of its parameters, return its choices if lastInput in paramsStr: param = node.getParam(lastInput) if param.getProperties().hasProperty( 'OfxParamPropChoiceOption'): propChoiceOption = param.getProperties( ).fetchProperty('OfxParamPropChoiceOption') choicesStr = samUtils.getListValues( propChoiceOption) return choicesStr # else, return its parameters else: return paramsStr # else return available plugins return pluginsStr
def testSimpleProcessGraph(): graph = tuttle.Graph() n = [ tuttle.NodeInit( "tuttle.exrreader", filename="TuttleOFX-data/image/openexr/DisplayWindow/t##.exr"), tuttle.NodeInit("tuttle.invert"), tuttle.NodeInit("tuttle.gamma", master=.5), tuttle.NodeInit("tuttle.jpegwriter", filename=".tests/fromExr/output-####.jpg"), ] nodes = graph.addConnectedNodes(n) procOptions = tuttle.ComputeOptions() procGraph = tuttle.ProcessGraph(procOptions, graph, [], tuttle.core().getMemoryCache()) print("before compute") outputCache = tuttle.MemoryCache() timeRange = tuttle.TimeRange(1, 16, 10) print("setup") procGraph.setup() print("beginSequence") procGraph.beginSequence(timeRange) for time in range(timeRange._begin, timeRange._end, timeRange._step): print("time:", time) procGraph.setupAtTime(time) procGraph.processAtTime(outputCache, time) print("endSequence") procGraph.endSequence() print("after compute")
def testSimpleProcessGraph(): graph = tuttle.Graph() n = [ tuttle.NodeInit( "tuttle.exrreader", filename="TuttleOFX-data/image/openexr/DisplayWindow/t##.exr" ), tuttle.NodeInit( "tuttle.invert" ), tuttle.NodeInit( "tuttle.gamma", master=.5 ), tuttle.NodeInit( "tuttle.jpegwriter", filename=".tests/fromExr/output-####.jpg" ), ] nodes = graph.addConnectedNodes(n) procOptions = tuttle.ComputeOptions() procGraph = tuttle.ProcessGraph(procOptions, graph, [], tuttle.core().getMemoryCache()) print("before compute") outputCache = tuttle.MemoryCache() timeRange = tuttle.TimeRange(1, 16, 10) print("setup") procGraph.setup() print("beginSequence") procGraph.beginSequence(timeRange) for time in range(timeRange._begin, timeRange._end, timeRange._step): print("time:", time) procGraph.setupAtTime(time) procGraph.processAtTime(outputCache, time) print("endSequence") procGraph.endSequence() print("after compute")
def _displayFileFormats(self): """ Display all supported input/output file formats. """ def getListOfSupportedExtension(ofxhImageEffectNodeDescriptor): """ Return list of supported extension from a given plugin descriptor. """ propSupportedExtension = ofxhImageEffectNodeDescriptor.getParamSetProps().fetchProperty('TuttleOfxImageEffectPropSupportedExtensions') return samUtils.getListValues(propSupportedExtension) supportedExtensions = {'r': [], 'w': []} for plugin in tuttle.core().getImageEffectPluginCache().getPlugins(): try: plugin.loadAndDescribeActions() if plugin.supportsContext('OfxImageEffectContextReader'): pluginDescriptor = plugin.getDescriptorInContext('OfxImageEffectContextReader') if pluginDescriptor.getParamSetProps().hasProperty('TuttleOfxImageEffectPropSupportedExtensions'): supportedExtensions['r'].extend(getListOfSupportedExtension(pluginDescriptor)) elif plugin.supportsContext('OfxImageEffectContextWriter'): pluginDescriptor = plugin.getDescriptorInContext('OfxImageEffectContextWriter') if pluginDescriptor.getParamSetProps().hasProperty('TuttleOfxImageEffectPropSupportedExtensions'): supportedExtensions['w'].extend(getListOfSupportedExtension(pluginDescriptor)) except Exception as e: self.logger.warning('Cannot load and describe plugin "' + plugin.getIdentifier() + '".') self.logger.debug(e) for key, extensions in supportedExtensions.items(): if key == 'r': self._displayTitle('SUPPORTED INPUT FILE FORMATS') elif key == 'w': self._displayTitle('SUPPORTED OUTPUT FILE FORMATS') puts(', '.join(sorted(set(extensions))))
def testBrowseIEPlugins(): pluginCache = tuttle.core().getImageEffectPluginCache() print [p.getDescriptor().getShortLabel() for p in pluginCache.getPlugins()] print [p.getDescriptor().getLabel() for p in pluginCache.getPlugins()] print [p.getDescriptor().getLongLabel() for p in pluginCache.getPlugins()] print [p.getDescriptor().getPluginGrouping() for p in pluginCache.getPlugins()]
def testBrowsePlugins(): pluginCache = tuttle.core().getPluginCache() pluginPath = pluginCache.getPluginPath() print([p for p in pluginPath]) # print([p for p in pluginCache.getPluginPath()]) # BUG binding: TODO print([p.getIdentifier() for p in pluginCache.getPlugins()])
def testBrowseIEPlugins(): pluginCache = tuttle.core().getImageEffectPluginCache() print([p.getDescriptor().getShortLabel() for p in pluginCache.getPlugins()]) print([p.getDescriptor().getLabel() for p in pluginCache.getPlugins()]) print([p.getDescriptor().getLongLabel() for p in pluginCache.getPlugins()]) print([p.getDescriptor().getPluginGrouping() for p in pluginCache.getPlugins()])
def _displayPlugins(self): """ Display all available plugins (in alphabetical order), with their versions (v[major].[minor]). """ plugins = [] for plugin in tuttle.core().getPlugins(): plugins.append(plugin.getIdentifier().ljust(30) + ' (v' + str(plugin.getVersionMajor()) + '.' + str(plugin.getVersionMinor()) + ')') for plugin in sorted(set(plugins)): puts(plugin)
def samDoCompleter(prefix, parsed_args, **kwargs): """ Custom Completer to manage auto competion when looking for openFX nodes. @warning The autocompletion works only for TuttleOFX plugins. """ # preload OFX plugins (to have auto completion of plugins name, their parameters...) tuttle.core().preload(True) # get plugins pluginsId = tuttle.core().getImageEffectPluginCache().getPluginsByID() pluginsStr = [str(id).replace('tuttle.', '') for id in pluginsId] # check last input in command line if len(parsed_args.inputs): lastInput = parsed_args.inputs[-1] # if last input is a plugin, return its parameters if lastInput in pluginsStr: graph = tuttle.Graph() node = graph.createNode('tuttle.'+lastInput) params = node.getParams() paramsStr = [str(param.getScriptName()) for param in params] return paramsStr elif lastInput == '//': return pluginsStr else: for input in reversed(parsed_args.inputs): # if an input is a plugin, get its parameters if input in pluginsStr: graph = tuttle.Graph() node = graph.createNode('tuttle.'+input) params = node.getParams() paramsStr = [str(param.getScriptName()) for param in params] # if last input is one of its parameters, return its choices if lastInput in paramsStr: param = node.getParam(lastInput) if param.getProperties().hasProperty('OfxParamPropChoiceOption'): propChoiceOption = param.getProperties().fetchProperty('OfxParamPropChoiceOption') choicesStr = samUtils.getListValues(propChoiceOption) return choicesStr # else, return its parameters else: return paramsStr # else return available plugins return pluginsStr
def getPluginName(self, logger): """ Return complete node name from the pluginId and its arguments. Plugin's arguments can be used to get best reader/writer. @note Get best reader if the given name is 'r'. @note Get best writer if the given name is 'w'. @exception if cannot find the plugin name which corresponds to the plugin id """ if self.isGenericReader() or self.isGenericWriter(): if len(self._arguments) == 0: logger.warning( 'Cannot guess the best reader/writer node without any filename specified.' ) # get filename filename = self._arguments[0][1] # return best reader if self.isGenericReader(): bestReader = tuttle.getBestReader(filename) logger.info('Use "' + bestReader + '" to read "' + filename + '".') return bestReader # return best writer elif self.isGenericWriter(): bestWriter = tuttle.getBestWriter(filename) logger.info('Use "' + bestWriter + '" to write "' + filename + '".') return bestWriter else: pluginsMap = tuttle.core().getImageEffectPluginCache( ).getPluginsByID() # get plugins name which match with the given id pluginNames = [] for pluginName in pluginsMap: # if the given id exactly matches the plugin id # plugin id = plugin name without its group if self._pluginId == pluginName[pluginName.rfind('.') + 1:]: return pluginName # else if the given id is contains in the plugin name elif self._pluginId in pluginName: pluginNames.append(pluginName) # one plugin matches if len(pluginNames) == 1: return pluginNames[0] # more than one matches elif len(pluginNames) > 1: logger.warning( 'Cannot guess the best match for plugin name "' + self._pluginId + '".') logger.warning('Possible choices are: "' + ', '.join(pluginNames) + '".') # cannot find a best reader/writer or no plugin name matches with the id raise RuntimeError('Plugin with id "' + self._pluginId + '" not found.')
def analyse(pluginPath): ''' Analyse the bundle an return a description for each plugin. ''' pluginCache = tuttle.core().getPluginCache() pluginCache.addDirectoryToPath(str(pluginPath)) tuttle.core().getFormatter().setLogLevel_int(5) tuttle.core().preload(False) plugins = pluginCache.getPlugins() logging.warning('pluginCache: %s' % pluginCache) logging.warning('Analyse plugins: %s' % pluginPath) logging.warning('Nb plugins: %s' % len(plugins)) pluginsDescription = {'plugins':[], 'total': len(plugins)} for currentPlugin in plugins: logging.warning(currentPlugin.getRawIdentifier()) p = Plugin.Plugin(currentPlugin) pluginsDescription['plugins'].append(p.__dict__) return pluginsDescription
def testPluginDescProps(): """ Test the 'SupportedExtensions' and 'Evaluation' properties of plugins pluginTurboJpeg and pluginImageMagick. """ # test evaluation for pluginTurboJpeg turboJpeg_plugin = tuttle.core().getImageEffectPluginCache().getPluginByLabel("TuttleTurboJpegReader") turboJpeg_plugin.loadAndDescribeActions() turboJpeg_desc = turboJpeg_plugin.getDescriptor() assert turboJpeg_desc.getProperties().hasProperty("TuttleOfxImageEffectPropSupportedExtensions", True) assert turboJpeg_desc.getProperties().hasProperty("TuttleOfxImageEffectPropEvaluation", True) turboJpeg_evaluation = turboJpeg_desc.getProperties().getDoubleProperty("TuttleOfxImageEffectPropEvaluation") assert_equal(turboJpeg_evaluation, 90) # test evaluation for pluginImageMagick imageMagick_plugin = tuttle.core().getImageEffectPluginCache().getPluginByLabel("TuttleImageMagickReader") imageMagick_plugin.loadAndDescribeActions() imageMagick_desc = imageMagick_plugin.getDescriptor() assert imageMagick_desc.getProperties().hasProperty("TuttleOfxImageEffectPropSupportedExtensions", True) assert imageMagick_desc.getProperties().hasProperty("TuttleOfxImageEffectPropEvaluation", True) imageMagick_evaluation = imageMagick_desc.getProperties().getDoubleProperty("TuttleOfxImageEffectPropEvaluation") assert_equal(imageMagick_evaluation, 0)
def getPluginName(self, logger): """ Return complete node name from the pluginId and its arguments. Plugin's arguments can be used to get best reader/writer. @note Get best reader if the given name is 'r'. @note Get best writer if the given name is 'w'. @exception if cannot find the plugin name which corresponds to the plugin id """ if self.isGenericReader() or self.isGenericWriter(): if len(self._arguments) == 0: logger.warning('Cannot guess the best reader/writer node without any filename specified.') # get filename filename = self._arguments[0][1] # return best reader if self.isGenericReader(): bestReader = tuttle.getBestReader(filename) logger.info('Use "' + bestReader + '" to read "' + filename + '".') return bestReader # return best writer elif self.isGenericWriter(): bestWriter = tuttle.getBestWriter(filename) logger.info('Use "' + bestWriter + '" to write "' + filename + '".') return bestWriter else: pluginsMap = tuttle.core().getImageEffectPluginCache().getPluginsByID() # get plugins name which match with the given id pluginNames = [] for pluginName in pluginsMap: # if the given id exactly matches the plugin id # plugin id = plugin name without its group if self._pluginId == pluginName[pluginName.rfind('.') + 1:]: return pluginName # else if the given id is contains in the plugin name elif self._pluginId in pluginName: pluginNames.append(pluginName) # one plugin matches if len(pluginNames) == 1: return pluginNames[0] # more than one matches elif len(pluginNames) > 1: logger.warning('Cannot guess the best match for plugin name "' + self._pluginId +'".') logger.warning('Possible choices are: "' + ', '.join(pluginNames) +'".') # cannot find a best reader/writer or no plugin name matches with the id raise RuntimeError('Plugin with id "' + self._pluginId + '" not found.')
def _displayFileFormats(self): """ Display all supported input/output file formats. """ def getListOfSupportedExtension(ofxhImageEffectNodeDescriptor): """ Return list of supported extension from a given plugin descriptor. """ propSupportedExtension = ofxhImageEffectNodeDescriptor.getParamSetProps( ).fetchProperty('TuttleOfxImageEffectPropSupportedExtensions') return samUtils.getListValues(propSupportedExtension) supportedExtensions = {'r': [], 'w': []} for plugin in tuttle.core().getImageEffectPluginCache().getPlugins(): try: plugin.loadAndDescribeActions() if plugin.supportsContext('OfxImageEffectContextReader'): pluginDescriptor = plugin.getDescriptorInContext( 'OfxImageEffectContextReader') if pluginDescriptor.getParamSetProps().hasProperty( 'TuttleOfxImageEffectPropSupportedExtensions'): supportedExtensions['r'].extend( getListOfSupportedExtension(pluginDescriptor)) elif plugin.supportsContext('OfxImageEffectContextWriter'): pluginDescriptor = plugin.getDescriptorInContext( 'OfxImageEffectContextWriter') if pluginDescriptor.getParamSetProps().hasProperty( 'TuttleOfxImageEffectPropSupportedExtensions'): supportedExtensions['w'].extend( getListOfSupportedExtension(pluginDescriptor)) except Exception as e: self.logger.warning('Cannot load and describe plugin "' + plugin.getIdentifier() + '".') self.logger.debug(e) for key, extensions in supportedExtensions.items(): if key == 'r': self._displayTitle('SUPPORTED INPUT FILE FORMATS') elif key == 'w': self._displayTitle('SUPPORTED OUTPUT FILE FORMATS') puts(', '.join(sorted(set(extensions))))
#!/usr/bin/python import os from sys import argv from pyTuttle import tuttle tuttle.core().preload(False) tuttle.core().getFormatter().setLogLevel(tuttle.eVerboseLevelError) def start(): """ A callback function """ print "One, two, three... Go!" class ProgressHandle(tuttle.IProgressHandle): """ Progress handle that must inherit IProgressHandle beginSequence(), setupAtTime(), processAtTime() and endSequence() have to be overwritten Do whatever you want do in these functions (print, increment var, call another func...) See example above """ def __init__(self, callback=None): # Required super(ProgressHandle, self).__init__() # Test counter (optional) self.callback = callback
def main(argv): #preload Tuttle tuttle.core().preload() # give to QML acces to TimerPlayer defined in buttleofx/gui/viewer QtDeclarative.qmlRegisterType(TimerPlayer, "TimerPlayer", 1, 0, "TimerPlayer") # add new QML type QtDeclarative.qmlRegisterType(Finder, "FolderListViewItem", 1, 0, "FolderListView") if tuttleofx_installed: QtDeclarative.qmlRegisterType(GLViewport_tuttleofx, "Viewport", 1, 0, "GLViewport") else: QtDeclarative.qmlRegisterType(GLViewport_pil, "Viewport", 1, 0, "GLViewport") # init undo_redo contexts cmdManager = CommandManager() cmdManager.setActive() cmdManager.clean() # create QApplication app = ButtleApp(argv) # create the declarative view view = QtDeclarative.QDeclarativeView() view.setViewport(QtOpenGL.QGLWidget()) view.setViewportUpdateMode(QtDeclarative.QDeclarativeView.FullViewportUpdate) # data buttleData = ButtleDataSingleton().get().init(view, currentFilePath) # manager buttleManager = ButtleManagerSingleton().get().init() # event buttleEvent = ButtleEventSingleton().get() # Menus fileMenu = MenuWrapper("file", 0, view, app) editMenu = MenuWrapper("edit", 0, view, app) addMenu = MenuWrapper("buttle/", 1, view, app) # expose data to QML rc = view.rootContext() rc.setContextProperty("_buttleApp", app) rc.setContextProperty("_buttleData", buttleData) rc.setContextProperty("_buttleManager", buttleManager) rc.setContextProperty("_buttleEvent", buttleEvent) rc.setContextProperty("_fileMenu", fileMenu) rc.setContextProperty("_editMenu", editMenu) rc.setContextProperty("_addMenu", addMenu) # set the view view.setSource(os.path.join(currentFilePath, "MainWindow.qml")) view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView) view.setWindowTitle("ButtleOFX") view.setWindowIcon(QtGui.QIcon("blackMosquito.png")) view.setWindowIconText("ButtleOFX") view.setVisible(True) # Declare we are using instant coding tool on this view qic = QmlInstantCoding(view, verbose=True) # Add any source file (.qml and .js by default) in current working directory qic.addFilesFromDirectory(os.getcwd(), recursive=True) #add._menu.popup(view.mapToGlobal(QtCore.QPoint(0, 0))) view.show() app.exec_()
dest="text", default=False, action="store_true", help="burn date and sequence name on output movie (disable by default)") ### Parse command-line args = parser.parse_args() ### Get sequence sequence = getSequence(args.inputSequence) if args.interactive: interactiveMode() ### Initialize Tuttle graph tuttle.core().preload(False) tuttle.core().getFormatter().setLogLevel(tuttle.eVerboseLevelFatal) graph = tuttle.Graph() nodes = [] # Set verbose level options = tuttle.ComputeOptions() # Set progress handle progress = ProgressHandle() options.setProgressHandle(progress) ### Create reader node nodes.append( graph.createNode(getReaderId(args.inputSequence), filename=args.inputSequence)) # Depend on input, manage color conversion
def setUp(): print("testComputeTime setUp") tuttle.core().getFormatter().setLogLevel_int(0) tuttle.core().preload(False)
def getPluginsIdentifiers(): """ Returns the list of all names of Tuttle's plugins. """ pluginCache = tuttle.core().getPluginCache() return [plugin.getIdentifier() for plugin in pluginCache.getPlugins()]
def setUp(): tuttle.core().preload(False)
from pyTuttle import tuttle tuttle.core().preload() pluginCache = tuttle.core().getPluginCache() print [p for p in pluginCache.getPluginPath()] print [p.getIdentifier() for p in pluginCache.getPlugins()]
def testBrowsePlugins(): pluginCache = tuttle.core().getPluginCache() print [p for p in pluginCache.getPluginPath()]
#!/usr/bin/python import os from sys import argv from pyTuttle import tuttle tuttle.core().preload(False) def start(): """ A callback function """ print "One, two, three... Go!" class ProgressHandle(tuttle.IProgressHandle): """ Progress handle that must inherit IProgressHandle beginSequence(), setupAtTime(), processAtTime() and endSequence() have to be overwritten Do whatever you want do in these functions (print, increment var, call another func...) See example above """ def __init__(self, callback=None): # Required super(ProgressHandle, self).__init__() # Test counter (optional) self.callback = callback self.counter = 0
def setUp(): print "testComputeTime setUp" tuttle.core().preload(False)
def getPlugins(): """ Returns the list of all Tuttle's plugins. """ pluginCache = tuttle.core().getPluginCache() return pluginCache.getPlugins()
def run(self, parser): """ Process the do operation. """ # Parse command-line args, unknown = parser.parse_known_args() # Set sam log level self.setLogLevel(args.verbose) # set tuttle host log level tuttle.core().getFormatter().setLogLevel(args.verbose) # Clear plugin cache if args.rebuildPluginCache: tuttle.core().getPluginCache().clearPluginFiles() # preload OFX plugins if args.noPluginCache: tuttle.core().preload(False) else: tuttle.core().preload(True) # sam-do --nodes if args.nodes: self._displayPlugins() exit(0) # sam-do --file-formats if args.fileFormats: self._displayFileFormats() exit(0) # sam-do --help if self._isCommandLineAskForHelp(args.inputs, unknown): self._displayCommandLineHelp(parser) exit(0) # Check sam-do command line if self._isCommandLineInvalid(args.inputs, unknown): self._displayCommandLineHelp(parser) exit(1) # Add unknown options to the command line to process args.inputs.extend(unknown) # Split command line splitCmd = samDoUtils.SplitCmd(args.inputs, args.noRecursivity) graphsWithNodes = [] for splitCmdGraph in splitCmd.getGraphs(): self.logger.debug('Create the following tuttle graph: \n' + str(splitCmdGraph)) try: graphsWithNodes.append(self._getTuttleGraph(splitCmdGraph)) except Exception as e: self.logger.error('Cannot create tuttle graph') self.logger.debug('\n' + str(splitCmdGraph)) self.logger.debug(e) if not graphsWithNodes: self.logger.error('No tuttle graph to compute.') exit(1) error = 0 # Compute the corresponding tuttle graphs for graph, nodes in graphsWithNodes: # Options of process options = tuttle.ComputeOptions() # sam-do --ranges if args.ranges is not None: self._setTimeRanges(options, args.ranges) # sam-do --continue-on-error options.setContinueOnError(args.continueOnError) # sam-do --stop-on-missing-files options.setContinueOnMissingFile(not args.stopOnMissingFiles) # Set progress handle ranges = options.getTimeRanges() if not len(ranges): # get time domaine try: timeDomain = nodes[0].asImageEffectNode( ).computeTimeDomain() ranges = [] ranges.append( tuttle.TimeRange(int(timeDomain.min), int(timeDomain.max), 1)) except Exception as e: # the first added node has no filename set pass progress = samDoUtils.ProgressHandle(ranges) options.setProgressHandle(progress) if not nodes: self.logger.warning('No tuttle nodes to compute') continue # Connect and compute try: graph.compute(nodes[-1], options) except Exception as e: self.logger.error('Tuttle graph computation has failed.') self.logger.debug(e) error = 1 self.logger.info('Memory usage: ' + str(int(samUtils.memoryUsageResource())) + 'KB') exit(error)
def convertScenePatterns(scene): ''' Replace PATTERNS with real filepaths. :param scene: dict with nodes, params and connections. :return: (scene, outputFilepaths) ''' outputScene = copy.deepcopy(scene) # Preload general plugins to use getBestReader/getBestWriter. tuttle.core().getPluginCache().addDirectoryToPath(globalOfxPluginPath) tuttle.core().preload(False) logging.debug("outputScene: " + str(outputScene)) outputResources = [] for node in outputScene['nodes']: if 'plugin' in node and node['plugin'] is not 'reader': logging.debug("Retrieve bundleId from plugin: " + str(node['plugin'])) resp = requests.get(catalogRootUri + "/bundle/" + node['plugin'] + '/bundle') if resp.status_code == 404: logging.warning("Cannont retrieve bundleId for plugin: " + str(node['plugin'])) else: respJson = resp.json() node["bundleId"] = respJson['bundleId'] logging.debug("bundleId: " + str(respJson['bundleId'])) for parameter in node['parameters']: logging.warning('param: %s %s', parameter['id'], parameter['value']) if isinstance(parameter['value'], (str, unicode)): if 'plugin' not in node and '{RESOURCES_DIR}' in parameter['value']: parameter['value'] = parameter['value'].replace('{RESOURCES_DIR}', config.resourcesPath) node['plugin'] = tuttle.getBestReader(str(parameter['value'])) if 'plugin' not in node and '{UNIQUE_OUTPUT_FILE}' in parameter['value']: node['plugin'] = tuttle.getBestWriter(str(parameter['value'])) # Declare Bundles paths to TuttleOFX bundleIds = [] for node in outputScene['nodes']: if 'bundleId' in node: bundleIds.append(node['bundleId']) else: logging.error("No bundle defined for node: " + str(node)) bundlePaths = [os.path.join(pluginsStorage, str(bundleId)) for bundleId in bundleIds] logging.debug("bundlePaths: " + str(bundlePaths)) configLocalPluginPath(bundlePaths) logging.debug("outputScene after conversion: " + str(outputScene)) # Create a Tuttle Graph to generate the UID for each node tuttleGraphTmp = loadGraph(outputScene) # logging.warning("tuttleGraphTemp" + str(tuttleGraphTmp)) # logging.warning("outputScene" + str(outputScene)) nodesHashMap = tuttle.NodeHashContainer() tuttleGraphTmp.computeGlobalHashAtTime(nodesHashMap, 0.0) for node in outputScene['nodes']: for parameter in node['parameters']: logging.warning('param: %s %s', parameter['id'], parameter['value']) if isinstance(parameter['value'], (str, unicode)): if '{UNIQUE_OUTPUT_FILE}' in parameter['value']: prefix, suffix = parameter['value'].split('{UNIQUE_OUTPUT_FILE}') nodeHash = str(nodesHashMap.getHash(node['name'], 0.0)) node['hash'] = nodeHash filename = nodeHash + suffix filepath = os.path.join(config.renderDirectory, cache.cachePathFromFile(filename)) outputResources.append(filename) parameter['value'] = filepath return (outputScene, outputResources)
from pyTuttle import tuttle import numpy import Image # This is called by Tuttle as an input of the graph def getImage(time): img = numpy.asarray( Image.open("data/input.jpg") ) img = numpy.flipud(img) return (img.tostring(), img.shape[1], img.shape[0], img.strides[0]) tuttle.core().preload() g = tuttle.Graph() ib = g.createInputBuffer() ib.setComponents( tuttle.InputBufferWrapper.ePixelComponentRGB ); ib.setBitDepth( tuttle.InputBufferWrapper.eBitDepthUByte ); ib.setOrientation( tuttle.InputBufferWrapper.eImageOrientationFromTopToBottom ); ib.setPyCallback( getImage ) w = g.createNode("tuttle.pngwriter", filename="foo.png") g.connect( ib.getNode(), w ) g.compute( w )
def testBrowsePlugins(): pluginCache = tuttle.core().getPluginCache() print [p for p in pluginCache.getPluginPath()] print [p.getIdentifier() for p in pluginCache.getPlugins()]
def run(self, parser): """ Process the do operation. """ # Parse command-line args, unknown = parser.parse_known_args() # Set sam log level self.setLogLevel(args.verbose) # set tuttle host log level tuttle.core().getFormatter().setLogLevel_int(args.verbose) # Clear plugin cache if args.rebuildPluginCache: tuttle.core().getPluginCache().clearPluginFiles() # preload OFX plugins if args.noPluginCache: tuttle.core().preload(False) else: tuttle.core().preload(True) # sam-do --nodes if args.nodes: self._displayPlugins() exit(0) # sam-do --file-formats if args.fileFormats: self._displayFileFormats() exit(0) # sam-do --help if self._isCommandLineInvalid(args.inputs, unknown): self._displayCommandLineHelp(parser) exit(0) # Add unknown options to the command line to process args.inputs.extend(unknown) # Split command line splitCmd = samDoUtils.SplitCmd(args.inputs, args.noRecursivity) graphsWithNodes = [] for splitCmdGraph in splitCmd.getGraphs(): self.logger.debug('Create the following tuttle graph: \n' + str(splitCmdGraph)) try: graphsWithNodes.append(self._getTuttleGraph(splitCmdGraph)) except Exception as e: self.logger.error('Cannot create tuttle graph') self.logger.debug('\n' + str(splitCmdGraph)) self.logger.debug(e) if not graphsWithNodes: self.logger.error('No tuttle graph to compute.') exit(1) # Compute the corresponding tuttle graphs for graph, nodes in graphsWithNodes: # Options of process options = tuttle.ComputeOptions() # sam-do --verbose options.setVerboseLevel(args.verbose) # sam-do --ranges if args.ranges is not None: self._setTimeRanges(options, args.ranges) # sam-do --continue-on-error options.setContinueOnError(args.continueOnError) # sam-do --stop-on-missing-files options.setContinueOnMissingFile(not args.stopOnMissingFiles) # Set progress handle ranges = options.getTimeRanges() if not len(ranges): # get time domaine try: timeDomain = nodes[0].asImageEffectNode().computeTimeDomain() ranges = [] ranges.append(tuttle.TimeRange(int(timeDomain.min), int(timeDomain.max), 1)) except Exception as e: # the first added node has no filename set pass progress = samDoUtils.ProgressHandle(ranges) options.setProgressHandle(progress) if not nodes: self.logger.warning('No tuttle nodes to compute') continue # Connect and compute try: graph.compute(nodes[-1], options) except Exception as e: self.logger.error('Tuttle graph computation has failed.') self.logger.debug(e) self.logger.info('Memory usage: ' + str(int(samUtils.memoryUsageResource())) + 'KB')
from pyTuttle import tuttle import numpy import Image tuttle.core().preload() g = tuttle.Graph() ib = g.createInputBuffer() # numpy array from an image img = numpy.asarray(Image.open('data/input.jpg')) ib.set3DArrayBuffer(img) # generated numpy array #x = numpy.array([[.9, .1, .9], [.8, .2, .9]], numpy.float32) #ib.set2DArrayBuffer( x ) w = g.createNode("tuttle.pngwriter", filename="foo.png") g.connect(ib.getNode(), w) g.compute(w)
def convertScenePatterns(scene): ''' Replace PATTERNS with real filepaths. :param scene: dict with nodes, params and connections. :return: (scene, outputFilepaths) ''' outputScene = copy.deepcopy(scene) # Preload general plugins to use getBestReader/getBestWriter. tuttle.core().getPluginCache().addDirectoryToPath(globalOfxPluginPath) tuttle.core().preload(False) logging.debug("outputScene: " + str(outputScene)) outputResources = [] for node in outputScene['nodes']: if 'plugin' in node and node['plugin'] is not 'reader': logging.debug("Retrieve bundleId from plugin: " + str(node['plugin'])) resp = requests.get(catalogRootUri + "/bundle/" + node['plugin'] + '/bundle') if resp.status_code == 404: logging.warning("Cannont retrieve bundleId for plugin: " + str(node['plugin'])) else: respJson = resp.json() node["bundleId"] = respJson['bundleId'] logging.debug("bundleId: " + str(respJson['bundleId'])) for parameter in node['parameters']: logging.warning('param: %s %s', parameter['id'], parameter['value']) if isinstance(parameter['value'], (str, unicode)): if 'plugin' not in node and '{RESOURCES_DIR}' in parameter[ 'value']: parameter['value'] = parameter['value'].replace( '{RESOURCES_DIR}', config.resourcesPath) node['plugin'] = tuttle.getBestReader( str(parameter['value'])) if 'plugin' not in node and '{UNIQUE_OUTPUT_FILE}' in parameter[ 'value']: node['plugin'] = tuttle.getBestWriter( str(parameter['value'])) # Declare Bundles paths to TuttleOFX bundleIds = [] for node in outputScene['nodes']: if 'bundleId' in node: bundleIds.append(node['bundleId']) else: logging.error("No bundle defined for node: " + str(node)) bundlePaths = [ os.path.join(pluginsStorage, str(bundleId)) for bundleId in bundleIds ] logging.debug("bundlePaths: " + str(bundlePaths)) configLocalPluginPath(bundlePaths) logging.debug("outputScene after conversion: " + str(outputScene)) # Create a Tuttle Graph to generate the UID for each node tuttleGraphTmp = loadGraph(outputScene) # logging.warning("tuttleGraphTemp" + str(tuttleGraphTmp)) # logging.warning("outputScene" + str(outputScene)) nodesHashMap = tuttle.NodeHashContainer() tuttleGraphTmp.computeGlobalHashAtTime(nodesHashMap, 0.0) for node in outputScene['nodes']: for parameter in node['parameters']: logging.warning('param: %s %s', parameter['id'], parameter['value']) if isinstance(parameter['value'], (str, unicode)): if '{UNIQUE_OUTPUT_FILE}' in parameter['value']: prefix, suffix = parameter['value'].split( '{UNIQUE_OUTPUT_FILE}') nodeHash = str(nodesHashMap.getHash(node['name'], 0.0)) node['hash'] = nodeHash filename = nodeHash + suffix filepath = os.path.join(config.renderDirectory, cache.cachePathFromFile(filename)) outputResources.append(filename) parameter['value'] = filepath return (outputScene, outputResources)
def setUp(): print("testComputeTime setUp") tuttle.core().preload(False)
def getPluginsIdentifiersAsDictionary(): """ Returns a dictionary of what we need to display the menu of the node creation. For each level in the menu we need to have the list of items of the submenu When the items are plugins, we need to know their label to display, and their identifier to be able to create the node. So this dictionary returns a tuple : - if it's a plugin, the tuple is : (pluginLabel, pluginIdentifier) - if i's a category of plugins, the tuple is : (categoryLabel, "") The keys of this dictionary are the "paths" of each element of the menu. Example : pluginsIdentifiersAsDictionary["buttle/tuttle/"] = ['image', 'param'] pluginsIdentifiersAsDictionary["buttle/tuttle/image/"] = ['io', 'process', 'generator', 'display', 'tool'] pluginsIdentifiersAsDictionary["buttle/tuttle/image/tool/"] = ['tuttle.dummy'] """ # root label : parent of all plugins buttleLabel = "buttle/" # list of all Tuttle's plugins pluginCache = tuttle.core().getImageEffectPluginCache() plugins = pluginCache.getPlugins() # Creation of the dictionary pluginsIdentifiersAsDictionary = dict() # if no plugin found we just add the "buttle" key with a message for the user if len(plugins) == 0: pluginsIdentifiersAsDictionary[buttleLabel] = [] pluginsIdentifiersAsDictionary[buttleLabel].append( ('Error : no plugin found...', False)) return pluginsIdentifiersAsDictionary for plugin in plugins: pluginId = plugin.getIdentifier() # All plugin labels in Tuttle are preceded by 'Tuttle', so we can delete 'Tuttle' from the beginning of the word. It doesn't affect other plugins, not preceded by 'Tuttle'. pluginLabel = plugin.getDescriptor().getLabel().replace( 'Tuttle', '', 1) # We take the path of the plugin's parents (ex: 'tuttle/image/process/') fullPath = plugin.getDescriptor().getPluginGrouping() # We split this path to have a list of parents parentList = None if fullPath.startswith(' '): parentList = fullPath[1:].split(' ') else: parentList = fullPath.split('/') # parentLabel is the parentPath of each element of this nex list of parents parentLabel = buttleLabel # We browse this list of parents. For each element, we want to create a new entry in the dictionary. for i in range(len(parentList) + 1): # only if this parentLabel is not yet in the dictionary, we create a new list for this entry in the dictionary. if parentLabel not in pluginsIdentifiersAsDictionary: # if we are not yet at the end of the parentList, then we append the next parent if i < len(parentList): pluginsIdentifiersAsDictionary[parentLabel] = [] pluginsIdentifiersAsDictionary[parentLabel].append( (parentList[i], "")) # but if we are at the end of the parentList, then the child is the plugin itself, so we add its identifier. else: pluginsIdentifiersAsDictionary[parentLabel] = [] pluginsIdentifiersAsDictionary[parentLabel].append( (pluginLabel, pluginId)) # same reasoning, but here the parentLabel is already in the dictionary, we just append the child and not create a new list. else: if i < len(parentList): if parentList[i] not in [ p[0] for p in pluginsIdentifiersAsDictionary[parentLabel] ]: pluginsIdentifiersAsDictionary[parentLabel].append( (parentList[i], "")) else: if pluginId not in [ p[1] for p in pluginsIdentifiersAsDictionary[parentLabel] ]: pluginsIdentifiersAsDictionary[parentLabel].append( (pluginLabel, pluginId)) # We have created the right entry for this element, and we want to create a new one at the next iteration. So we update the parentLabel for this entry. if i < len(parentList): parentLabel = parentLabel + parentList[i] + "/" # Here we are ! return pluginsIdentifiersAsDictionary
parser.add_argument("-r", "--ratio", dest="ratio", type=float, help="set output movie ratio: 1.33 (4/3), 1.77 (16/9), 1.85, 2.35 (cinemascope)... (default=same as input)") parser.add_argument("-l", "--lut", dest="lut", default=False, action="store_true", help="set lut appied to output movie (disable by default)") parser.add_argument("-lp", "--lutPath", dest="lutPath", help="path of lut appied to output movie") parser.add_argument("-t", "--text", dest="text", default=False, action="store_true", help="burn date and sequence name on output movie (disable by default)") ### Parse command-line args = parser.parse_args() ### Get sequence sequence = getSequence(args.inputSequence) if args.interactive: interactiveMode() ### Initialize Tuttle graph tuttle.core().preload(False) graph = tuttle.Graph() nodes = [] # Set verbose level options = tuttle.ComputeOptions() options.setVerboseLevel(tuttle.eVerboseLevelFatal) # Set progress handle progress = ProgressHandle() options.setProgressHandle(progress) ### Create reader node nodes.append(graph.createNode(getReaderId(args.inputSequence), filename=args.inputSequence)) # Depend on input, manage color conversion fileExtension = os.path.splitext(args.inputSequence)[1].lower() if fileExtension == ".exr":
def getPluginsIdentifiersAsDictionary(): """ Returns a dictionary of what we need to display the menu of the node creation. For each level in the menu we need to have the list of items of the submenu When the items are plugins, we need to know their label to display, and their identifier to be able to create the node. So this dictionary returns a tuple : - if it's a plugin, the tuple is : (pluginLabel, pluginIdentifier) - if i's a category of plugins, the tuple is : (categoryLabel, "") The keys of this dictionary are the "paths" of each element of the menu. Example : pluginsIdentifiersAsDictionary["buttle/tuttle/"] = ['image', 'param'] pluginsIdentifiersAsDictionary["buttle/tuttle/image/"] = ['io', 'process', 'generator', 'display', 'tool'] pluginsIdentifiersAsDictionary["buttle/tuttle/image/tool/"] = ['tuttle.dummy'] """ # root label : parent of all plugins buttleLabel = "buttle/" # list of all Tuttle's plugins pluginCache = tuttle.core().getImageEffectPluginCache() plugins = pluginCache.getPlugins() # Creation of the dictionary pluginsIdentifiersAsDictionary = dict() # if no plugin found we just add the "buttle" key with a message for the user if len(plugins) == 0: pluginsIdentifiersAsDictionary[buttleLabel] = [] pluginsIdentifiersAsDictionary[buttleLabel].append(('Error : no plugin found...', False)) return pluginsIdentifiersAsDictionary for plugin in plugins: pluginId = plugin.getIdentifier() # All plugin labels in Tuttle are preceded by 'Tuttle', so we can delete 'Tuttle' from the beginning of the word. It doesn't affect other plugins, not preceded by 'Tuttle'. pluginLabel = plugin.getDescriptor().getLabel().replace('Tuttle', '', 1) # We take the path of the plugin's parents (ex: 'tuttle/image/process/') fullPath = plugin.getDescriptor().getPluginGrouping() # We split this path to have a list of parents parentList = None if fullPath.startswith(' '): parentList = fullPath[1:].split(' ') else: parentList = fullPath.split('/') # parentLabel is the parentPath of each element of this nex list of parents parentLabel = buttleLabel # We browse this list of parents. For each element, we want to create a new entry in the dictionary. for i in range(len(parentList) + 1): # only if this parentLabel is not yet in the dictionary, we create a new list for this entry in the dictionary. if parentLabel not in pluginsIdentifiersAsDictionary: # if we are not yet at the end of the parentList, then we append the next parent if i < len(parentList): pluginsIdentifiersAsDictionary[parentLabel] = [] pluginsIdentifiersAsDictionary[parentLabel].append((parentList[i], "")) # but if we are at the end of the parentList, then the child is the plugin itself, so we add its identifier. else: pluginsIdentifiersAsDictionary[parentLabel] = [] pluginsIdentifiersAsDictionary[parentLabel].append((pluginLabel, pluginId)) # same reasoning, but here the parentLabel is already in the dictionary, we just append the child and not create a new list. else: if i < len(parentList): if parentList[i] not in [p[0] for p in pluginsIdentifiersAsDictionary[parentLabel]]: pluginsIdentifiersAsDictionary[parentLabel].append((parentList[i], "")) else: if pluginId not in [p[1] for p in pluginsIdentifiersAsDictionary[parentLabel]]: pluginsIdentifiersAsDictionary[parentLabel].append((pluginLabel, pluginId)) # We have created the right entry for this element, and we want to create a new one at the next iteration. So we update the parentLabel for this entry. if i < len(parentList): parentLabel = parentLabel + parentList[i] + "/" # Here we are ! return pluginsIdentifiersAsDictionary
#!/usr/bin/python from __future__ import print_function from pyTuttle import tuttle tuttle.core().preload(False) for p in tuttle.core().getPlugins(): print(p.getIdentifier().ljust(30) + " (v" + str( p.getVersionMajor() ) + "." + str( p.getVersionMinor() ) + ")")
#!/usr/bin/python from __future__ import print_function from pyTuttle import tuttle tuttle.core().preload(False) for p in tuttle.core().getPlugins(): print(p.getIdentifier().ljust(30) + " (v" + str(p.getVersionMajor()) + "." + str(p.getVersionMinor()) + ")")