def testSimpleLayers(self): expected = GafferImage.ImageReader() expected["fileName"].setValue(self.layersPath) constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(10, 10, 1.000)) constant["color"].setValue(IECore.Color4f(1, 0, 0, 1)) crop = GafferImage.Crop() crop["affectDisplayWindow"].setValue(False) crop["in"].setInput(constant["out"]) delete = GafferImage.DeleteChannels() delete["channels"].setValue("A") delete["in"].setInput(crop["out"]) collect = GafferImage.CollectImages() collect["rootLayers"].setValue(IECore.StringVectorData(['0', '1', '2'])) collect["in"].setInput(delete["out"]) e = Gaffer.Expression() crop.addChild(e) e.setExpression( inspect.cleandoc(""" layer = context.get( "collect:layerName", None ) if layer: o = IECore.V2i(2, 2 ) * ( 1 + int( layer ) ) area = IECore.Box2i( o, IECore.V2i( 1, 1 ) + o ) else: area = IECore.Box2i( IECore.V2i( 3, 1 ), IECore.V2i( 4, 2 ) ) parent["area"] = area """), "python") copyChannels = GafferImage.CopyChannels() copyChannels["channels"].setValue("*") copyChannels["in"][0].setInput(crop["out"]) copyChannels["in"][1].setInput(collect["out"]) self.assertImagesEqual(copyChannels["out"], expected["out"], ignoreMetadata=True)
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)
def testLayerMapping(self): constant1 = GafferImage.Constant() constant1['color'].setValue(IECore.Color4f(0.1, 0.2, 0.3, 0.4)) constant1["format"].setValue(GafferImage.Format(10, 10, 1.000)) metadata1 = GafferImage.ImageMetadata() metadata1["in"].setInput(constant1["out"]) metadata1["metadata"].addMember("test", 1) constant2 = GafferImage.Constant() constant2['color'].setValue(IECore.Color4f(0.2, 0.4, 0.6, 0.8)) constant2["format"].setValue(GafferImage.Format(20, 20, 1.000)) metadata2 = GafferImage.ImageMetadata() metadata2["in"].setInput(constant2["out"]) metadata2["metadata"].addMember("test", 2) switch = GafferImage.ImageSwitch() switch["in"][0].setInput(metadata1["out"]) switch["in"][1].setInput(metadata2["out"]) e = Gaffer.Expression() switch.addChild(e) e.setExpression( 'parent["index"] = context["collect:layerName"] != "A"', "python") collect = GafferImage.CollectImages() collect["in"].setInput(switch["out"]) # Metadata and format are driven by the first layer collect["rootLayers"].setValue(IECore.StringVectorData(['A', 'B'])) self.assertEqual(collect["out"]["format"].getValue(), GafferImage.Format(10, 10, 1)) self.assertEqual(collect["out"]["metadata"].getValue(), IECore.CompoundData({"test": 1})) collect["rootLayers"].setValue(IECore.StringVectorData(['B', 'A'])) self.assertEqual(collect["out"]["format"].getValue(), GafferImage.Format(20, 20, 1)) self.assertEqual(collect["out"]["metadata"].getValue(), IECore.CompoundData({"test": 2})) collect["rootLayers"].setValue(IECore.StringVectorData([])) self.assertEqual( collect["out"]["format"].getValue(), constant1["format"].getDefaultFormat(Gaffer.Context.current())) self.assertEqual(collect["out"]["metadata"].getValue(), IECore.CompoundData()) sampler = GafferImage.ImageSampler("ImageSampler") sampler["pixel"].setValue(IECore.V2f(1, 1)) sampler["channels"].setValue( IECore.StringVectorData(["A.R", "A.G", "A.B", "A.A"])) sampler["image"].setInput(collect["out"]) collect["rootLayers"].setValue(IECore.StringVectorData(['A'])) self.assertEqual(list(collect["out"]["channelNames"].getValue()), ["A.R", "A.G", "A.B", "A.A"]) self.assertEqual(sampler["color"].getValue(), IECore.Color4f(0.1, 0.2, 0.3, 0.4)) # Test simple duplicate collect["rootLayers"].setValue(IECore.StringVectorData(['A', 'A'])) self.assertEqual(list(collect["out"]["channelNames"].getValue()), ["A.R", "A.G", "A.B", "A.A"]) self.assertEqual(sampler["color"].getValue(), IECore.Color4f(0.1, 0.2, 0.3, 0.4)) collect["rootLayers"].setValue(IECore.StringVectorData(['A', 'B'])) self.assertEqual( list(collect["out"]["channelNames"].getValue()), ["A.R", "A.G", "A.B", "A.A", "B.R", "B.G", "B.B", "B.A"]) self.assertEqual(sampler["color"].getValue(), IECore.Color4f(0.1, 0.2, 0.3, 0.4)) sampler["channels"].setValue( IECore.StringVectorData(["B.R", "B.G", "B.B", "B.A"])) self.assertEqual(sampler["color"].getValue(), IECore.Color4f(0.2, 0.4, 0.6, 0.8)) # Test overlapping names take the first layer constant1["layer"].setValue("B") collect["rootLayers"].setValue(IECore.StringVectorData(['A', 'A.B'])) sampler["channels"].setValue( IECore.StringVectorData(["A.B.R", "A.B.G", "A.B.B", "A.B.A"])) self.assertEqual(list(collect["out"]["channelNames"].getValue()), ["A.B.R", "A.B.G", "A.B.B", "A.B.A"]) self.assertEqual(sampler["color"].getValue(), IECore.Color4f(0.1, 0.2, 0.3, 0.4)) collect["rootLayers"].setValue(IECore.StringVectorData(['A.B', 'A'])) self.assertEqual(list(collect["out"]["channelNames"].getValue()), ["A.B.R", "A.B.G", "A.B.B", "A.B.A"]) self.assertEqual(sampler["color"].getValue(), IECore.Color4f(0.2, 0.4, 0.6, 0.8))
def testDeep(self): constantA = GafferImage.Constant() constantA["color"].setValue(imath.Color4f(0.1, 0.2, 0.3, 0.4)) constantB = GafferImage.Constant() constantB["color"].setValue(imath.Color4f(0.01, 0.02, 0.03, 0.04)) constantC = GafferImage.Constant() constantC["color"].setValue(imath.Color4f(0.001, 0.002, 0.003, 0.004)) constantD = GafferImage.Constant() constantD["color"].setValue( imath.Color4f(0.0001, 0.0002, 0.0003, 0.0004)) deepMergeAB = GafferImage.DeepMerge() deepMergeAB["in"][0].setInput(constantA["out"]) deepMergeAB["in"][1].setInput(constantB["out"]) deepMergeCD = GafferImage.DeepMerge() deepMergeCD["in"][0].setInput(constantC["out"]) deepMergeCD["in"][1].setInput(constantD["out"]) switch = Gaffer.Switch() switch.setup(GafferImage.ImagePlug("in", )) switch["in"][0].setInput(deepMergeAB["out"]) switch["in"][1].setInput(deepMergeCD["out"]) switchExpr = Gaffer.Expression() switch.addChild(switchExpr) switchExpr.setExpression( 'parent["index"] = context["collect:layerName"] == "CD"') collect = GafferImage.CollectImages() collect["in"].setInput(switch["out"]) collect["rootLayers"].setValue(IECore.StringVectorData(['AB', 'CD'])) o = imath.V2i(0) self.assertEqual(collect["out"].channelData("AB.R", o), deepMergeAB["out"].channelData("R", o)) self.assertEqual(collect["out"].channelData("AB.G", o), deepMergeAB["out"].channelData("G", o)) self.assertEqual(collect["out"].channelData("AB.B", o), deepMergeAB["out"].channelData("B", o)) self.assertEqual(collect["out"].channelData("AB.A", o), deepMergeAB["out"].channelData("A", o)) self.assertEqual(collect["out"].channelData("CD.R", o), deepMergeCD["out"].channelData("R", o)) self.assertEqual(collect["out"].channelData("CD.G", o), deepMergeCD["out"].channelData("G", o)) self.assertEqual(collect["out"].channelData("CD.B", o), deepMergeCD["out"].channelData("B", o)) self.assertEqual(collect["out"].channelData("CD.A", o), deepMergeCD["out"].channelData("A", o)) self.assertEqual(collect["out"].sampleOffsets(o), deepMergeAB["out"].sampleOffsets(o)) self.assertEqual(collect["out"].dataWindow(), deepMergeAB["out"].dataWindow()) self.assertEqual(collect["out"].deep(), True) self.assertEqual( collect["out"].channelNames(), IECore.StringVectorData([ 'AB.R', 'AB.G', 'AB.B', 'AB.A', 'CD.R', 'CD.G', 'CD.B', 'CD.A' ])) deepMergeAB["enabled"].setValue(False) with self.assertRaisesRegexp( Gaffer.ProcessException, r'Input to CollectImages must be consistent, but it is sometimes deep.*' ) as raised: collect["out"].deep() deepMergeAB["enabled"].setValue(True) deepMergeAB["in"][2].setInput(constantB["out"]) with self.assertRaisesRegexp( Gaffer.ProcessException, r'SampleOffsets on input to CollectImages must match. Pixel 0,0 received both 3 and 2 samples' ) as raised: collect["out"].sampleOffsets(o) offset = GafferImage.Offset() offset["in"].setInput(constantB["out"]) offset["offset"].setValue(imath.V2i(-5, -13)) deepMergeAB["in"][2].setInput(offset["out"]) with self.assertRaisesRegexp( Gaffer.ProcessException, r'DataWindows on deep input to CollectImages must match. Received both -5,-13 -> 1920,1080 and 0,0 -> 1920,1080' ) as raised: collect["out"].dataWindow()