def testClipOrder(): a_g = tuttle.Graph() a_read1 = a_g.createNode("tuttle.checkerboard", size=[50, 50]) a_read2 = a_g.createNode("tuttle.checkerboard", size=[50, 49]) a_merge = a_g.createNode("tuttle.merge") a_g.connect(a_read1, a_merge.getClip("A")) a_g.connect(a_read2, a_merge.getClip("B")) b_g = tuttle.Graph() b_read1 = b_g.createNode("tuttle.checkerboard", size=[50, 50]) b_read2 = b_g.createNode("tuttle.checkerboard", size=[50, 49]) b_merge = b_g.createNode("tuttle.merge") b_g.connect(b_read1, b_merge.getClip("A")) b_g.connect(b_read2, b_merge.getClip("B")) assert_equal(a_merge.getLocalHashAtTime(1.0), b_merge.getLocalHashAtTime(1.0)) c_g = tuttle.Graph() c_read1 = c_g.createNode("tuttle.checkerboard", size=[50, 50]) c_read2 = c_g.createNode("tuttle.checkerboard", size=[50, 49]) c_merge = c_g.createNode("tuttle.merge") c_g.connect(c_read1, c_merge.getClip("B")) c_g.connect(c_read2, c_merge.getClip("A")) # Clip connections has no impact assert_equal(b_merge.getLocalHashAtTime(1.0), c_merge.getLocalHashAtTime(1.0))
def testNotTheSameClipIsUnconnected(): """ A "fade" node with 2 optional input clips should have different hashes depending on which input is unconnected. """ a_g = tuttle.Graph() a_read1 = a_g.createNode("tuttle.checkerboard", size=[50, 50]) a_fade = a_g.createNode("tuttle.fade") a_g.connect(a_read1, a_fade.getClip("SourceFrom")) # a_fade.getClip("SourceTo") is unconnected b_g = tuttle.Graph() b_read1 = b_g.createNode("tuttle.checkerboard", size=[50, 50]) b_fade = b_g.createNode("tuttle.fade") b_g.connect(b_read1, b_fade.getClip("SourceTo")) # b_fade.getClip("SourceFrom") is unconnected time = 0.0 aHashMap = tuttle.NodeHashContainer() a_g.computeGlobalHashAtTime(aHashMap, time) aHash = aHashMap.getHash(a_fade.getName(), time) bHashMap = tuttle.NodeHashContainer() b_g.computeGlobalHashAtTime(bHashMap, time) bHash = bHashMap.getHash(b_fade.getName(), time) assert_not_equal(aHash, bHash)
def testClipOrderWithSameInputs(): """ The "merge" node has 2 input clips. The order of these input connections modify the hash only if these input are different. "Merge.A -> Read1" and "Merge.B -> Read2" is the same than "Merge.A -> Read2" and "Merge.B -> Read1" ONLY IF Read1 is the same than Read2 """ a_g = tuttle.Graph() a_read1 = a_g.createNode("tuttle.checkerboard", size=[50, 72]) a_read2 = a_g.createNode("tuttle.checkerboard", size=[50, 72]) a_merge = a_g.createNode("tuttle.merge") a_g.connect(a_read1, a_merge.getClip("A")) a_g.connect(a_read2, a_merge.getClip("B")) b_g = tuttle.Graph() b_read1 = b_g.createNode("tuttle.checkerboard", size=[50, 72]) b_read2 = b_g.createNode("tuttle.checkerboard", size=[50, 72]) b_merge = b_g.createNode("tuttle.merge") b_g.connect(b_read2, b_merge.getClip("A")) b_g.connect(b_read1, b_merge.getClip("B")) time = 0.0 aHashMap = tuttle.NodeHashContainer() a_g.computeGlobalHashAtTime(aHashMap, time) aHash = aHashMap.getHash(a_merge.getName(), time) bHashMap = tuttle.NodeHashContainer() b_g.computeGlobalHashAtTime(bHashMap, time) bHash = bHashMap.getHash(b_merge.getName(), time) assert_equal(aHash, bHash)
def testSameGraph(): """ If we create 2 identical graphs, their hashes should be the same! """ a_g = tuttle.Graph() a_read1 = a_g.createNode("tuttle.checkerboard", size=[50, 50]) a_read2 = a_g.createNode("tuttle.checkerboard", size=[50, 49]) a_merge = a_g.createNode("tuttle.merge") a_g.connect(a_read1, a_merge.getClip("A")) a_g.connect(a_read2, a_merge.getClip("B")) b_g = tuttle.Graph() b_read1 = b_g.createNode("tuttle.checkerboard", size=[50, 50]) b_read2 = b_g.createNode("tuttle.checkerboard", size=[50, 49]) b_merge = b_g.createNode("tuttle.merge") b_g.connect(b_read1, b_merge.getClip("A")) b_g.connect(b_read2, b_merge.getClip("B")) time = 0.0 aHashMap = tuttle.NodeHashContainer() a_g.computeGlobalHashAtTime(aHashMap, time) aHash = aHashMap.getHash(a_merge.getName(), time) bHashMap = tuttle.NodeHashContainer() b_g.computeGlobalHashAtTime(bHashMap, time) bHash = bHashMap.getHash(b_merge.getName(), time) assert_equal(aHash, bHash)
def testClipOrder(): """ The "merge" node has 2 input clips. The order of these input connections should modify the hash. "Merge.A -> Read1" and "Merge.B -> Read2" is NOT the same than "Merge.A -> Read2" and "Merge.B -> Read1" """ a_g = tuttle.Graph() a_read1 = a_g.createNode("tuttle.checkerboard", size=[50, 50]) a_read2 = a_g.createNode("tuttle.checkerboard", size=[50, 49]) a_merge = a_g.createNode("tuttle.merge") a_g.connect(a_read1, a_merge.getClip("A")) a_g.connect(a_read2, a_merge.getClip("B")) c_g = tuttle.Graph() c_read1 = c_g.createNode("tuttle.checkerboard", size=[50, 50]) c_read2 = c_g.createNode("tuttle.checkerboard", size=[50, 49]) c_merge = c_g.createNode("tuttle.merge") c_g.connect(c_read2, c_merge.getClip("A")) c_g.connect(c_read1, c_merge.getClip("B")) time = 0.0 aHashMap = tuttle.NodeHashContainer() a_g.computeGlobalHashAtTime(aHashMap, time) aHash = aHashMap.getHash(a_merge.getName(), time) cHashMap = tuttle.NodeHashContainer() c_g.computeGlobalHashAtTime(cHashMap, time) cHash = cHashMap.getHash(c_merge.getName(), time) assert_not_equal(aHash, cHash)
def testNotValidGraphRaise(): """ To compute the hash we need to run setupAtTime first (we need to know if the node isFrameVaying, etc.). "setupAtTime()" raises if the graph is not valid, like a non optional clip is unconnected. And there is no sense to compute the hash of a node which is not valid. @todo: The computeGlobalHashAtTime should not throw, and it should compute the hash of all valid nodes. """ a_g = tuttle.Graph() a_read1 = a_g.createNode("tuttle.checkerboard", size=[50, 50]) a_read2 = a_g.createNode("tuttle.checkerboard", size=[50, 49]) a_merge = a_g.createNode("tuttle.merge") a_g.connect(a_read1, a_merge.getClip("A")) b_g = tuttle.Graph() b_read1 = b_g.createNode("tuttle.checkerboard", size=[50, 50]) b_read2 = b_g.createNode("tuttle.checkerboard", size=[50, 49]) b_merge = b_g.createNode("tuttle.merge") b_g.connect(b_read2, b_merge.getClip("B")) time = 0.0 aHashMap = tuttle.NodeHashContainer() assert_raises(Exception, a_g.computeGlobalHashAtTime, aHashMap, time) bHashMap = tuttle.NodeHashContainer() assert_raises(Exception, b_g.computeGlobalHashAtTime, bHashMap, time)
def testComputeTime(): nbFrames = 10 N = 0 print("testComputeTime %d" % N); N += 1 gA = tuttle.Graph() gA.createNode( "tuttle.avreader", filename="TuttleOFX-data/video/bars_100.avi", v_colorspace=2 ) print("testComputeTime %d" % N); N += 1 t0 = time.clock() time0 = time.time() print("testComputeTime %d" % N); N += 1 gA.compute( tuttle.ComputeOptions(0, nbFrames) ) t1 = time.clock() time1 = time.time() print("testComputeTime %d" % N); N += 1 rangeCompute_duration = t1-t0 rangeCompute_timeDuration = time1-time0 print("testComputeTime %d" % N); N += 1 gB = tuttle.Graph() gB.createNode( "tuttle.avreader", filename="TuttleOFX-data/video/bars_100.avi", v_colorspace=2 ) print("testComputeTime %d" % N); N += 1 t0 = time.clock() time0 = time.time() print("compute frame by frame") for i in range(0, nbFrames): print("compute frame %d" % i) gB.compute( tuttle.ComputeOptions(i) ) t1 = time.clock() time1 = time.time() print("testComputeTime %d" % N); N += 1 frameByFrameCompute_duration = t1-t0 frameByFrameCompute_timeDuration = time1-time0 print("testComputeTime %d" % N); N += 1 diff = frameByFrameCompute_duration - rangeCompute_duration diffTime = frameByFrameCompute_timeDuration - rangeCompute_timeDuration print("_"*10) print("rangeCompute_duration:", rangeCompute_duration) print("frameByFrameCompute_duration:", frameByFrameCompute_duration) print("diff duration:", diff) print("-"*10) print("rangeCompute_timeDuration:", rangeCompute_timeDuration) print("frameByFrameCompute_timeDuration:", frameByFrameCompute_timeDuration) print("diff time duration:", diffTime) print("_"*10) print("testComputeTime %d" % N); N += 1
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 generate(pluginName, *orderedParams, **namedParams): """ generate an image wrote automaticaly the command line in the center of the image the graph process will be: pluginName -> burn command line -> write orderedParams are pluginName default ordered parameters (HD) namedParams are pluginName parameters (for example: format=HD) """ filename = pluginName + '_' + '_'.join( ['%s_%s' % (key, value) for (key, value) in namedParams.items()]).replace(' ', '_') cmdLine = pluginName + ' ' + ' '.join( ['%s=%s' % (key, value) for (key, value) in namedParams.items()]) graph = tuttle.Graph() generator = graph.createNode(pluginName, *orderedParams, **namedParams) text = graph.createNode("tuttle.text", vAlign="center", bold=1, color=[0.5, 0.5, 0.5, 1.0], text=cmdLine) write = graph.createNode("tuttle.pngwriter", filename=os.path.join(os.environ["DOC_DIR"], "images", filename + ".png")) graph.connect([generator, text, write]) graph.compute(write)
def testFilenameLastWriteTimeChanged(): filepath = NamedTemporaryFile(prefix="localHashTest-", suffix=".png") if os.path.exists(filepath.name): os.remove(filepath.name) g = tuttle.Graph() read_filename = g.createNode("tuttle.pngreader", filename=filepath.name) hash_with_no_file = read_filename.getLocalHashAtTime(0.0) assert_equal(read_filename.getLocalHashAtTime(0.0), read_filename.getLocalHashAtTime(0.0)) open(filepath.name, "w").write("Not empty\n") # Cast to long, because in C++ we see it as a long. last_modification_time = long(os.stat(filepath.name).st_ctime) hash_with_file = read_filename.getLocalHashAtTime(0.0) assert_equal(read_filename.getLocalHashAtTime(0.0), read_filename.getLocalHashAtTime(0.0)) # Modify the timestamp, until the last write time change becames visible i = 0 while last_modification_time == long(os.stat(filepath.name).st_ctime): open(filepath.name, "w").write("Adding data to modify the last wite time: " + str(i) + "\n") i += 1 hash_with_modified_file = read_filename.getLocalHashAtTime(0.0) os.remove(filepath.name) assert_not_equal(hash_with_no_file, hash_with_file) assert_not_equal(hash_with_file, hash_with_modified_file)
def testDeleteUnconnectedNodes(): g = tuttle.Graph() n = [ tuttle.NodeInit( "tuttle.oiioreader", filename="TuttleOFX-data/image/openexr/DisplayWindow/t##.exr" ), tuttle.NodeInit( "tuttle.invert" ), tuttle.NodeInit( "tuttle.timeshift", 12 ), tuttle.NodeInit( "tuttle.gamma", master=.5 ), tuttle.NodeInit( "tuttle.timeshift", 0 ), tuttle.NodeInit( "tuttle.jpegwriter", filename=".tests/fromExr/output-####.jpg" ), ] nodes = g.addConnectedNodes(n) assert_equals(g.getNbNodes(), 6) assert_equals(g.getNbConnections(), 5) g.deleteUnconnectedNodes( nodes[-1] ) assert_equals(g.getNbNodes(), 6) assert_equals(g.getNbConnections(), 5) checkerboard = g.createNode( "tuttle.gamma", master=.5 ).asImageEffectNode() lensdistort = g.createNode( "tuttle.timeshift", 0. ).asImageEffectNode() assert_equals(g.getNbNodes(), 8) assert_equals(g.getNbConnections(), 5) assert_equals(len(g.getUnconnectedNodes(nodes[-1])), 2) assert_equals(len(g.getConnectedNodes(nodes[-1])), 6) g.deleteUnconnectedNodes( nodes[-1] ) assert_equals(g.getNbNodes(), 6) assert_equals(g.getNbConnections(), 5)
def testCompute(): 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, []) print "before compute" outputCache = tuttle.MemoryCache() timeRange = tuttle.TimeRange(1, 16, 10) print "setup" procGraph.setup() print "beginSequence" procGraph.beginSequence(timeRange) for time in xrange(timeRange._begin, timeRange._end, timeRange._step): print "time:", time procGraph.setupAtTime(time) procGraph.processAtTime(outputCache, time) print "endSequence" procGraph.endSequence() print "after compute"
def testMergeWithSameChildrens(): g = tuttle.Graph() read = g.createNode("tuttle.checkerboard", size=[100, 200], explicitConversion="8i") scale = g.createNode("tuttle.swscale", width=150) effect = g.createNode("tuttle.invert") merge = g.createNode("tuttle.merge", offsetA=[150, 0], mergingFunction="copy", rod="union") write = g.createNode("tuttle.invert") # read -> scale -> effect # \ \ # -----------> merge -> write g.connect([read, scale, effect]) g.connect(scale, merge.getAttribute("B")) g.connect(effect, merge.getAttribute("A")) g.connect(merge, write) outputCache = tuttle.MemoryCache() g.compute(outputCache, write, tuttle.ComputeOptions(5)) # We retrieve the output image buffer, and we could read the image size rodMerge = outputCache.get(0).getROD() print(rodMerge.x1, rodMerge.y1, rodMerge.x2, rodMerge.y2) assert rodMerge.x1 == 0 assert rodMerge.y1 == 0 assert rodMerge.x2 == 300 assert rodMerge.y2 == 300
def testNodeComputeInfos(): graph = tuttle.Graph() node = graph.createNode("tuttle.avreader", filename="TuttleOFX-data/video/bars_100.avi", colorspace="bt709").asImageEffectNode() graph.setup() td = node.getTimeDomain() print "node timeDomain: ", td.min, td.max assert td.min == 0.0 assert td.max == 100.0 # Duration is 101, the last frame is included assert_equal((td.max - td.min) + 1, 101.0) framerate = node.getOutputFrameRate() print "framerate: ", framerate assert_equal(framerate, 25.0) pixelAspectRatio = node.getOutputPixelAspectRatio() print "pixel aspect ratio: ", pixelAspectRatio assert_almost_equal(pixelAspectRatio, 16.0 / 15.0) # modify input SAR node.getParam("customSAR").setValue(2.0) graph.setup() pixelAspectRatio = node.getOutputPixelAspectRatio() print "pixel aspect ratio: ", pixelAspectRatio assert_equal(pixelAspectRatio, 2.0)
def testNodeInfos(): graph = tuttle.Graph() print "graph:", graph print "graph.__str__():", graph.__str__() node = graph.createNode("tuttle.lensdistort") node = node.asImageEffectNode() print "plugin: ", node.getName() print "version: ", node.getVersion() print "nbParams: ", node.getNbParams() print "paramSet: ", node.getParamSet() print[p for p in node.getParams()] print[p.getName() for p in node.getParams()] pref = tuttle.Preferences() print dir(pref) testPath = pref.buildTuttleTestPathStr() filenameSimple = os.path.join(testPath, "testNodeInfos_exportDot_simple.dot") filenameDetailed = os.path.join(testPath, "testNodeInfos_exportDot_detailed.dot") graph.exportDot(filenameSimple) graph.exportDot(filenameDetailed, tuttle.Graph.eDotExportLevelDetailed) assert os.path.isfile(filenameSimple) assert os.path.isfile(filenameDetailed) print "filenameSimple:", filenameSimple print "filenameDetailed:", filenameDetailed os.remove(filenameSimple) os.remove(filenameDetailed)
def testExportDot(): graph = tuttle.Graph() read1 = graph.createNode("tuttle.checkerboard", size=[20, 137]).asImageEffectNode() read2 = graph.createNode("tuttle.checkerboard", size=[234, 357]).asImageEffectNode() merge = graph.createNode("tuttle.merge", rod="union").asImageEffectNode() graph.connect(read1, merge.getClip("A")) graph.connect(read2, merge.getClip("B")) pref = tuttle.Preferences() testPath = pref.buildTuttleTestPathStr() filenameSimple = os.path.join(testPath, "testExportDot_simple.dot") filenameDetailed = os.path.join(testPath, "testExportDot_detailed.dot") graph.exportDot(filenameSimple) graph.exportDot(filenameDetailed, tuttle.Graph.eDotExportLevelDetailed) assert os.path.isfile(filenameSimple) assert os.path.isfile(filenameDetailed) print("filenameSimple:", filenameSimple) print("filenameDetailed:", filenameDetailed) os.remove(filenameSimple) os.remove(filenameDetailed)
def testFilenameLastWriteTimeChanged(): tmp_file = NamedTemporaryFile(prefix="localHashTest-", suffix=".png", delete=False) # First hash is computed without the file, # as NamedTemporaryFile creates it, we need to delete it if os.path.exists(tmp_file.name): os.remove(tmp_file.name) g = tuttle.Graph() read_filename = g.createNode("tuttle.pngreader", filename=tmp_file.name) hash_with_no_file = read_filename.getLocalHashAtTime(0.0) # second hash use the file with open(tmp_file.name, "w") as f: f.write("There is something in the file\n") hash_with_file = read_filename.getLocalHashAtTime(0.0) # last hash use a modified timestamp stat = os.stat(tmp_file.name) os.utime(tmp_file.name, (stat.st_atime, stat.st_mtime + 1)) hash_with_modified_file = read_filename.getLocalHashAtTime(0.0) # cleanup os.remove(tmp_file.name) assert_not_equal(hash_with_no_file, hash_with_file) assert_not_equal(hash_with_file, hash_with_modified_file)
def testDoubleParamProps(): print("testDoubleParamProps") g = tuttle.Graph() print("--") checkerNode = g.createNode( "tuttle.checkerboard", size=[50,50] ) sizeParam = checkerNode.getParam("size") ratioParam = checkerNode.getParam("ratio") print("--") print("-- Node props:", checkerNode.getProperties().getSize()) print("-- Node props len:", len(checkerNode.getProperties())) print("-- Node props:", checkerNode.getProperties().getLocalSize()) assert_less(checkerNode.getProperties().getLocalSize(), checkerNode.getProperties().getSize()) for i, p in enumerate(checkerNode.getProperties()): v = p.getStringValues() for vv in v: print(vv) print(i, p.getName(), p.getType()) print(i, p.getName(), p.getType(), [str(vv) for vv in v]) print(i, p.getName(), p.getType(), p.getStringValueAt(0) if p.getDimension() else None) print("--") print("-- Param props:") s = checkerNode.getParam("size") for p in s.getProperties(): v = p.getStringValues() print(p.getName(), p.getType(), [str(vv) for vv in v]) print(p.getName(), p.getType(), p.getStringValues()) print("--")
def check(video, sequence): graph = tuttle.Graph() readSequence = graph.createNode("tuttle.pngreader", filename=os.path.join( os.environ["DOC_DIR"], "images", sequence)) readVideo = graph.createNode("tuttle.avreader", filename=os.path.join(os.environ["DOC_DIR"], "videos", video), colorspace="bt709") diff = graph.createNode("tuttle.diff").asImageEffectNode() graph.connect(readSequence, diff.getClip("SourceA")) graph.connect(readVideo, diff.getClip("SourceB")) graph.setup() #td = diff.getTimeDomain() #assert td.min == 0.0 #assert td.max == 49.0 graph.compute(diff) param = diff.getParam("quality") print("diff = ", param.getDoubleValueAtIndex(0), param.getDoubleValueAtIndex(1), param.getDoubleValueAtIndex(2), param.getDoubleValueAtIndex(3)) assert_equal(0.0, param.getDoubleValueAtIndex(0)) assert_equal(0.0, param.getDoubleValueAtIndex(1)) assert_equal(0.0, param.getDoubleValueAtIndex(2)) assert_equal(0.0, param.getDoubleValueAtIndex(3))
def testGraphMultipleConnections(): """ Multiple connections """ graph = tuttle.Graph() print "graph:", graph checkerboard = graph.createNode("tuttle.checkerboard").asImageEffectNode() merge = graph.createNode("tuttle.merge").asImageEffectNode() mergeClipA = merge.getClip("A") mergeClipB = merge.getClip("B") assert graph.getNbOutputConnections(checkerboard) == 0 graph.connect(checkerboard.getClip("Output"), mergeClipA) assert graph.getNbOutputConnections(checkerboard) == 1 graph.connect(checkerboard.getClip("Output"), mergeClipA) assert graph.getNbOutputConnections(checkerboard) == 1 print "graph:", graph graph.connect(checkerboard.getClip("Output"), mergeClipB) print "graph:", graph
def testInt2DParam(): g = tuttle.Graph() node = g.createNode("tuttle.constant", size=[50, 50]) # set Int2D param values s = node.getParam("size") s.setValue([1, 2]) assert_equal(1, s.getIntValueAtIndex(0)) assert_equal(2, s.getIntValueAtIndex(1)) # Check error cases # not a double param assert_raises(Exception, s.getDoubleValue) # not a string param assert_raises(Exception, s.getStringValue) # not a multidim double param assert_raises(Exception, s.getDoubleValueAtIndex, 0) assert_raises(Exception, s.getDoubleValueAtIndex, 1) # outside dim assert_raises(Exception, s.getIntValueAtIndex, 3) assert_raises(Exception, s.getIntValueAtIndex, 13) # set values at times s.setValue({1.0: [80, 40], 9.0: [0, 0]}) assert_equal(80, s.getIntValueAtTimeAndIndex(1., 0)) assert_equal(40, s.getIntValueAtTimeAndIndex(1., 1)) assert_equal(0, s.getIntValueAtTimeAndIndex(9., 0)) assert_equal(0, s.getIntValueAtTimeAndIndex(9., 1))
def testInputBuffer_MergeInputBufferNodes(): """ Merge an image file (loaded with PIL) with a generated image buffer (created with numpy). """ g = tuttle.Graph() img = numpy.asarray( Image.open('TuttleOFX-data/image/jpeg/MatrixLarge.jpg')) ii = g.createInputBuffer() ii.set3DArrayBuffer(img) # generated numpy array array = numpy.array([[.9, .1, .9], [.8, .2, .9]], numpy.float32) ib = g.createInputBuffer() ib.set2DArrayBuffer(array) c = g.createNode("tuttle.component", to="rgb") m = g.createNode("tuttle.merge", mergingFunction="average", rod="union") filepath = NamedTemporaryFile(prefix="inputBufferWithNumpyTest-", suffix=".png") w = g.createNode("tuttle.pngwriter", filename=filepath.name) g.connect(ib.getNode(), c) g.connect(c, m.getAttribute("A")) g.connect(ii.getNode(), m.getAttribute("B")) g.connect(m, w)
def testDouble2DParam(): g = tuttle.Graph() node = g.createNode("tuttle.blur", size=[12.34, 0.5]) # set Double2D param values s = node.getParam("size") # Check init values assert_equal(12.34, s.getDoubleValueAtIndex(0)) assert_equal(0.5, s.getDoubleValueAtIndex(1)) # Check error cases # not an int param assert_raises(Exception, s.getIntValue) assert_raises(Exception, s.getIntValueAtIndex, 0) assert_raises(Exception, s.getIntValueAtIndex, 1) # not a single value param assert_raises(Exception, s.getDoubleValue) # Simple set value s.setValue([1.5, 25.0]) assert_equal(1.5, s.getDoubleValueAtIndex(0)) assert_equal(25., s.getDoubleValueAtIndex(1)) # check return the same value at all times assert_equal(1.5, s.getDoubleValueAtTimeAndIndex(1., 0)) assert_equal(25., s.getDoubleValueAtTimeAndIndex(1., 1)) # Set at time s.setValue({1.0: [10.5, 40.], 9.0: 0.}) assert_equal(10.5, s.getDoubleValueAtTimeAndIndex(1., 0)) assert_equal(40., s.getDoubleValueAtTimeAndIndex(1., 1)) assert_equal(0., s.getDoubleValueAtTimeAndIndex(9., 0)) assert_equal(0., s.getDoubleValueAtTimeAndIndex(9., 1)) # Check interpolation m = s.getDoubleValueAtTimeAndIndex(3., 0) assert_greater(m, 0.) assert_less(m, 10.5) # Check outside ranges assert_equal(10.5, s.getDoubleValueAtTimeAndIndex(-5., 0)) assert_equal(0.0, s.getDoubleValueAtTimeAndIndex(20., 0)) assert_equal(40.0, s.getDoubleValueAtTimeAndIndex(-5., 1)) assert_equal(0.0, s.getDoubleValueAtTimeAndIndex(20., 1)) # Set integers to double (auto conversion) s.setValue([1, 25]) assert_equal(1., s.getDoubleValueAtIndex(0)) assert_equal(25., s.getDoubleValueAtIndex(1)) # check return the same value at all times assert_equal(1., s.getDoubleValueAtTimeAndIndex(1., 0)) assert_equal(25., s.getDoubleValueAtTimeAndIndex(1., 1)) # mix double and integers (auto conversion) s.setValue([1.345, 25]) assert_equal(1.345, s.getDoubleValueAtIndex(0)) assert_equal(25., s.getDoubleValueAtIndex(1))
def testCheckerBlurWrite(): g = tuttle.Graph() read = g.createNode("tuttle.checkerboard", size=[20, 20]) blur = g.createNode("tuttle.blur", size=[0.03, 0.05]) write = g.createNode("tuttle.pngwriter", filename=".tests/output.png") g.connect([read, blur, write]) g.compute(write)
def testPushButton(): graph = tuttle.Graph() node = graph.createNode("tuttle.ffmpegwriter", filename=".tests/plop.avi") node = node.asImageEffectNode() render = node.getParam("render") # the user click on the PushButton render.paramChanged(tuttle.eChangeUserEdited)
def testThreadEnv(): g = tuttle.Graph() pngRead = g.createNode("tuttle.checkerboard", size=[50, 50]) blur = g.createNode('tuttle.blur') pngW = g.createNode('tuttle.pngwriter', ".tests/output-###.png") g.connect([pngRead, blur, pngW]) env = tuttle.ThreadEnv() env.compute(g, pngW) env.join()
def testMultipleCompute_renderSomeFrames(): g = tuttle.Graph() checkerboard = g.createNode("tuttle.checkerboard", size=[50, 50]) invert = g.createNode("tuttle.invert") write = g.createNode("tuttle.pngwriter", filename=".tests/output.png") g.connect([checkerboard, invert, write]) assert g.compute(write, tuttle.ComputeOptions(0)) assert g.compute(write, tuttle.ComputeOptions(5)) assert g.compute(write, tuttle.ComputeOptions(0))
def generate( prefix, number_of_frames ): """ Generate a sequence test with number_of_frames frames, burned with the frame index the sequence will be placed in the documentation directory (DOC_DIR) and the sequence will named: DOC_DIR/images/prefix#####.png """ for i in range( number_of_frames ): graph = tuttle.Graph() text = graph.createNode( "tuttle.text", vAlign="center", bold=1, color=[1,1,1,1], format="PAL", textSize=50, text=str(i) ) write = graph.createNode( "tuttle.pngwriter", filename=os.path.join( os.environ["DOC_DIR"], "images", prefix + str(i).zfill(5) + ".png" ) ) graph.connect( [text, write] ) graph.compute( write ) for i in range( number_of_frames ): graph = tuttle.Graph() text = graph.createNode( "tuttle.text", vAlign="center", bold=1, color=[1,1,1,1], format="HD", textSize=50, text=str(i) ) write = graph.createNode( "tuttle.pngwriter", filename=os.path.join( os.environ["DOC_DIR"], "images", prefix + "hd_" + str(i).zfill(5) + ".png" ) ) graph.connect( [text, write] ) graph.compute( write )
def testGraphAlreadyConnected(): """ Connect twice... """ graph = tuttle.Graph() checkerboard = graph.createNode("tuttle.checkerboard").asImageEffectNode() merge = graph.createNode("tuttle.merge").asImageEffectNode() graph.connect(checkerboard.getClip("Output"), merge.getClip("A")) assert_raises(Exception, graph.connect, checkerboard.getClip("Output"), merge.getClip("A"))
def __init__(self): self._graphTuttle = tuttle.Graph() self._nodes = [] self._connections = [] # signals self.nodesChanged = Signal() self.connectionsChanged = Signal() self.connectionsCoordChanged = Signal() logging.info("Core : Graph created")