Skip to content

Commit

Permalink
Merge pull request #2731 from johnhaddon/dontPullOnInvalidChannels
Browse files Browse the repository at this point in the history
ColorProcessor/Shuffle : Don't pull on invalid input channels
  • Loading branch information
danieldresser-ie committed Aug 10, 2018
2 parents ba42479 + 7eede5f commit 0db9f32
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 20 deletions.
23 changes: 23 additions & 0 deletions python/GafferImageTest/ColorSpaceTest.py
Expand Up @@ -231,5 +231,28 @@ def testContext( self ) :
# check override produce expected output
self.assertImagesEqual( expected, context, ignoreMetadata = True )

def testSingleChannelImage( self ) :

r = GafferImage.ImageReader()
r["fileName"].setValue( "${GAFFER_ROOT}/python/GafferImageTest/images/blurRange.exr" )
self.assertEqual( r["out"]["channelNames"].getValue(), IECore.StringVectorData( [ "R" ] ) )

s = GafferImage.Shuffle()
s["in"].setInput( r["out"] )
s["channels"].addChild( s.ChannelPlug( "G", "R" ) )
s["channels"].addChild( s.ChannelPlug( "B", "R" ) )

c1 = GafferImage.ColorSpace()
c1["in"].setInput( r["out"] )
c1["inputSpace"].setValue( "linear" )
c1["outputSpace"].setValue( "sRGB" )

c2 = GafferImage.ColorSpace()
c2["in"].setInput( s["out"] )
c2["inputSpace"].setValue( "linear" )
c2["outputSpace"].setValue( "sRGB" )

self.assertEqual( c2["out"].channelData( "R", imath.V2i( 0 ) ), c1["out"].channelData( "R", imath.V2i( 0 ) ) )

if __name__ == "__main__":
unittest.main()
20 changes: 20 additions & 0 deletions python/GafferImageTest/ShuffleTest.py
Expand Up @@ -147,5 +147,25 @@ def testAffects( self ) :
s["channels"].addChild( s.ChannelPlug( "R", "G" ) )
self.assertEqual( s.affects( s["channels"][0]["out"] ), [ s["out"]["channelNames"], s["out"]["channelData"] ] )

def testMissingInputChannel( self ) :

r = GafferImage.ImageReader()
r["fileName"].setValue( "${GAFFER_ROOT}/python/GafferImageTest/images/blurRange.exr" )
self.assertEqual( r["out"]["channelNames"].getValue(), IECore.StringVectorData( [ "R" ] ) )

s = GafferImage.Shuffle()
s["in"].setInput( r["out"] )
s["channels"].addChild( s.ChannelPlug( "R", "A" ) )
s["channels"].addChild( s.ChannelPlug( "G", "B" ) )
s["channels"].addChild( s.ChannelPlug( "B", "G" ) )
s["channels"].addChild( s.ChannelPlug( "A", "R" ) )

black = IECore.FloatVectorData( [ 0 ] * GafferImage.ImagePlug.tileSize() * GafferImage.ImagePlug.tileSize() )

self.assertEqual( s["out"].channelData( "R", imath.V2i( 0 ) ), black )
self.assertEqual( s["out"].channelData( "G", imath.V2i( 0 ) ), black )
self.assertEqual( s["out"].channelData( "B", imath.V2i( 0 ) ), black )
self.assertEqual( s["out"].channelData( "A", imath.V2i( 0 ) ), r["out"].channelData( "R", imath.V2i( 0 ) ) )

