def testDeep( self ) : representativeDeep = GafferImage.ImageReader() representativeDeep["fileName"].setValue( self.representativeDeepImagePath ) deepCrop = GafferImage.Crop() deepCrop["in"].setInput( representativeDeep["out"] ) postFlatten = GafferImage.DeepToFlat() postFlatten["in"].setInput( deepCrop["out"] ) preFlatten = GafferImage.DeepToFlat() preFlatten["in"].setInput( representativeDeep["out"] ) flatCrop = GafferImage.Crop() flatCrop["in"].setInput( preFlatten["out"] ) dataWindow = representativeDeep["out"].dataWindow() for affectDisplay in [ True, False ]: for area in [ imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 150, 100 ) ), imath.Box2i( imath.V2i( -10, -13 ), imath.V2i( 157, 103 ) ), imath.Box2i( imath.V2i( 10, 13 ), imath.V2i( 143, 77 ) ), imath.Box2i( imath.V2i( 37, 65 ), imath.V2i( 101, 67 ) ), imath.Box2i( imath.V2i( 0, 0 ), imath.V2i( 149, 99 ) ) ] : deepCrop["area"].setValue( area ) flatCrop["area"].setValue( area ) self.assertImagesEqual( postFlatten["out"], flatCrop["out"] )
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 testAreaFormat(self): constant = GafferImage.Constant() constant['format'].setValue(GafferImage.Format(1024, 576)) crop1 = GafferImage.Crop() crop1['in'].setInput(constant['out']) crop1['areaSource'].setValue(GafferImage.Crop.AreaSource.Format) crop1['format'].setValue(GafferImage.Format(2048, 1152)) crop2 = GafferImage.Crop() crop2['in'].setInput(constant['out']) crop2['areaSource'].setValue(GafferImage.Crop.AreaSource.Area) crop2['area'].setValue( IECore.Box2i(IECore.V2i(0, 0), IECore.V2i(2048, 1152))) self.assertEqual(crop1['out']['dataWindow'].getValue(), crop2['out']['dataWindow'].getValue()) crop1['formatCenter'].setValue(True) crop2['area'].setValue( IECore.Box2i(IECore.V2i(-512, -288), IECore.V2i(1536, 864))) crop2['resetOrigin'].setValue(True) self.assertEqual(crop1['out']['dataWindow'].getValue(), crop2['out']['dataWindow'].getValue())
def testSinglePixelThatUsedToCrash( self ) : i = GafferImage.Constant() i["format"].setValue( GafferImage.Format( 4096, 2304, 1.000 ) ) overscanCrop = GafferImage.Crop() overscanCrop["area"].setValue( IECore.Box2i( IECore.V2i( 300, 300 ), IECore.V2i( 2220, 1908 ) ) ) overscanCrop["affectDataWindow"].setValue( False ) overscanCrop["in"].setInput( i["out"] ) c = GafferImage.Crop() c["area"].setValue( IECore.Box2i( IECore.V2i( -144, 1744 ), IECore.V2i( -143, 1745 ) ) ) c["affectDisplayWindow"].setValue( False ) c["in"].setInput( overscanCrop["out"] ) testFile = self.__testFile( "emptyImage", "RGBA", "exr" ) self.failIf( os.path.exists( testFile ) ) w = GafferImage.ImageWriter() w["in"].setInput( c["out"] ) w["fileName"].setValue( testFile ) with Gaffer.Context(): w["task"].execute() self.failUnless( os.path.exists( testFile ) ) after = GafferImage.ImageReader() after["fileName"].setValue( testFile ) # Check that the data window is the expected single pixel self.assertEqual( after["out"]["dataWindow"].getValue(), IECore.Box2i( IECore.V2i( -144, 1744 ), IECore.V2i( -143, 1745 ) ) )
def testDataWindow(self): sourceFormat = GafferImage.Format( imath.Box2i(imath.V2i(0), imath.V2i(512)), 1) constant1 = GafferImage.Constant() constant1["format"].setValue(sourceFormat) constant2 = GafferImage.Constant() constant2["format"].setValue(sourceFormat) crop1 = GafferImage.Crop() crop1["in"].setInput(constant1["out"]) crop1["affectDisplayWindow"].setValue(False) crop2 = GafferImage.Crop() crop2["in"].setInput(constant2["out"]) crop2["affectDisplayWindow"].setValue(False) merge = GafferImage.DeepMerge() merge["in"][0].setInput(crop1["out"]) merge["in"][1].setInput(crop2["out"]) for i in range(100): crop1Area = imath.Box2i() crop1Area.extendBy( imath.V2i(int(random.uniform(0, sourceFormat.width())), int(random.uniform(0, sourceFormat.height())))) crop1Area.extendBy( imath.V2i(int(random.uniform(0, sourceFormat.width())), int(random.uniform(0, sourceFormat.height())))) crop1["area"].setValue(crop1Area) crop2Area = imath.Box2i() crop2Area.extendBy( imath.V2i(int(random.uniform(0, sourceFormat.width())), int(random.uniform(0, sourceFormat.height())))) crop2Area.extendBy( imath.V2i(int(random.uniform(0, sourceFormat.width())), int(random.uniform(0, sourceFormat.height())))) crop2["area"].setValue(crop2Area) expectedDataWindow = crop1Area expectedDataWindow.extendBy(crop2Area.min()) expectedDataWindow.extendBy(crop2Area.max()) self.assertEqual(merge["out"]["dataWindow"].getValue(), expectedDataWindow)
def __test(fileName, size, filter): inputFileName = os.path.dirname(__file__) + "/images/" + fileName reader = GafferImage.ImageReader() reader["fileName"].setValue(inputFileName) inSize = reader["out"]["format"].getValue().getDisplayWindow( ).size() inSize = imath.V2f(inSize.x, inSize.y) deleteChannels = GafferImage.DeleteChannels() deleteChannels["mode"].setValue(1) deleteChannels["channels"].setValue(IECore.StringVectorData(['R'])) deleteChannels["in"].setInput(reader["out"]) scale = imath.V2f(size.x, size.y) / inSize resample = GafferImage.Resample() resample["in"].setInput(deleteChannels["out"]) resample["matrix"].setValue(imath.M33f().scale(scale)) resample["filter"].setValue(filter) resample["boundingMode"].setValue( GafferImage.Sampler.BoundingMode.Clamp) crop = GafferImage.Crop() crop["in"].setInput(resample["out"]) crop["area"].setValue(imath.Box2i(imath.V2i(0), size)) borderForFilterWidth = 60 sampleRegion = reader["out"]["dataWindow"].getValue() sampleRegion.setMin(sampleRegion.min() - imath.V2i(borderForFilterWidth)) sampleRegion.setMax(sampleRegion.max() + imath.V2i(borderForFilterWidth)) s = GafferImage.Sampler(reader["out"], "R", sampleRegion, GafferImage.Sampler.BoundingMode.Clamp) resampledS = GafferImage.Sampler( resample["out"], "R", resample["out"]["dataWindow"].getValue()) for y in range(size.y): for x in range(size.x): resampled = resampledS.sample(x, y) self.assertAlmostEqual( resampled, GafferImage.FilterAlgo.sampleBox( s, imath.V2f(x + 0.5, y + 0.5) / scale, max(1.0 / scale[0], 1.0), max(1.0 / scale[1], 1.0), filter), places=5) self.assertAlmostEqual( resampled, GafferImage.FilterAlgo.sampleParallelogram( s, imath.V2f(x + 0.5, y + 0.5) / scale, imath.V2f(1.0 / scale[0], 0), imath.V2f(0, 1.0 / scale[1]), filter), places=5)
def testEnergyPreservation(self): constant = GafferImage.Constant() constant["color"].setValue(IECore.Color4f(1)) crop = GafferImage.Crop() crop["in"].setInput(constant["out"]) crop["area"].setValue(IECore.Box2i(IECore.V2i(10), IECore.V2i(11))) crop["affectDisplayWindow"].setValue(False) blur = GafferImage.Blur() blur["in"].setInput(crop["out"]) blur["expandDataWindow"].setValue(True) stats = GafferImage.ImageStats() stats["in"].setInput(blur["out"]) stats["regionOfInterest"].setValue( IECore.Box2i(IECore.V2i(5), IECore.V2i(15))) for i in range(0, 10): blur["radius"].setValue(IECore.V2f(i * 0.5)) self.assertAlmostEqual(stats["average"]["r"].getValue(), 1 / 100., delta=0.0001)
def testSampleOutsideDataWindow(self): constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(1000, 1000)) constant["color"].setValue(IECore.Color4f(1)) crop = GafferImage.Crop() crop["in"].setInput(constant["out"]) crop["areaSource"].setValue(crop.AreaSource.Area) crop["area"].setValue(IECore.Box2i(IECore.V2i(135), IECore.V2i(214))) crop["affectDisplayWindow"].setValue(False) sampler = GafferImage.Sampler( crop["out"], "R", IECore.Box2i(IECore.V2i(0), IECore.V2i(50)), boundingMode=GafferImage.Sampler.BoundingMode.Clamp) self.assertEqual(sampler.sample(0, 0), 1) sampler = GafferImage.Sampler( crop["out"], "R", IECore.Box2i(IECore.V2i(0), IECore.V2i(50)), boundingMode=GafferImage.Sampler.BoundingMode.Black) self.assertEqual(sampler.sample(0, 0), 0)
def __test(fileName, size, filter): inputFileName = os.path.dirname(__file__) + "/images/" + fileName reader = GafferImage.ImageReader() reader["fileName"].setValue(inputFileName) resample = GafferImage.Resample() resample["in"].setInput(reader["out"]) resample["dataWindow"].setValue( IECore.Box2f(IECore.V2f(0), IECore.V2f(size.x, size.y))) resample["filter"].setValue(filter) resample["boundingMode"].setValue( GafferImage.Sampler.BoundingMode.Clamp) crop = GafferImage.Crop() crop["in"].setInput(resample["out"]) crop["area"].setValue(IECore.Box2i(IECore.V2i(0), size)) outputFileName = self.temporaryDirectory() + "/%s_%dx%d_%s.exr" % ( os.path.splitext(fileName)[0], size.x, size.y, filter) writer = GafferImage.ImageWriter() writer["in"].setInput(crop["out"]) writer["fileName"].setValue(outputFileName) writer.execute() result = GafferImage.ImageReader() result["fileName"].setValue(writer["fileName"].getValue()) expected = GafferImage.ImageReader() expected["fileName"].setValue( "%s/images/%s_%dx%d_%s.exr" % (os.path.dirname(__file__), os.path.splitext(fileName)[0], size.x, size.y, filter)) self.assertImagesEqual(result["out"], expected["out"], maxDifference=0.0005, ignoreMetadata=True) # Enable to write out images for visual comparison with OIIO. # The images will appear in a "resampleComparison" subdirectory # of the current directory. if False: if not os.path.exists("resampleComparison"): os.makedirs("resampleComparison") shutil.copyfile( outputFileName, "resampleComparison/gaffer_" + os.path.basename(outputFileName)) oiioOutputFileName = "resampleComparison/oiio_%s_%dx%d_%s.exr" % ( os.path.splitext(fileName)[0], size.x, size.y, filter) subprocess.check_call( "oiiotool --threads 1 %s --ch R,G,B --resize:filter=%s %dx%d -o %s" % (inputFileName, filter, size.x, size.y, oiioOutputFileName), shell=True)
def testWriteEmptyImage( self ) : i = GafferImage.Constant() i["format"].setValue( GafferImage.Format( IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 100 ) ), 1 ) ) c = GafferImage.Crop() c["areaSource"].setValue( GafferImage.Crop.AreaSource.Area ) c["area"].setValue( IECore.Box2i( IECore.V2i( 40 ), IECore.V2i( 40 ) ) ) c["affectDisplayWindow"].setValue( False ) c["affectDataWindow"].setValue( True ) c["in"].setInput( i["out"] ) testFile = self.__testFile( "emptyImage", "RGBA", "exr" ) self.failIf( os.path.exists( testFile ) ) w = GafferImage.ImageWriter() w["in"].setInput( c["out"] ) w["fileName"].setValue( testFile ) with Gaffer.Context(): w["task"].execute() self.failUnless( os.path.exists( testFile ) ) after = GafferImage.ImageReader() after["fileName"].setValue( testFile ) # Check that the data window and the display window are the same self.assertEqual( after["out"]["format"].getValue().getDisplayWindow(), after["out"]["dataWindow"].getValue() )
def testOnePixelBlur( self ) : constant = GafferImage.Constant() constant["color"].setValue( IECore.Color4f( 1 ) ) crop = GafferImage.Crop() crop["in"].setInput( constant["out"] ) crop["area"].setValue( IECore.Box2i( IECore.V2i( 10 ), IECore.V2i( 11 ) ) ) crop["affectDisplayWindow"].setValue( False ) blur = GafferImage.Blur() blur["in"].setInput( crop["out"] ) blur["radius"].setValue( IECore.V2f( 1 ) ) blur["expandDataWindow"].setValue( True ) sampler = GafferImage.Sampler( blur["out"], "R", IECore.Box2i( IECore.V2i( 0 ), IECore.V2i( 20 ) ) ) # Centre is brightest self.assertGreater( sampler.sample( 10, 10 ), sampler.sample( 11, 10 ) ) # Corners are least bright self.assertGreater( sampler.sample( 11, 10 ), sampler.sample( 11, 11 ) ) self.assertGreater( sampler.sample( 11, 11 ), 0 ) # Shape is symmetrical self.assertEqual( sampler.sample( 11, 10 ), sampler.sample( 9, 10 ) ) self.assertEqual( sampler.sample( 10, 11 ), sampler.sample( 10, 9 ) ) self.assertEqual( sampler.sample( 10, 11 ), sampler.sample( 10, 9 ) ) self.assertEqual( sampler.sample( 9, 9 ), sampler.sample( 11, 9 ) ) self.assertEqual( sampler.sample( 9, 9 ), sampler.sample( 11, 11 ) ) self.assertEqual( sampler.sample( 9, 9 ), sampler.sample( 9, 11 ) )
def testEmptyInput(self): crop = GafferImage.Crop() crop["area"]["min"].setValue(IECore.V2i(20)) self.assertTrue( GafferImage.BufferAlgo.empty(crop["out"]["dataWindow"].getValue()))
def testPassThrough( self ) : i = GafferImage.ImageReader() i["fileName"].setValue( self.imageFileUndersizeDataWindow ) crop = GafferImage.Crop() crop["in"].setInput(i["out"]) crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Area ) crop["area"].setValue( imath.Box2i( imath.V2i( 40 ), imath.V2i( 50 ) ) ) crop["affectDataWindow"].setValue( True ) crop["affectDisplayWindow"].setValue( True ) crop["resetOrigin"].setValue( False ) self.assertEqual(i['out'].channelDataHash( "R", imath.V2i( 0 ) ), crop['out'].channelDataHash( "R", imath.V2i( 0 ) ) ) self.assertEqual(i['out'].channelDataHash( "G", imath.V2i( 0 ) ), crop['out'].channelDataHash( "G", imath.V2i( 0 ) ) ) self.assertEqual(i['out'].channelDataHash( "B", imath.V2i( 0 ) ), crop['out'].channelDataHash( "B", imath.V2i( 0 ) ) ) self.assertEqual( i["out"]["metadata"].hash(), crop["out"]["metadata"].hash() ) self.assertEqual( i["out"]["channelNames"].hash(), crop["out"]["channelNames"].hash() ) self.assertNotEqual( i["out"]["format"].hash(), crop["out"]["format"].hash() ) self.assertNotEqual( i["out"]["dataWindow"].hash(), crop["out"]["dataWindow"].hash() ) self.assertEqual( i["out"]["metadata"].getValue(), crop["out"]["metadata"].getValue() ) self.assertEqual( i["out"]["channelNames"].getValue(), crop["out"]["channelNames"].getValue() ) self.assertNotEqual( i["out"]["format"].getValue(), crop["out"]["format"].getValue() ) self.assertNotEqual( i["out"]["dataWindow"].getValue(), crop["out"]["dataWindow"].getValue() )
def testDefaultState( self ) : crop = GafferImage.Crop() self.assertEqual( crop["areaSource"].getValue(), GafferImage.Crop.AreaSource.Area ) self.assertTrue( crop["area"].getValue().isEmpty() ) self.assertEqual( crop["affectDataWindow"].getValue(), True ) self.assertEqual( crop["affectDisplayWindow"].getValue(), True )
def testEnableBehaviour( self ) : crop = GafferImage.Crop() self.assertTrue( crop.enabledPlug().isSame( crop["enabled"] ) ) self.assertTrue( crop.correspondingInput( crop["out"] ).isSame( crop["in"] ) ) self.assertEqual( crop.correspondingInput( crop["in"] ), None ) self.assertEqual( crop.correspondingInput( crop["enabled"] ), None )
def emptyImage( self ) : emptyCrop = GafferImage.Crop( "Crop" ) emptyCrop["Constant"] = GafferImage.Constant() emptyCrop["Constant"]["format"].setValue( GafferImage.Format( 100, 100, 1.000 ) ) emptyCrop["in"].setInput( emptyCrop["Constant"]["out"] ) emptyCrop["area"].setValue( imath.Box2i() ) emptyCrop["affectDisplayWindow"].setValue( False ) self.assertEqual( emptyCrop["out"]["dataWindow"].getValue(), imath.Box2i() ) return emptyCrop
def testDisplayWindowToDataWindow( self ) : i = GafferImage.ImageReader() i["fileName"].setValue( self.imageFileOversizeDataWindow ) crop = GafferImage.Crop() crop["in"].setInput(i["out"]) crop["areaSource"].setValue( GafferImage.Crop.AreaSource.DisplayWindow ) crop["affectDataWindow"].setValue( True ) crop["affectDisplayWindow"].setValue( False ) self.assertEqual( i["out"]["format"].getValue().getDisplayWindow(), crop["out"]["dataWindow"].getValue() )
def testIntersectDataWindow( self ) : i = GafferImage.ImageReader() i["fileName"].setValue( self.imageFileUndersizeDataWindow ) crop = GafferImage.Crop() crop["in"].setInput(i["out"]) crop["areaSource"].setValue( GafferImage.Crop.AreaSource.Area ) crop["area"].setValue( imath.Box2i( imath.V2i( 0 ), imath.V2i( 50 ) ) ) crop["affectDataWindow"].setValue( True ) crop["affectDisplayWindow"].setValue( False ) self.assertEqual( crop["out"]["dataWindow"].getValue(), imath.Box2i( imath.V2i( 30 ), imath.V2i( 50 ) ) )
def testSmallDataWindowOverLarge(self): b = GafferImage.Constant() b["format"].setValue(GafferImage.Format(500, 500, 1.0)) b["color"].setValue(imath.Color4f(1, 0, 0, 1)) a = GafferImage.Constant() a["format"].setValue(GafferImage.Format(500, 500, 1.0)) a["color"].setValue(imath.Color4f(0, 1, 0, 1)) mask = GafferImage.Constant() mask["format"].setValue(GafferImage.Format(500, 500, 1.0)) mask["color"].setValue(imath.Color4f(0.75)) aCrop = GafferImage.Crop() aCrop["in"].setInput(a["out"]) aCrop["areaSource"].setValue(aCrop.AreaSource.Area) aCrop["area"].setValue(imath.Box2i(imath.V2i(50), imath.V2i(162))) aCrop["affectDisplayWindow"].setValue(False) m = GafferImage.Mix() m["in"][0].setInput(b["out"]) m["in"][1].setInput(aCrop["out"]) m["mask"].setInput(mask["out"]) redSampler = GafferImage.Sampler( m["out"], "R", m["out"]["format"].getValue().getDisplayWindow()) greenSampler = GafferImage.Sampler( m["out"], "G", m["out"]["format"].getValue().getDisplayWindow()) blueSampler = GafferImage.Sampler( m["out"], "B", m["out"]["format"].getValue().getDisplayWindow()) def sample(x, y): return imath.Color3f( redSampler.sample(x, y), greenSampler.sample(x, y), blueSampler.sample(x, y), ) # We should only have green in areas which are inside # the data window of aCrop. But we still only take 25% # of the red everywhere self.assertEqual(sample(49, 49), imath.Color3f(0.25, 0, 0)) self.assertEqual(sample(50, 50), imath.Color3f(0.25, 0.75, 0)) self.assertEqual(sample(161, 161), imath.Color3f(0.25, 0.75, 0)) self.assertEqual(sample(162, 162), imath.Color3f(0.25, 0, 0))
def testAffectDataWindow(self): i = GafferImage.ImageReader() i["fileName"].setValue(self.imageFileUndersizeDataWindow) crop = GafferImage.Crop() crop["in"].setInput(i["out"]) crop["areaSource"].setValue(GafferImage.Crop.AreaSource.Custom) crop["area"].setValue(IECore.Box2i(IECore.V2i(40), IECore.V2i(50))) crop["affectDataWindow"].setValue(True) crop["affectDisplayWindow"].setValue(False) self.assertEqual(crop["out"]["dataWindow"].getValue(), IECore.Box2i(IECore.V2i(40), IECore.V2i(50))) self.assertEqual(i["out"]["format"].getValue(), crop["out"]["format"].getValue())
def testAffects( self ) : c = GafferImage.Crop() self.assertEqual( set( c.affects( c["affectDisplayWindow"] ) ), { c["out"]["format"], c["out"]["dataWindow"], c["__offset"]["x"], c["__offset"]["y"] } ) self.assertEqual( set( c.affects( c["affectDataWindow"] ) ), { c["out"]["dataWindow"] } ) self.assertTrue( c["out"]["dataWindow"] in set( c.affects( c["in"]["dataWindow"] ) ) ) self.assertTrue( c["out"]["format"] in set( c.affects( c["in"]["format"] ) ) )
def testLargeDataWindowAddedToSmall(self): b = GafferImage.Constant() b["format"].setValue(GafferImage.Format(500, 500, 1.0)) b["color"].setValue(imath.Color4f(1, 0, 0, 1)) a = GafferImage.Constant() a["format"].setValue(GafferImage.Format(500, 500, 1.0)) a["color"].setValue(imath.Color4f(0, 1, 0, 1)) mask = GafferImage.Constant() mask["format"].setValue(GafferImage.Format(500, 500, 1.0)) mask["color"].setValue(imath.Color4f(0.5)) bCrop = GafferImage.Crop() bCrop["in"].setInput(b["out"]) bCrop["areaSource"].setValue(bCrop.AreaSource.Area) bCrop["area"].setValue(imath.Box2i(imath.V2i(50), imath.V2i(162))) bCrop["affectDisplayWindow"].setValue(False) m = GafferImage.Mix() m["in"][0].setInput(bCrop["out"]) m["in"][1].setInput(a["out"]) m["mask"].setInput(mask["out"]) redSampler = GafferImage.Sampler( m["out"], "R", m["out"]["format"].getValue().getDisplayWindow()) greenSampler = GafferImage.Sampler( m["out"], "G", m["out"]["format"].getValue().getDisplayWindow()) blueSampler = GafferImage.Sampler( m["out"], "B", m["out"]["format"].getValue().getDisplayWindow()) def sample(x, y): return imath.Color3f( redSampler.sample(x, y), greenSampler.sample(x, y), blueSampler.sample(x, y), ) # We should only have yellow in areas where the background exists, # and should have just green everywhere else. self.assertEqual(sample(49, 49), imath.Color3f(0, 0.5, 0)) self.assertEqual(sample(50, 50), imath.Color3f(0.5, 0.5, 0)) self.assertEqual(sample(161, 161), imath.Color3f(0.5, 0.5, 0)) self.assertEqual(sample(162, 162), imath.Color3f(0, 0.5, 0))
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 testSmallDataWindowOverLarge(self): b = GafferImage.Constant() b["format"].setValue(GafferImage.Format(500, 500, 1.0)) b["color"].setValue(IECore.Color4f(1, 0, 0, 1)) a = GafferImage.Constant() a["format"].setValue(GafferImage.Format(500, 500, 1.0)) a["color"].setValue(IECore.Color4f(0, 1, 0, 1)) aCrop = GafferImage.Crop() aCrop["in"].setInput(a["out"]) aCrop["areaSource"].setValue(aCrop.AreaSource.Area) aCrop["area"].setValue(IECore.Box2i(IECore.V2i(50), IECore.V2i(162))) aCrop["affectDisplayWindow"].setValue(False) m = GafferImage.Merge() m["operation"].setValue(m.Operation.Over) m["in"][0].setInput(b["out"]) m["in"][1].setInput(aCrop["out"]) redSampler = GafferImage.Sampler( m["out"], "R", m["out"]["format"].getValue().getDisplayWindow()) greenSampler = GafferImage.Sampler( m["out"], "G", m["out"]["format"].getValue().getDisplayWindow()) blueSampler = GafferImage.Sampler( m["out"], "B", m["out"]["format"].getValue().getDisplayWindow()) def sample(x, y): return IECore.Color3f( redSampler.sample(x, y), greenSampler.sample(x, y), blueSampler.sample(x, y), ) # We should only have overed green in areas which are inside # the data window of aCrop. Everywhere else we should have # red still. self.assertEqual(sample(49, 49), IECore.Color3f(1, 0, 0)) self.assertEqual(sample(50, 50), IECore.Color3f(0, 1, 0)) self.assertEqual(sample(161, 161), IECore.Color3f(0, 1, 0)) self.assertEqual(sample(162, 162), IECore.Color3f(1, 0, 0))
def testResetOrigin(self): constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(100, 200, 1)) crop = GafferImage.Crop() crop["in"].setInput(constant["out"]) self.assertEqual(crop["affectDisplayWindow"].getValue(), True) self.assertEqual(crop["affectDataWindow"].getValue(), True) self.assertEqual(crop["resetOrigin"].getValue(), True) area = IECore.Box2i(IECore.V2i(50), IECore.V2i(100, 190)) crop["area"].setValue(area) self.assertEqual(crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i(IECore.V2i(0), area.size())) self.assertEqual(crop["out"]["dataWindow"].getValue(), IECore.Box2i(IECore.V2i(0), area.size())) crop["resetOrigin"].setValue(False) self.assertEqual(crop["out"]["format"].getValue().getDisplayWindow(), area) self.assertEqual(crop["out"]["dataWindow"].getValue(), area) # If we're not affecting the display window, then the reset origin flag # should be ignored. crop["resetOrigin"].setValue(True) crop["affectDisplayWindow"].setValue(False) self.assertEqual(crop["out"]["format"].getValue(), crop["in"]["format"].getValue()) self.assertEqual(crop["out"]["dataWindow"].getValue(), area) # But if we are affecting the display window, and we are resetting the origin, # the data window should be offset even if affectDataWindow is off. crop["affectDisplayWindow"].setValue(True) crop["affectDataWindow"].setValue(False) self.assertEqual(crop["out"]["format"].getValue().getDisplayWindow(), IECore.Box2i(IECore.V2i(0), area.size())) self.assertEqual(crop["out"]["dataWindow"].getValue(), IECore.Box2i(IECore.V2i(-50), IECore.V2i(50, 150)))
def testSubpixelTranslate( self ) : # This checks we can do subpixel translations properly - at one # time a bug in Resample prevented this. # Use a Constant and a Crop to make a vertical line. constant = GafferImage.Constant() constant["format"].setValue( GafferImage.Format( 100, 100 ) ) constant["color"].setValue( IECore.Color4f( 1 ) ) crop = GafferImage.Crop() crop["in"].setInput( constant["out"] ) crop["affectDataWindow"].setValue( True ) crop["affectDisplayWindow"].setValue( False ) crop["area"].setValue( IECore.Box2i( IECore.V2i( 10, 0 ), IECore.V2i( 11, 100 ) ) ) # Check it's where we expect transform = GafferImage.ImageTransform() transform["in"].setInput( crop["out"] ) transform["filter"].setValue( "rifman" ) def sample( position ) : sampler = GafferImage.Sampler( transform["out"], "R", IECore.Box2i( position, position + IECore.V2i( 1 ) ) ) return sampler.sample( position.x, position.y ) self.assertEqual( sample( IECore.V2i( 9, 10 ) ), 0 ) self.assertEqual( sample( IECore.V2i( 10, 10 ) ), 1 ) self.assertEqual( sample( IECore.V2i( 11, 10 ) ), 0 ) # Move it a tiiny bit, and check it has moved # a tiiny bit. transform["transform"]["translate"]["x"].setValue( 0.1 ) self.assertEqual( sample( IECore.V2i( 9, 10 ) ), 0 ) self.assertGreater( sample( IECore.V2i( 10, 10 ) ), 0.9 ) self.assertGreater( sample( IECore.V2i( 11, 10 ) ), 0.09 )
def testEmptyDataWindowMerge(self): constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(512, 512, 1.000)) constant["color"].setValue(imath.Color4f(1)) offset = GafferImage.Offset() offset["in"].setInput(constant["out"]) offset["offset"].setValue(imath.V2i(-1024)) emptyCrop = GafferImage.Crop() emptyCrop["in"].setInput(constant["out"]) emptyCrop["area"].setValue(imath.Box2i(imath.V2i(-10), imath.V2i(-100))) merge = GafferImage.Merge() merge["in"][0].setInput(offset["out"]) merge["in"][1].setInput(emptyCrop["out"]) self.assertEqual(merge["out"].dataWindow(), imath.Box2i(imath.V2i(-1024), imath.V2i(-512)))
def testMismatchedDataWindow(self): constant = GafferImage.Constant() constant["format"].setValue( GafferImage.Format( IECore.Box2i(IECore.V2i(0), IECore.V2i(256, 256)), 1)) crop = GafferImage.Crop() crop["in"].setInput(constant["out"]) crop["areaSource"].setValue(crop.AreaSource.Custom) crop["area"].setValue(IECore.Box2i(IECore.V2i(64), IECore.V2i(128))) crop["affectDisplayWindow"].setValue(False) crop["affectDataWindow"].setValue(True) resize = GafferImage.Resize() resize["in"].setInput(crop["out"]) resize["format"].setValue( GafferImage.Format( IECore.Box2i(IECore.V2i(0), IECore.V2i(512, 512)), 1)) self.assertEqual(resize["out"]["dataWindow"].getValue(), IECore.Box2i(IECore.V2i(128), IECore.V2i(256)))
def testHashIncludesBlackPixels(self): constant = GafferImage.Constant() constant["format"].setValue(GafferImage.Format(1000, 1000)) constant["color"].setValue(IECore.Color4f(1)) crop = GafferImage.Crop() crop["in"].setInput(constant["out"]) crop["areaSource"].setValue(crop.AreaSource.Area) crop["area"].setValue(IECore.Box2i(IECore.V2i(0), IECore.V2i(200))) crop["affectDisplayWindow"].setValue(False) crop["affectDataWindow"].setValue(False) # Samples the whole data window sampler1 = GafferImage.Sampler( crop["out"], "R", IECore.Box2i(IECore.V2i(0), IECore.V2i(200)), boundingMode=GafferImage.Sampler.BoundingMode.Black) # Samples the whole data window and then some. sampler2 = GafferImage.Sampler( crop["out"], "R", IECore.Box2i(IECore.V2i(0), IECore.V2i(210)), boundingMode=GafferImage.Sampler.BoundingMode.Black) # Samples the whole data window and then some and then some more. sampler3 = GafferImage.Sampler( crop["out"], "R", IECore.Box2i(IECore.V2i(0), IECore.V2i(220)), boundingMode=GafferImage.Sampler.BoundingMode.Black) # The hashes must take account of the additional pixels being sampled. self.assertNotEqual(sampler1.hash(), sampler2.hash()) self.assertNotEqual(sampler2.hash(), sampler3.hash()) self.assertNotEqual(sampler3.hash(), sampler1.hash())
def testFormatAffectsOutput( self ) : crop = GafferImage.Crop() cs = GafferTest.CapturingSlot( crop.plugDirtiedSignal() ) crop["format"].setValue( GafferImage.Format( 100, 200 ) ) self.assertIn( crop["out"]["dataWindow"], { x[0] for x in cs } )