def testTileHashes( self ) : # Test that two tiles within the image have the same hash. e = GafferImage.Empty() e["format"].setValue( GafferImage.Format( 2048, 1156, 1. ) ) self.assertEqual( e["out"].channelDataHash( "R", imath.V2i( 0 ) ), e["out"].channelDataHash( "R", imath.V2i( GafferImage.ImagePlug().tileSize() ) ), ) self.assertEqual( e["out"].sampleOffsetsHash( imath.V2i( 0 ) ), e["out"].sampleOffsetsHash( imath.V2i( GafferImage.ImagePlug().tileSize() ) ), )
def testIterationsContext(self): script = Gaffer.ScriptNode() script["c"] = GafferImage.Constant() script["loop"] = Gaffer.Loop() script["loop"].setup(GafferImage.ImagePlug()) script["loop"]["in"].setInput(script["c"]["out"]) script["grade"] = GafferImage.Grade() script["grade"]["offset"].setValue(imath.Color3f(.1)) script["grade"]["in"].setInput(script["loop"]["previous"]) script["loop"]["next"].setInput(script["grade"]["out"]) script["sampler"] = GafferImage.ImageSampler() script["sampler"]["pixel"].setValue(imath.V2f(10)) script["sampler"]["image"].setInput(script["loop"]["out"]) script["expression"] = Gaffer.Expression() script["expression"].setExpression( inspect.cleandoc(""" assert( context.get( "image:channelName", None ) is None ) assert( context.get( "image:tileOrigin", None ) is None ) parent["loop"]["iterations"] = 4 """)) with script.context(): self.assertAlmostEqual(script["sampler"]["color"]["r"].getValue(), .4)
def testSwitching(self): in0 = GafferImage.Constant() in0["format"].setValue(GafferImage.Format(100, 100, 1.0)) in0["color"].setValue(imath.Color4f(1, 0, 0, 1)) in1 = GafferImage.Constant() in1["format"].setValue(GafferImage.Format(100, 100, 1.0)) in0["color"].setValue(imath.Color4f(0, 1, 0, 1)) switch = Gaffer.Switch() switch.setup(GafferImage.ImagePlug()) switch["in"][0].setInput(in0["out"]) switch["in"][1].setInput(in1["out"]) self.assertImageHashesEqual(switch["out"], in0["out"]) self.assertImagesEqual(switch["out"], in0["out"]) switch["index"].setValue(1) self.assertImageHashesEqual(switch["out"], in1["out"]) self.assertImagesEqual(switch["out"], in1["out"]) switch["enabled"].setValue(False) self.assertImageHashesEqual(switch["out"], in0["out"]) self.assertImagesEqual(switch["out"], in0["out"])
def testEnabledPlug(self): s = Gaffer.Switch() s.setup(GafferImage.ImagePlug()) self.assertTrue(isinstance(s["enabled"], Gaffer.BoolPlug)) self.assertTrue(s["enabled"].isSame(s.enabledPlug())) self.assertFalse("enabled1" in s)
def testTileSize(self): n = GafferImage.ImageReader() n["fileName"].setValue(self.fileName) tile = n["out"].channelData("R", IECore.V2i(0)) self.assertEqual(len(tile), GafferImage.ImagePlug().tileSize()**2)
def testTimeWarping(self): script = Gaffer.ScriptNode() script["constant"] = GafferImage.Constant() script["expression"] = Gaffer.Expression() script["expression"].setExpression( 'parent["constant"]["color"]["r"] = context["frame"]') script["timeWarp"] = Gaffer.TimeWarp() script["timeWarp"].setup(GafferImage.ImagePlug()) script["timeWarp"]["offset"].setValue(1) script["timeWarp"]["in"].setInput(script["constant"]["out"]) for f in range(0, 10): with script.context(): script.context().setFrame(f) c0 = script["constant"]["out"].image() c0Hash = script["constant"]["out"].imageHash() t = script["timeWarp"]["out"].image() tHash = script["timeWarp"]["out"].imageHash() script.context().setFrame(f + 1) c1 = script["constant"]["out"].image() c1Hash = script["constant"]["out"].imageHash() self.assertEqual(c1, t) self.assertEqual(c1Hash, tHash) self.assertNotEqual(c0, c1) self.assertNotEqual(c0Hash, c1Hash)
def testBlurRange( self ): constant = GafferImage.Constant() constant["format"].setValue( GafferImage.Format( 5, 5, 1.000 ) ) constant["color"].setValue( IECore.Color4f( 1, 1, 1, 1 ) ) cropDot = GafferImage.Crop() cropDot["area"].setValue( IECore.Box2i( IECore.V2i( 2, 2 ), IECore.V2i( 3, 3 ) ) ) cropDot["affectDisplayWindow"].setValue( False ) cropDot["in"].setInput( constant["out"] ) blur = GafferImage.Blur() blur["expandDataWindow"].setValue( True ) blur["in"].setInput( cropDot["out"] ) blur["radius"]["y"].setInput( blur["radius"]["x"] ) expression = Gaffer.Expression() blur.addChild( expression ) expression.setExpression( 'parent["radius"]["x"] = context[ "loop:index" ] * 0.2', "python" ) loopInit = GafferImage.Constant() loopInit["format"].setValue( GafferImage.Format( 5, 5, 1.000 ) ) imageLoop = GafferImage.ImageLoop() imageLoop["in"].setInput( loopInit["out"] ) merge = GafferImage.Merge() merge["in"].addChild( GafferImage.ImagePlug( "in2", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, ) ) merge["in"]["in0"].setInput( blur["out"] ) merge["in"]["in1"].setInput( imageLoop["previous"] ) offset = GafferImage.Offset() offset["offset"].setValue( IECore.V2i( -5, 0 ) ) offset["in"].setInput( merge["out"] ) imageLoop["next"].setInput( offset["out"] ) deleteChannels = GafferImage.DeleteChannels() deleteChannels["mode"].setValue( GafferImage.DeleteChannels.Mode.Keep ) deleteChannels["channels"].setValue( IECore.StringVectorData( [ 'R' ] ) ) deleteChannels["in"].setInput( imageLoop["out"] ) finalCrop = GafferImage.Crop() finalCrop["areaSource"].setValue( 1 ) finalCrop["in"].setInput( deleteChannels["out"] ) # Enable to write out images for visual comparison if False: testWriter = GafferImage.ImageWriter() testWriter["in"].setInput( finalCrop["out"] ) testWriter["fileName"].setValue( "/tmp/blurRange.exr" ) testWriter["openexr"]["dataType"].setValue( 'float' ) testWriter["task"].execute() expectedReader = GafferImage.ImageReader() expectedReader["fileName"].setValue( os.path.dirname( __file__ ) + "/images/blurRange.exr" ) self.assertImagesEqual( finalCrop["out"], expectedReader["out"], maxDifference = 0.00001, ignoreMetadata = True )
def testEnabledPlug(self): t = Gaffer.TimeWarp() t.setup(GafferImage.ImagePlug()) self.assertTrue(isinstance(t["enabled"], Gaffer.BoolPlug)) self.assertTrue(t["enabled"].isSame(t.enabledPlug())) self.assertFalse("enabled1" in t)
def testAffects(self): timeWarp = Gaffer.TimeWarp() timeWarp.setup(GafferImage.ImagePlug()) for n in [ "format", "dataWindow", "metadata", "channelNames", "channelData" ]: a = timeWarp.affects(timeWarp["in"][n]) self.assertEqual(len(a), 1) self.assertTrue(a[0].isSame(timeWarp["out"][n])) for n in ["enabled", "offset", "speed"]: a = set([ plug.relativeName(plug.node()) for plug in timeWarp.affects(timeWarp[n]) ]) self.assertEqual( a, set([ "out.format", "out.dataWindow", "out.metadata", "out.channelNames", "out.channelData", ]), )
def testAcceptsInput(self): w = GafferImage.ImageWriter() p = GafferImage.ImagePlug(direction=Gaffer.Plug.Direction.Out) self.failIf(w['requirements']['requirement0'].acceptsInput(p)) self.failUnless(w["in"].acceptsInput(p))
def testTimeContext(self): script = Gaffer.ScriptNode() script["constant"] = GafferImage.Constant() script["constant"]["format"].setValue(GafferImage.Format(1, 1, 1.0)) script["e"] = Gaffer.Expression() script["e"].setExpression( 'parent["constant"]["color"] = imath.Color4f( context["frame"] )') script["timeWarp"] = Gaffer.TimeWarp() script["timeWarp"].setup(GafferImage.ImagePlug()) script["timeWarp"]["in"].setInput(script["constant"]["out"]) script["timeWarp"]["speed"].setValue(0) script["timeWarp"]["offset"].setValue(3) script["sampler"] = GafferImage.ImageSampler() script["sampler"]["pixel"].setValue(imath.V2f(0.5, 0.5)) script["sampler"]["image"].setInput(script["timeWarp"]["out"]) self.assertEqual(script["sampler"]["color"].getValue(), imath.Color4f(3)) script["e2"] = Gaffer.Expression() script["e2"].setExpression( inspect.cleandoc(""" assert( context.get( "image:channelName", None ) is None ) assert( context.get( "image:tileOrigin", None ) is None ) parent["timeWarp"]["offset"] = 5 """)) self.assertEqual(script["sampler"]["color"].getValue(), imath.Color4f(5))
def testAcceptsInput( self ) : w = GafferImage.ImageWriter() p = GafferImage.ImagePlug( direction = Gaffer.Plug.Direction.Out ) self.failIf( w["preTasks"][0].acceptsInput( p ) ) self.failUnless( w["in"].acceptsInput( p ) )
def testTileNotAvailableInContextExpressions(self): # We don't want expressions on the index to be sensitive # to the image:tileOrigin or image:channelName context entries, # because then an invalid image could result from splicing together # different images, even requesting tiles outside the data window. script = Gaffer.ScriptNode() script["switch"] = Gaffer.Switch() script["switch"].setup(GafferImage.ImagePlug()) script["in0"] = GafferImage.Constant() script["in0"]["color"].setValue(imath.Color4f(1, 1, 1, 1)) script["in1"] = GafferImage.Constant() script["in0"]["color"].setValue(imath.Color4f(0, 0, 0, 0)) script["switch"]["in"][0].setInput(script["in0"]["out"]) script["switch"]["in"][1].setInput(script["in1"]["out"]) script["expression"] = Gaffer.Expression() script["expression"].setExpression( inspect.cleandoc(""" assert( context.get( "image:channelName", None ) is None ) assert( context.get( "image:tileOrigin", None ) is None ) parent["switch"]["index"] = 1 """)) self.assertEqual( script["switch"]["out"].channelData("R", imath.V2i(0))[0], 0)
def testChannelDataHashes( self ) : # Test that two tiles within the same image have different hashes. n = GafferImage.ImageReader() n["fileName"].setValue( self.fileName ) h1 = n["out"].channelData( "R", imath.V2i( 0 ) ).hash() h2 = n["out"].channelData( "R", imath.V2i( GafferImage.ImagePlug().tileSize() ) ).hash() self.assertNotEqual( h1, h2 )
def testCreateCounterpart( self ) : p = GafferImage.ImagePlug() p2 = p.createCounterpart( "a", Gaffer.Plug.Direction.Out ) self.assertEqual( p2.getName(), "a" ) self.assertEqual( p2.direction(), Gaffer.Plug.Direction.Out ) self.assertEqual( p2.getFlags(), p.getFlags() )
def testDisabledChannelDataHashes( self ) : # Test that two tiles within the same image have the same hash when disabled. n = GafferImage.OpenImageIOReader() n["fileName"].setValue( self.fileName ) n["enabled"].setValue( False ) h1 = n["out"].channelData( "R", imath.V2i( 0 ) ).hash() h2 = n["out"].channelData( "R", imath.V2i( GafferImage.ImagePlug().tileSize() ) ).hash() self.assertEqual( h1, h2 )
def testTileHashes(self): # Test that two tiles within the image have the same hash. c = GafferImage.Constant() c["format"].setValue(GafferImage.Format(2048, 1156, 1.)) c["color"][0].setValue(.5) h1 = c["out"].channelData("R", IECore.V2i(0)).hash() h2 = c["out"].channelData( "R", IECore.V2i(GafferImage.ImagePlug().tileSize())).hash() self.assertEqual(h1, h2)
def testChannelDataHashes( self ) : # Create a grade node and save the hash of a tile from each channel. i = GafferImage.ImageReader() i["fileName"].setValue( self.checkerFile ) grade = GafferImage.Grade() grade["in"].setInput(i["out"]) grade["gain"].setValue( IECore.Color3f( 2., 2., 2. ) ) h1 = grade["out"].channelData( "R", IECore.V2i( 0 ) ).hash() h2 = grade["out"].channelData( "R", IECore.V2i( GafferImage.ImagePlug().tileSize() ) ).hash() self.assertNotEqual( h1, h2 ) # Test that two tiles within the same image have the same hash when disabled. grade["enabled"].setValue(False) h1 = grade["out"].channelData( "R", IECore.V2i( 0 ) ).hash() h2 = grade["out"].channelData( "R", IECore.V2i( GafferImage.ImagePlug().tileSize() ) ).hash() self.assertNotEqual( h1, h2 )
def testAffects(self): in0 = GafferImage.Constant() in1 = GafferImage.Constant() switch = Gaffer.Switch() switch.setup(GafferImage.ImagePlug()) switch["in"][0].setInput(in0["out"]) switch["in"][1].setInput(in1["out"]) add = GafferTest.AddNode() switch["index"].setInput(add["sum"]) for p in [switch["in"][0], switch["in"][1]]: for n in [ "format", "dataWindow", "metadata", "deep", "sampleOffsets", "channelNames", "channelData" ]: a = switch.affects(p[n]) self.assertEqual(len(a), 1) self.assertTrue(a[0].isSame(switch["out"][n])) a = set([ plug.relativeName(plug.node()) for plug in switch.affects(switch["enabled"]) ]) self.assertEqual( a, set([ "out.format", "out.dataWindow", "out.metadata", "out.deep", "out.sampleOffsets", "out.channelNames", "out.channelData", ]), ) a = set([ plug.relativeName(plug.node()) for plug in switch.affects(switch["index"]) ]) self.assertEqual( a, set([ "out.format", "out.dataWindow", "out.metadata", "out.deep", "out.sampleOffsets", "out.channelNames", "out.channelData", ]), )
def testDynamicSerialisation( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() s["n"]["p"] = GafferImage.ImagePlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ss = s.serialise() s = Gaffer.ScriptNode() s.execute( ss ) self.assertTrue( isinstance( s["n"]["p"], GafferImage.ImagePlug ) ) self.assertEqual( s["n"]["p"].getFlags(), Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic )
def __init__( self, viewedPlug = None ) : GafferImageUI.ImageView.__init__( self, "MyView" ) converter = Gaffer.Node() converter["in"] = Gaffer.StringPlug() converter["out"] = GafferImage.ImagePlug( direction = Gaffer.Plug.Direction.Out ) converter["text"] = GafferImage.Text() converter["text"]["text"].setInput( converter["in"] ) converter["out"].setInput( converter["text"]["out"] ) self._insertConverter( converter ) self["in"].setInput( viewedPlug )
def __init__( self, viewedPlug = None ) : GafferImageUI.ImageView.__init__( self, "MyView" ) converter = Gaffer.Node() converter["in"] = Gaffer.ObjectPlug( defaultValue = IECore.NullObject.defaultNullObject() ) converter["out"] = GafferImage.ImagePlug( direction = Gaffer.Plug.Direction.Out ) converter["constant"] = GafferImage.Constant() converter["constant"]["format"].setValue( GafferImage.Format( 20, 20, 1 ) ) converter["out"].setInput( converter["constant"]["out"] ) self._insertConverter( converter ) self["in"].setInput( viewedPlug )
def testDefaultFormat(self): s = Gaffer.ScriptNode() d = GafferImage.Display() s.addChild(d) p = GafferImage.ImagePlug("in", Gaffer.Plug.Direction.In) p.setInput(d["out"]) with s.context(): self.assertEqual(p["format"].getValue(), GafferImage.Format.getDefaultFormat(s)) GafferImage.Format.setDefaultFormat( s, GafferImage.Format(200, 150, 1.)) self.assertEqual(p["format"].getValue(), GafferImage.Format.getDefaultFormat(s))
def testSerialisation(self): script = Gaffer.ScriptNode() script["switch"] = Gaffer.Switch() script["switch"].setup(GafferImage.ImagePlug()) script["in0"] = GafferImage.Constant() script["in1"] = GafferImage.Constant() script["switch"]["in"][0].setInput(script["in0"]["out"]) script["switch"]["in"][1].setInput(script["in1"]["out"]) script2 = Gaffer.ScriptNode() script2.execute(script.serialise()) self.assertTrue(script2["switch"]["in"][0].getInput().isSame( script2["in0"]["out"])) self.assertTrue(script2["switch"]["in"][1].getInput().isSame( script2["in1"]["out"])) self.assertTrue(script2["switch"]["in"][2].getInput() is None)
def testDefaultFormatChanged( self ) : # Create a grade node and check that the format changes if it is unconnected. n = GafferImage.Grade() s = Gaffer.ScriptNode() s.addChild( n ) p = GafferImage.ImagePlug( "test", GafferImage.ImagePlug.Direction.In ) p.setInput( n["out"] ) with s.context() : f1 = p["format"].getValue() # Change the default format. GafferImage.Format.registerFormat( self.__testFormatValue(), self.__testFormatName() ) GafferImage.Format.setDefaultFormat( s, self.__testFormatValue() ) # Check that the hash has changed. f2 = p["format"].getValue() self.assertNotEqual( f1, f2 )
def testLoop(self): script = Gaffer.ScriptNode() script["c"] = GafferImage.Constant() script["loop"] = Gaffer.Loop() script["loop"].setup(GafferImage.ImagePlug()) script["loop"]["in"].setInput(script["c"]["out"]) script["grade"] = GafferImage.Grade() script["grade"]["offset"].setValue(imath.Color3f(.1)) script["grade"]["in"].setInput(script["loop"]["previous"]) script["loop"]["next"].setInput(script["grade"]["out"]) script["sampler"] = GafferImage.ImageSampler() script["sampler"]["pixel"].setValue(imath.V2f(10)) script["sampler"]["image"].setInput(script["loop"]["out"]) with script.context(): script["loop"]["iterations"].setValue(2) self.assertAlmostEqual(script["sampler"]["color"]["r"].getValue(), .2) script["loop"]["iterations"].setValue(4) self.assertAlmostEqual(script["sampler"]["color"]["r"].getValue(), .4) script2 = Gaffer.ScriptNode() script2.execute(script.serialise()) with script2.context(): script2["loop"]["iterations"].setValue(3) self.assertAlmostEqual(script2["sampler"]["color"]["r"].getValue(), .3) script2["loop"]["iterations"].setValue(5) self.assertAlmostEqual(script2["sampler"]["color"]["r"].getValue(), .5)
def __init__(self, viewedPlug=None): GafferImageUI.ImageView.__init__( self, "MyView", Gaffer.ObjectPlug( "in", defaultValue=IECore.NullObject.defaultNullObject())) self["in"].setInput(viewedPlug) self.__preprocessor = Gaffer.Node() self.__preprocessor["in"] = Gaffer.ObjectPlug( defaultValue=IECore.NullObject.defaultNullObject()) self.__preprocessor["out"] = GafferImage.ImagePlug( direction=Gaffer.Plug.Direction.Out) self.__preprocessor["constant"] = GafferImage.Constant() self.__preprocessor["constant"]["format"].setValue( GafferImage.Format(20, 20, 1)) self.__preprocessor["out"].setInput( self.__preprocessor["constant"]["out"]) self._setPreprocessor(self.__preprocessor)
def testDisabling(self): script = Gaffer.ScriptNode() script["constant"] = GafferImage.Constant() script["expression"] = Gaffer.Expression() script["expression"].setExpression( 'parent["constant"]["color"]["r"] = context["frame"]') script["timeWarp"] = Gaffer.TimeWarp() script["timeWarp"].setup(GafferImage.ImagePlug()) script["timeWarp"]["offset"].setValue(1) script["timeWarp"]["in"].setInput(script["constant"]["out"]) with script.context(): c = script["constant"]["out"].image() cHash = script["constant"]["out"].imageHash() t = script["timeWarp"]["out"].image() tHash = script["timeWarp"]["out"].imageHash() self.assertNotEqual(c, t) self.assertNotEqual(cHash, tHash) script["timeWarp"]["enabled"].setValue(False) with script.context(): c = script["constant"]["out"].image() cHash = script["constant"]["out"].imageHash() t = script["timeWarp"]["out"].image() tHash = script["timeWarp"]["out"].imageHash() self.assertEqual(c, t) self.assertEqual(cHash, tHash)
def testDefaultChannelNamesMethod( self ) : channelNames = GafferImage.ImagePlug()['channelNames'].defaultValue() self.assertTrue( 'R' in channelNames ) self.assertTrue( 'G' in channelNames ) self.assertTrue( 'B' in channelNames )
def testManyImages(self): allFilter = GafferScene.PathFilter() allFilter["paths"].setValue(IECore.StringVectorData(['/...'])) sphere = GafferScene.Sphere() sphere["transform"]["translate"].setValue(imath.V3f(-3, 0, 0)) standardSurface = GafferArnold.ArnoldShader() standardSurface.loadShader("standard_surface") shaderAssignment = GafferScene.ShaderAssignment() shaderAssignment["in"].setInput(sphere["out"]) shaderAssignment["filter"].setInput(allFilter["out"]) shaderAssignment["shader"].setInput(standardSurface["out"]) uvScaleCode = GafferOSL.OSLCode() uvScaleCode["out"].addChild( Gaffer.V3fPlug("uvScaled", direction=Gaffer.Plug.Direction.Out)) uvScaleCode["code"].setValue('uvScaled = vector( u * 2, v * 2, 0 );') outUV = GafferOSL.OSLShader() outUV.loadShader("ObjectProcessing/OutUV") outUV["parameters"]["value"].setInput(uvScaleCode["out"]["uvScaled"]) outObject2 = GafferOSL.OSLShader() outObject2.loadShader("ObjectProcessing/OutObject") outObject2["parameters"]["in0"].setInput( outUV["out"]["primitiveVariable"]) uvScaleOSL = GafferOSL.OSLObject() uvScaleOSL["in"].setInput(shaderAssignment["out"]) uvScaleOSL["filter"].setInput(allFilter["out"]) uvScaleOSL["shader"].setInput(outObject2["out"]) uvScaleOSL["interpolation"].setValue(5) mapOffset = GafferScene.MapOffset() mapOffset["in"].setInput(uvScaleOSL["out"]) mapOffset["filter"].setInput(allFilter["out"]) mapOffset["udim"].setValue(1033) offsetGroup = GafferScene.Group() offsetGroup["in"]["in0"].setInput(mapOffset["out"]) offsetGroup["name"].setValue('offset') offsetGroup["transform"]["translate"].setValue(imath.V3f(6, 0, 3)) combineGroup = GafferScene.Group() combineGroup["in"]["in0"].setInput(uvScaleOSL["out"]) combineGroup["in"]["in1"].setInput(offsetGroup["out"]) lights = [] for color, rotate in [((1, 0, 0), (0, 0, 0)), ((0, 1, 0), (0, 90, 0)), ((0, 0, 1), (-90, 0, 0))]: light = GafferArnold.ArnoldLight() light.loadShader("distant_light") light["parameters"]["color"].setValue(imath.Color3f(*color)) light["transform"]["rotate"].setValue(imath.V3f(*rotate)) combineGroup["in"][-1].setInput(light["out"]) lights.append(light) arnoldTextureBake = GafferArnold.ArnoldTextureBake() arnoldTextureBake["in"].setInput(combineGroup["out"]) arnoldTextureBake["filter"].setInput(allFilter["out"]) arnoldTextureBake["bakeDirectory"].setValue(self.temporaryDirectory() + '/bakeSpheres/') arnoldTextureBake["defaultResolution"].setValue(32) arnoldTextureBake["aovs"].setValue('beauty:RGBA diffuse:diffuse') arnoldTextureBake["tasks"].setValue(3) arnoldTextureBake["cleanupIntermediateFiles"].setValue(True) # Dispatch the bake script = Gaffer.ScriptNode() script.addChild(arnoldTextureBake) dispatcher = GafferDispatch.LocalDispatcher() dispatcher["jobsDirectory"].setValue(self.temporaryDirectory()) dispatcher.dispatch([arnoldTextureBake]) # Test that we are writing all expected files, and that we have cleaned up all temp files expectedUdims = [i + j for j in [1001, 1033] for i in [0, 1, 10, 11]] self.assertEqual( sorted(os.listdir(self.temporaryDirectory() + '/bakeSpheres/')), ["beauty", "diffuse"]) self.assertEqual( sorted( os.listdir(self.temporaryDirectory() + '/bakeSpheres/beauty')), ["beauty.%i.tx" % i for i in expectedUdims]) self.assertEqual( sorted( os.listdir(self.temporaryDirectory() + '/bakeSpheres/diffuse')), ["diffuse.%i.tx" % i for i in expectedUdims]) # Read back in the 4 udim tiles of a sphere reader = GafferImage.ImageReader() imageTransform = GafferImage.ImageTransform() imageTransform["in"].setInput(reader["out"]) exprBox = Gaffer.Box() expression = Gaffer.Expression() exprBox.addChild(reader) exprBox.addChild(imageTransform) exprBox.addChild(expression) expression.setExpression( inspect.cleandoc( """ i = context.get( "loop:index", 0 ) layer = context.get( "collect:layerName", "beauty" ) x = i % 2 y = i / 2 parent["ImageReader"]["fileName"] = '""" + self.temporaryDirectory() + """/bakeSpheres/%s/%s.%i.tx' % ( layer, layer, 1001 + x + y * 10 ) parent["ImageTransform"]["transform"]["translate"] = imath.V2f( 32 * x, 32 * y ) """), "python") udimLoop = Gaffer.Loop() udimLoop.setup(GafferImage.ImagePlug()) udimLoop["iterations"].setValue(4) udimMerge = GafferImage.Merge() udimMerge["in"]["in0"].setInput(imageTransform["out"]) udimMerge["in"]["in1"].setInput(udimLoop["previous"]) udimLoop["next"].setInput(udimMerge["out"]) aovCollect = GafferImage.CollectImages() aovCollect["in"].setInput(udimLoop["out"]) aovCollect["rootLayers"].setValue( IECore.StringVectorData(['beauty', 'diffuse'])) # We have a little reference image for how the diffuse should look imageReaderRef = GafferImage.ImageReader() imageReaderRef["fileName"].setValue( os.path.dirname(__file__) + "/images/sphereLightBake.exr") resizeRef = GafferImage.Resize() resizeRef["in"].setInput(imageReaderRef["out"]) resizeRef["format"].setValue(GafferImage.Format(64, 64, 1.000)) shuffleRef = GafferImage.Shuffle() shuffleRef["in"].setInput(resizeRef["out"]) for layer in ["beauty", "diffuse"]: for channel in ["R", "G", "B"]: shuffleRef["channels"].addChild( GafferImage.Shuffle.ChannelPlug()) shuffleRef["channels"][-1]["in"].setValue(channel) shuffleRef["channels"][-1]["out"].setValue(layer + "." + channel) differenceMerge = GafferImage.Merge() differenceMerge["in"]["in0"].setInput(aovCollect["out"]) differenceMerge["in"]["in1"].setInput(shuffleRef["out"]) differenceMerge["operation"].setValue( GafferImage.Merge.Operation.Difference) stats = GafferImage.ImageStats() stats["in"].setInput(differenceMerge["out"]) stats["area"].setValue(imath.Box2i(imath.V2i(0, 0), imath.V2i(64, 64))) # We should get a very close match to our single tile low res reference bake stats["channels"].setValue( IECore.StringVectorData( ['diffuse.R', 'diffuse.G', 'diffuse.B', 'diffuse.A'])) for i in range(3): self.assertLess(stats["average"].getValue()[i], 0.002) self.assertLess(stats["max"].getValue()[i], 0.02) # The beauty should be mostly a close match, but with a high max difference due to the spec pings stats["channels"].setValue( IECore.StringVectorData( ['beauty.R', 'beauty.G', 'beauty.B', 'beauty.A'])) for i in range(3): self.assertLess(stats["average"].getValue()[i], 0.1) self.assertGreater(stats["max"].getValue()[i], 0.3)