if __name__ == "__main__":
unittest.main()
66 changes: 48 additions & 18 deletions src/GafferImage/ColorProcessor.cpp
Expand Up @@ -140,25 +140,41 @@ void ColorProcessor::compute( Gaffer::ValuePlug *output, const Gaffer::Context *
{
if( output == colorDataPlug() )
{
ConstStringVectorDataPtr channelNamesData;
{
ImagePlug::GlobalScope globalScope( context );
channelNamesData = inPlug()->channelNamesPlug()->getValue();
}
const vector<string> &channelNames = channelNamesData->readable();

const string &layerName = context->get<string>( g_layerNameKey );

FloatVectorDataPtr r, g, b;
FloatVectorDataPtr rgb[3];
{
ImagePlug::ChannelDataScope channelDataScope( context );
channelDataScope.setChannelName( ImageAlgo::channelName( layerName, "R" ) );
r = inPlug()->channelDataPlug()->getValue()->copy();
channelDataScope.setChannelName( ImageAlgo::channelName( layerName, "G" ) );
g = inPlug()->channelDataPlug()->getValue()->copy();
channelDataScope.setChannelName( ImageAlgo::channelName( layerName, "B" ) );
b = inPlug()->channelDataPlug()->getValue()->copy();
int i = 0;
for( const auto &baseName : { "R", "G", "B" } )
{
string channelName = ImageAlgo::channelName( layerName, baseName );
if( ImageAlgo::channelExists( channelNames, channelName ) )
{
channelDataScope.setChannelName( channelName );
rgb[i] = inPlug()->channelDataPlug()->getValue()->copy();
}
else
{
rgb[i] = ImagePlug::blackTile()->copy();
}
i++;
}
}

processColorData( context, r.get(), g.get(), b.get() );
processColorData( context, rgb[0].get(), rgb[1].get(), rgb[2].get() );

ObjectVectorPtr result = new ObjectVector();
result->members().push_back( r );
result->members().push_back( g );
result->members().push_back( b );
result->members().push_back( rgb[0] );
result->members().push_back( rgb[1] );
result->members().push_back( rgb[2] );

static_cast<ObjectPlug *>( output )->setValue( result );
return;
Expand Down Expand Up @@ -218,18 +234,32 @@ IECore::ConstFloatVectorDataPtr ColorProcessor::computeChannelData( const std::s

bool ColorProcessor::affectsColorData( const Gaffer::Plug *input ) const
{
return input == inPlug()->channelDataPlug();
return input == inPlug()->channelDataPlug() || input == inPlug()->channelNamesPlug();
}

void ColorProcessor::hashColorData( const Gaffer::Context *context, IECore::MurmurHash &h ) const
{
ConstStringVectorDataPtr channelNamesData;
{
ImagePlug::GlobalScope globalScope( context );
channelNamesData = inPlug()->channelNamesPlug()->getValue();
}
const vector<string> &channelNames = channelNamesData->readable();

const string &layerName = context->get<string>( g_layerNameKey );

ImagePlug::ChannelDataScope channelDataScope( context );
channelDataScope.setChannelName( ImageAlgo::channelName( layerName, "R" ) );
inPlug()->channelDataPlug()->hash( h );
channelDataScope.setChannelName( ImageAlgo::channelName( layerName, "G" ) );
inPlug()->channelDataPlug()->hash( h );
channelDataScope.setChannelName( ImageAlgo::channelName( layerName, "B" ) );
inPlug()->channelDataPlug()->hash( h );
for( const auto &baseName : { "R", "G", "B" } )
{
string channelName = ImageAlgo::channelName( layerName, baseName );
if( ImageAlgo::channelExists( channelNames, channelName ) )
{
channelDataScope.setChannelName( channelName );
inPlug()->channelDataPlug()->hash( h );
}
else
{
ImagePlug::blackTile()->hash( h );
}
}
}
14 changes: 12 additions & 2 deletions src/GafferImage/Shuffle.cpp
Expand Up @@ -36,6 +36,8 @@

#include "GafferImage/Shuffle.h"

#include "GafferImage/ImageAlgo.h"

using namespace std;
using namespace IECore;
using namespace Gaffer;
Expand Down Expand Up @@ -136,7 +138,7 @@ void Shuffle::affects( const Gaffer::Plug *input, AffectedPlugsContainer &output
{
outputs.push_back( outPlug()->channelNamesPlug() );
}
else if( input == inPlug()->channelDataPlug() )
else if( input == inPlug()->channelDataPlug() || input == inPlug()->channelNamesPlug() )
{
outputs.push_back( outPlug()->channelDataPlug() );
}
Expand Down Expand Up @@ -221,7 +223,15 @@ std::string Shuffle::inChannelName( const std::string &outChannelName ) const
{
if( (*it)->outPlug()->getValue() == outChannelName )
{
return (*it)->inPlug()->getValue();
const string inChannelName = (*it)->inPlug()->getValue();
if( inChannelName == "__white" || ImageAlgo::channelExists( inPlug(), inChannelName ) )
{
return inChannelName;
}
else
{
return "__black";
}
}
}
return outChannelName;
Expand Down

0 comments on commit 0db9f32

Please sign in to comment.