Beispiel #1
0
void layer_node_t::do_calc_bounds( const render::context_t& context)
{
    Imath::Box2i bbox;

    float opacity = get_value<float>( param( "opacity"));

    if( opacity == 1.0f)
    {
        switch( get_value<int>( param( "layer_mode")))
        {
        case comp_mult:
        case comp_min:
        case comp_mix:
            bbox = ImathExt::intersect( input_as<image_node_t>( 0)->bounds(), input_as<image_node_t>( 1)->bounds());
        break;

        case comp_sub:
            bbox = input_as<image_node_t>( 0)->bounds();
        break;

        default:
            bbox = input_as<image_node_t>( 0)->bounds();
            bbox.extendBy( input_as<image_node_t>( 1)->bounds());
        }
    }
    else
    {
        bbox = input_as<image_node_t>( 0)->bounds();
        bbox.extendBy( input_as<image_node_t>( 1)->bounds());
    }

    set_bounds( bbox);
}
Beispiel #2
0
void copy_channels_node_t::do_calc_bounds( const render::render_context_t& context)
{
    Imath::Box2i rod1 = input(0)->bounds();
    Imath::Box2i rod2 = input(1)->bounds();

    int ch_r = get_value<int>( param( "red"));
    int ch_g = get_value<int>( param( "green"));
    int ch_b = get_value<int>( param( "blue"));
    int ch_a = get_value<int>( param( "alpha"));

    // use alpha from input 1
    if( ch_a == copy_source)
    {
	set_bounds( rod1);
	return;
    }

    // alpha comes from input2
    if( ch_a != set_one && ch_a != set_zero)
    {
	set_bounds( rod2);
	return;
    }

    // alpha is zero or one, look at the other channels
    Imath::Box2i rod;

    if( ch_r == copy_source)
	rod = rod1;
    else
    {
	if( ch_r != set_zero && ch_r != set_one)
	    rod = rod2;
    }

    if( ch_g == copy_source)
	rod.extendBy( rod1);
    else
    {
	if( ch_g != set_zero && ch_r != set_one)
	    rod.extendBy( rod2);
    }

    if( ch_b == copy_source)
	rod.extendBy( rod1);
    else
    {
	if( ch_b != set_zero && ch_r != set_one)
	    rod.extendBy( rod2);
    }

    if( rod.isEmpty())
	rod = rod1;

    set_bounds( rod);
}
Beispiel #3
0
void copy_channels_node_t::do_calc_defined( const render::render_context_t& context)
{
    Imath::Box2i def1 = input(0)->defined();
    Imath::Box2i def2 = input(1)->defined();

    int ch_r = get_value<int>( param( "red"));
    int ch_g = get_value<int>( param( "green"));
    int ch_b = get_value<int>( param( "blue"));
    int ch_a = get_value<int>( param( "alpha"));

    // use alpha from input 1
    if( ch_a == copy_source)
    {
	set_defined( def1);
	return;
    }

    // alpha comes from input2
    if( ch_a != set_one && ch_a != set_zero)
    {
	set_defined( def2);
	return;
    }

    // alpha is zero or one, look at the other channels
    Imath::Box2i def;

    if( ch_r == copy_source)
	def = def1;
    else
    {
	if( ch_r != set_zero && ch_r != set_one)
	    def = def2;
    }

    if( ch_g == copy_source)
	def.extendBy( def1);
    else
    {
	if( ch_g != set_zero && ch_r != set_one)
	    def.extendBy( def2);
    }

    if( ch_b == copy_source)
	def.extendBy( def1);
    else
    {
	if( ch_b != set_zero && ch_r != set_one)
	    def.extendBy( def2);
    }

    if( def.isEmpty())
	def = def1;

    set_defined( def);
}
Beispiel #4
0
Imath::Box2i CopyChannels::computeDataWindow( const Gaffer::Context *context, const ImagePlug *parent ) const
{
	Imath::Box2i dataWindow;
	for( ImagePlugIterator it( inPlugs() ); !it.done(); ++it )
	{
		dataWindow.extendBy( (*it)->dataWindowPlug()->getValue() );
	}

	return dataWindow;
}
Beispiel #5
0
Imath::Box2i Merge::computeDataWindow( const Gaffer::Context *context, const ImagePlug *parent ) const
{
	Imath::Box2i dataWindow;
	for( ImagePlugIterator it( inPlugs() ); !it.done(); ++it )
	{
		// We don't need to check that the plug is connected here as unconnected plugs don't have data windows.
		dataWindow.extendBy( (*it)->dataWindowPlug()->getValue() );
	}

	return dataWindow;
}
Beispiel #6
0
Imath::Box2i Mix::computeDataWindow( const Gaffer::Context *context, const ImagePlug *parent ) const
{
	const float mix = mixPlug()->getValue();
	if( mix == 0.0f )
	{
		return inPlugs()->getChild< ImagePlug>( 0 )->dataWindowPlug()->getValue();
	}
	else if( mix == 1.0f && !maskPlug()->getInput<ValuePlug>() )
	{
		return inPlugs()->getChild< ImagePlug >( 1 )->dataWindowPlug()->getValue();
	}

	Imath::Box2i dataWindow;
	for( ImagePlugIterator it( inPlugs() ); !it.done(); ++it )
	{
		// We don't need to check that the plug is connected here as unconnected plugs don't have data windows.
		dataWindow.extendBy( (*it)->dataWindowPlug()->getValue() );
	}

	return dataWindow;
}
Beispiel #7
0
OfxRectD clip_t::getRegionOfDefinition( OfxTime time) const
{
    RAMEN_ASSERT( node());

    const image_node_t *in = 0;
    bool use_default = false;
    bool restore_time = false;
    float saved_frame;

    // calling getRoD for the output clip does not make a lot of sense, but some plugins do...
    if( port_ == -1)
        in = node();
    else // normal case
        in = node()->input_as<const image_node_t>( port_);

    if( !in)
    {
        in = node();
        use_default = true;
    }

    if( node()->composition())
    {
        saved_frame = node()->composition()->frame();

        if( saved_frame != time)
        {
            restore_time = true;
            composition_t *c = const_cast<composition_t*>( node()->composition());
            c->set_frame( time);
        }
    }

    Imath::Box2i b;

    if( use_default)
    {
        for( int i = 0; i < in->num_inputs(); ++i)
        {
            if( const image_node_t *src = in->input_as<const image_node_t>( i))
                b.extendBy( src->bounds());
        }

        if( b.isEmpty())
        {
            if( in->composition())
                b = node()->composition()->default_format().area();
            else
                b = preferences_t::Instance().default_format().area();
        }
    }
    else
        b = in->bounds();

    b = node()->vertical_flip( b);

    OfxRectD v;
    v.x1 = b.min.x;
    v.y1 = b.min.y;
    v.x2 = b.max.x + 1;
    v.y2 = b.max.y + 1;

    if( restore_time)
    {
        composition_t *c = const_cast<composition_t*>( node()->composition());
        c->set_frame( saved_frame);
    }

#ifndef NDEBUG
    DLOG( INFO) << "clip_t::getRoD, node = " << node()->name() << ", port = " << port() << ", result = " << v;
#endif

    return v;
}
Beispiel #8
0
// All the work is done here
int joinEXRs( int tilesX, int tilesY, const char* baseName, bool deleteTiles, bool Verbose )
{
   int exitCode = 0;

   // Expand names
   if( Verbose ) printf("Image file name = '%s', tilesX=%d, tilesY=%d\n", baseName, tilesX, tilesY);
   int numTiles = tilesX * tilesY;

   // Allocate memory:
   char ** tileNames = new char * [numTiles];
   Imf::InputFile ** iFiles = new Imf::InputFile * [numTiles];
   for( int i = 0; i < numTiles; i++)
   {
      tileNames[i] = new char[FILENAME_MAXLEN];
      iFiles[i] = 0;
   }

   // Insert tile info and check if files exist
   int nonEmptyTile = -1;
   struct stat stFileInfo;

   for( int i = 0; i < numTiles; i++)
   {
      sprintf( tileNames[i], "%s.tile_%d.exr", baseName, i);
      if( Verbose ) printf("Tile name  %d = '%s'\n", i, tileNames[i]);

      if( stat( tileNames[i], &stFileInfo ) == 0 )
      {
         // File exists - so open it and check for validness
         iFiles[i] = new Imf::InputFile( tileNames[i]);
         if( false == iFiles[i]->isComplete())
         {
            fprintf( stderr, "Error: File '%s' is incomplete or is not an OpenEXR file.\n", tileNames[i]); fflush( stderr);
            delete iFiles[i];
            iFiles[i] = 0;
            exitCode = 1;
         }
         else if( nonEmptyTile == -1 )
         {
            nonEmptyTile = i;
         }
      }
      else
      {
         fprintf( stderr, "Error: File '%s' not founded.\n", tileNames[i]); fflush( stderr);
         exitCode = 1;
      }
   }

   if( nonEmptyTile < 0) // All tiles were empty
   {
      fprintf( stderr, "Error: No tile files founded.\n"); fflush( stderr);
   }
   else
   {
   // Gather info from a non-empty tile file
   Imf::Header inHeader = iFiles[nonEmptyTile]->header();
   Imath::Box2i imageBox = inHeader.displayWindow(); // size of the resulting image
   int imageWidth = imageBox.max.x - imageBox.min.x + 1;
   int imageHeight = imageBox.max.y - imageBox.min.y + 1;

   // Iterate through all the channels and reserve mem for the whole display window
   // also add channels to the header of the output file
   Imf::Header outHeader( imageWidth, imageHeight);
   std::map< Imf::Name, ChannelInfo* > chInfos; // this will hold pixel data and stride for each channel in input files
   Imf::ChannelList channels = inHeader.channels();
   Imf::ChannelList::ConstIterator itCh;
   for( itCh = channels.begin(); itCh != channels.end(); itCh++ )
   {
      chInfos[itCh.name()] = new ChannelInfo( typeSize( itCh.channel().type), imageHeight, imageWidth );
      outHeader.channels().insert( itCh.name(), Imf::Channel( itCh.channel().type));
      if( Verbose) printf("Channel: '%s' | stride: %d\n", itCh.name(), typeSize( itCh.channel().type));
   }

   // Collect data from files
   Imath::Box2i tileBox;      // each tile's data window
   Imath::Box2i resultBox;    // resulting data window (should be sum of all tiles' data windows)
   Imf::FrameBuffer fb;
   for( int i = 0; i < numTiles; i++)
   {
      if( iFiles[i] == 0) // no file for this tile
         continue;

      tileBox = iFiles[i]->header().dataWindow();
      resultBox.extendBy( tileBox );

      if( Verbose) printf("Data win: xmin=%d xmax=%d ymin=%d ymax=%d\n", tileBox.min.x, tileBox.max.x, tileBox.min.y, tileBox.max.y);

      channels = iFiles[i]->header().channels();
      for( itCh = channels.begin(); itCh != channels.end(); itCh++ )
         fb.insert( itCh.name(),
                    Imf::Slice( itCh.channel().type,                // pixel type
                    (char*)&chInfos[itCh.name()]->array2d[0][0],    // base
                    chInfos[itCh.name()]->stride,                   // x stride
                    chInfos[itCh.name()]->stride * imageWidth,      // y stride
                    1, 1, 0.0 ) );                                  // x,y sampling, fill value

      iFiles[i]->setFrameBuffer(fb);
      iFiles[i]->readPixels( tileBox.min.y, tileBox.max.y);
   }

   // Write out everything:
   outHeader.dataWindow() = resultBox;
   Imf::OutputFile imageFile( baseName, outHeader );
   imageFile.setFrameBuffer(fb);
   imageFile.writePixels( resultBox.max.y-resultBox.min.y+1 );

   printf("Joined EXR image successfully written.\n");

   // Free files:
   for( int i = 0; i < numTiles; i++)
      if( iFiles[i] != 0 ) delete iFiles[i];
   delete [] iFiles;

   if( deleteTiles )
   {
      for( int i = 0; i < numTiles; i++)
         if( unlink( tileNames[i]) != 0)
         {
            perror("Remove");
            printf("Can't remove file '%s'\n", tileNames[i]);
         }
   }
   }

   // Free names:
   for( int i = 0; i < numTiles; i++)
      delete [] tileNames[i];
   delete [] tileNames;

   return exitCode;
}
void ImageCompositeOp::composite( CompositeFn fn, DataWindowResult dwr, ImagePrimitive * imageB, const CompoundObject * operands )
{
	assert( fn );
	assert( imageB );
	assert( operands );

	const StringVectorParameter::ValueType &channelNames = channelNamesParameter()->getTypedValue();
	if ( !channelNames.size() )
	{
		throw InvalidArgumentException( "ImageCompositeOp: No channels specified" );
	}

	ImagePrimitivePtr imageA = runTimeCast< ImagePrimitive > ( imageAParameter()->getValue() );
	assert( imageA );

	const std::string &alphaChannel = alphaChannelNameParameter()->getTypedValue();
	if ( !imageA->arePrimitiveVariablesValid() )
	{
		throw InvalidArgumentException( "ImageCompositeOp: Input image has invalid channels" );
	}

	const int inputMode = m_inputModeParameter->getNumericValue();
	if ( inputMode == Unpremultiplied )
	{
		ImagePremultiplyOpPtr premultOp = new ImagePremultiplyOp();
		premultOp->alphaChannelNameParameter()->setTypedValue( alphaChannel );
		premultOp->channelNamesParameter()->setTypedValue( channelNames );

		if ( imageA->variables.find( alphaChannel ) != imageA->variables.end() )
		{
			/// Make a new imageA, premultiplied
			premultOp->copyParameter()->setTypedValue( true );
			premultOp->inputParameter()->setValue( imageA );

			imageA = assertedStaticCast< ImagePrimitive >( premultOp->operate() );
			assert( imageA->arePrimitiveVariablesValid() );
		}

		if ( imageB->variables.find( alphaChannel ) != imageB->variables.end() )
		{
			/// Premultiply imageB in-place
			premultOp->copyParameter()->setTypedValue( false );
			premultOp->inputParameter()->setValue( imageB );
			premultOp->operate();
		}
	}
	else
	{
		assert( inputMode == Premultiplied );
	}


	const Imath::Box2i displayWindow = imageB->getDisplayWindow();

	Imath::Box2i newDataWindow = imageB->getDataWindow();

	if ( dwr == Union )
	{
		newDataWindow.extendBy( imageA->getDataWindow() );
	}
	else
	{
		assert( dwr == Intersection );
		newDataWindow = boxIntersection( newDataWindow, imageA->getDataWindow() );
	}

	newDataWindow = boxIntersection( newDataWindow, displayWindow );

	ImageCropOpPtr cropOp = new ImageCropOp();

	/// Need to make sure that we don't create a new image here - we want to modify the current one in-place. So,
	/// we turn off the "copy" parameter of ModifyOp.
	cropOp->copyParameter()->setTypedValue( false );
	cropOp->inputParameter()->setValue( imageB );
	cropOp->cropBoxParameter()->setTypedValue( newDataWindow );
	cropOp->matchDataWindowParameter()->setTypedValue( true );
	cropOp->resetOriginParameter()->setTypedValue( false );

	cropOp->operate();

	assert( imageB->arePrimitiveVariablesValid() );
	assert( imageB->getDataWindow() == newDataWindow );

	/// \todo Use the "reformat" parameter of the ImageCropOp to do this, when it's implemented
	imageB->setDisplayWindow( displayWindow );

	FloatVectorDataPtr aAlphaData = getChannelData( imageA.get(), alphaChannel, false );
	FloatVectorDataPtr bAlphaData = getChannelData( imageB, alphaChannel, false );

	const int newWidth = newDataWindow.size().x + 1;
	const int newHeight = newDataWindow.size().y + 1;
	const int newArea = newWidth * newHeight;

	assert( newArea == (int)imageB->variableSize( PrimitiveVariable::Vertex ) );

	for( unsigned i=0; i<channelNames.size(); i++ )
	{
		const StringVectorParameter::ValueType::value_type &channelName = channelNames[i];

		FloatVectorDataPtr aData = getChannelData( imageA.get(), channelName );
		assert( aData->readable().size() == imageA->variableSize( PrimitiveVariable::Vertex ) );
		FloatVectorDataPtr bData = getChannelData( imageB, channelName );
		assert( bData->readable().size() == imageB->variableSize( PrimitiveVariable::Vertex ) );
		FloatVectorDataPtr newBData = new FloatVectorData();

		newBData->writable().resize( newArea );
		imageB->variables[ channelName ].data = newBData;

		for ( int y = newDataWindow.min.y; y <= newDataWindow.max.y; y++ )
		{
			int offset = (y - newDataWindow.min.y ) * newWidth;
			for ( int x = newDataWindow.min.x; x <= newDataWindow.max.x; x++, offset++ )
			{
				float aVal = readChannelData( imageA.get(), aData.get(), V2i( x, y ) );
				float bVal = readChannelData( imageB, bData.get(), V2i( x, y ) );

				float aAlpha = aAlphaData ? readChannelData( imageA.get(), aAlphaData.get(), V2i( x, y ) ) : 1.0f;
				float bAlpha = bAlphaData ? readChannelData( imageB, bAlphaData.get(), V2i( x, y ) ) : 1.0f;

				assert( offset >= 0 );
				assert( offset < (int)newBData->readable().size() );
				newBData->writable()[ offset  ] = fn( aVal, aAlpha, bVal, bAlpha );
			}
		}
	}

	/// displayWindow should be unchanged
	assert( imageB->getDisplayWindow() == displayWindow );
	assert( imageB->arePrimitiveVariablesValid() );

	/// If input images were unpremultiplied, then ensure that the output is also
	if ( inputMode == Unpremultiplied && imageB->variables.find( alphaChannel ) != imageB->variables.end() )
	{
		ImageUnpremultiplyOpPtr unpremultOp = new ImageUnpremultiplyOp();
		/// Unpremultiply imageB in-place
		unpremultOp->copyParameter()->setTypedValue( false );
		unpremultOp->channelNamesParameter()->setTypedValue( channelNames );
		unpremultOp->alphaChannelNameParameter()->setTypedValue( alphaChannel );
		unpremultOp->inputParameter()->setValue( imageB );
		unpremultOp->operate();
		assert( imageB->arePrimitiveVariablesValid() );
	}
	else
	{
		assert( inputMode == Premultiplied );
	}
}