/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void JpegReaderPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleJpegReader", "JpegReader",
	                "Jpeg file reader" );
	desc.setPluginGrouping( "tuttle/image/io" );

	desc.setDescription( "<b>JPEG File reader</b> plugin is used to read jpeg files.  <br />" );

	// add the supported contexts
	desc.addSupportedContext( OFX::eContextReader );
	desc.addSupportedContext( OFX::eContextGenerator );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );

	// plugin flags
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
	desc.setHostFrameThreading( false );
	desc.setSupportsMultiResolution( false );
	desc.setSupportsMultipleClipDepths( true );
	desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void SeExprPluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
    desc.setLabels("TuttleSeExpr", "SeExpr", "SeExpr");
    desc.setPluginGrouping("tuttle/image/generator");

    desc.setDescription("SeExpr is a simple expression language that we use to provide"
                        "artistic control and customization to our core software.\n"
                        "We use it for procedural geometry synthesis, image synthesis,"
                        "simulation control, and much more.\n\n"
                        "language documentation: http://wdas.github.io/SeExpr/doxygen/userdoc.html"
                        "\n\n"
                        "projet website: http://www.disneyanimation.com/technology/seexpr.html");

    // add the supported contexts, only filter at the moment
    desc.addSupportedContext(OFX::eContextGenerator);
    desc.addSupportedContext(OFX::eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(OFX::eBitDepthUByte);
    desc.addSupportedBitDepth(OFX::eBitDepthUShort);
    desc.addSupportedBitDepth(OFX::eBitDepthFloat);

    // plugin flags
    desc.setRenderThreadSafety(OFX::eRenderFullySafe);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(true);
    desc.setSupportsMultipleClipDepths(true);
    desc.setSupportsTiles(kSupportTiles);
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void HistogramKeyerPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleHistogramKeyer", "HistogramKeyer",
		            "HistogramKeyer" );
	desc.setPluginGrouping( "tuttle/image/process/color" );

	desc.setDescription(
		"HistogramKeyer\n"
		"Test parametric parameters.\n"
		"Full description of the plugin....\n"
		"\n"
		"bla bla\n"
		"\n"
	);

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );

	desc.setOverlayInteractDescriptor( new OFX::DefaultEffectOverlayWrap<HistogramKeyerOverlayDescriptor>() );

//	if( ! OFX::getImageEffectHostDescription()->supportsParametricParameter )
//	{
//		BOOST_THROW_EXCEPTION( exception::MissingHostFeature( "Parametric parameter" ) );
//	}
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void ConstantPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleConstant", "Constant",
			"Constant" );
	desc.setPluginGrouping( "tuttle/image/generator" );

	desc.setDescription(
	    "Constant"
	    "\n"
	    "is a simple generator of a color."
	);

	// add the supported contexts
	desc.addSupportedContext( OFX::eContextGenerator );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
	desc.setHostFrameThreading( false );
	desc.setSupportsMultiResolution( false );
	desc.setSupportsMultipleClipDepths( true );
	desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void EXRReaderPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels(
		"TuttleExrReader",
		"ExrReader",
		"Exr file reader" );
	desc.setPluginGrouping( "tuttle/image/io" );

	desc.setDescription( "EXR File reader\n"
				 "Plugin is used to read exr files.\n"
	);

	// add the supported contexts
	desc.addSupportedContext( OFX::eContextReader );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// add supported extensions
	desc.addSupportedExtension( "exr" );
	desc.setPluginEvaluation( 90 );
	
	// plugin flags
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
	desc.setHostFrameThreading( false );
	desc.setSupportsMultiResolution( false );
	desc.setSupportsMultipleClipDepths( true );
	desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void Jpeg2000WriterPluginFactory::describe( OFX::ImageEffectDescriptor &desc )
{
    desc.setLabels(
	"TuttleJpeg2000Writer",
	"Jpeg2000Writer",
	"Jpeg 2000 image writer" );
    desc.setPluginGrouping( "tuttle/image/io" );

    desc.setDescription( "Jpeg2000 writer\n"
			 "plugin is used to output jpeg 2000 files.\n"
			 "In the filename pattern, put @ where you want your incrementation to be." );

    // add the supported contexts
    desc.addSupportedContext( OFX::eContextWriter );
    desc.addSupportedContext( OFX::eContextGeneral );

    // add supported pixel depths
    desc.addSupportedBitDepth( OFX::eBitDepthUByte );
    desc.addSupportedBitDepth( OFX::eBitDepthUShort );
    desc.addSupportedBitDepth( OFX::eBitDepthFloat );

    // add supported extensions
    desc.addSupportedExtension( "j2k" );
    //desc.addSupportedExtension( "jp2" );
    //desc.addSupportedExtension( "j2c" );

    // plugin flags
    desc.setRenderThreadSafety( OFX::eRenderFullySafe );
    desc.setHostFrameThreading( false );
    desc.setSupportsMultiResolution( false );
    desc.setSupportsMultipleClipDepths( true );
    desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void HistogramKeyerPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	// describe the plugin
	desc.setLabels( "TuttleHistogramKeyer", "HistogramKeyer",
		            "HistogramKeyer" );
	desc.setPluginGrouping( "tuttle/image/process/color" );

	desc.setDescription(
		"HistogramKeyer\n"
		"This histogram keyer plugin allows user to create an alpha mask using HSL & RGB curves. Output can be in gray scale or directly in alpha channel (RGBA)."
		"There are some selection parameters which could help you to refine your maniplulation (control points unders histograms and quantity)."
		"A reverse output mask is also implemented.\n"
		"\n"
	);

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );

	desc.setOverlayInteractDescriptor( new OFX::DefaultEffectOverlayWrap<HistogramKeyerOverlayDescriptor>() );

	if( ! OFX::getImageEffectHostDescription()->supportsParametricParameter )
	{
		BOOST_THROW_EXCEPTION( exception::MissingHostFeature( "Parametric parameter" ) );
	}
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void DPXWriterPluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
    desc.setLabels("TuttleDpxWriter", "DpxWriter", "Dpx file writer");
    desc.setPluginGrouping("tuttle/image/io");

    desc.setDescription("Digital Picture Exchange (DPX), ANSI/SMPTE standard (268M-2003)");

    // add the supported contexts
    desc.addSupportedContext(OFX::eContextWriter);
    desc.addSupportedContext(OFX::eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(OFX::eBitDepthUByte);
    desc.addSupportedBitDepth(OFX::eBitDepthUShort);
    desc.addSupportedBitDepth(OFX::eBitDepthFloat);

    // add supported extensions
    desc.addSupportedExtension("dpx");
    desc.setPluginEvaluation(90);

    // plugin flags
    desc.setRenderThreadSafety(OFX::eRenderFullySafe);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(false);
    desc.setSupportsMultipleClipDepths(true);
    desc.setSupportsTiles(kSupportTiles);
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void TurboJpegWriterPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels(
		"TuttleTurboJpegWriter",
		"TurboJpegWriter",
		"Turbo Jpeg file writer" );
	desc.setPluginGrouping( "tuttle/image/io" );

	using namespace boost::assign;
	std::vector<std::string> supportedExtensions;
	supportedExtensions += "jpeg", "jpg", "jpe", "jfif", "jfi";
	
	desc.setDescription( "Turbo Jpeg File writer\n"
			 "Plugin is used to write jpeg files.\n\n"
			 "supported extensions: \n" +
			 boost::algorithm::join( supportedExtensions, ", " )
	);

	// add the supported contexts
	desc.addSupportedContext( OFX::eContextWriter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
	desc.setHostFrameThreading( false );
	desc.setSupportsMultiResolution( false );
	desc.setSupportsMultipleClipDepths( true );
	desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void AVReaderPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	avtranscoder::preloadCodecsAndFormats();
	avtranscoder::Logger::setLogLevel( AV_LOG_QUIET );

	desc.setLabels(
		"TuttleAVReader",
		"AVReader",
		"Audio Video reader" );
	desc.setPluginGrouping( "tuttle/image/io" );
	
	std::vector<std::string> supportedExtensions( avtranscoder::getInputExtensions() );
	
	// Hack: Add basic video container extensions
	// as some versions of LibAV doesn't declare properly all extensions...
	supportedExtensions.push_back("mov");
	supportedExtensions.push_back("avi");
	supportedExtensions.push_back("mpg");
	supportedExtensions.push_back("mkv");
	supportedExtensions.push_back("flv");
	supportedExtensions.push_back("m2ts");
	
	// sort / unique
	std::sort(supportedExtensions.begin(), supportedExtensions.end());
	supportedExtensions.erase(
		std::unique(supportedExtensions.begin(), supportedExtensions.end()),
		supportedExtensions.end() );

	desc.setDescription( "Video reader based on AvTranscoder library\n\n"
			"Supported extensions: \n" +
			boost::algorithm::join( supportedExtensions, ", " )
		);
	
	// add the supported contexts
	desc.addSupportedContext( OFX::eContextReader );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// add supported extensions
	desc.addSupportedExtensions( supportedExtensions );
	desc.setPluginEvaluation( 30 );
	
	// plugin flags
	desc.setRenderThreadSafety( OFX::eRenderInstanceSafe );
	desc.setHostFrameThreading( false );
	desc.setSupportsMultiResolution( false );
	desc.setSupportsMultipleClipDepths( true );
	desc.setSupportsMultipleClipPARs( true );
	desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void HistogramPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	// describe the plugin
	desc.setLabels( "TuttleHistogram", "Histogram",
		            "Histogram" );
	desc.setPluginGrouping( "tuttle/image/display" );

	desc.setDescription(
		"Histogram\n"
		"\n"
		"An image histogram is a type of histogram that acts as a graphical representation "
		"of the tonal distribution in a digital image.[1] It plots the number of pixels "
		"for each tonal value. By looking at the histogram for a specific image a viewer "
		"will be able to judge the entire tonal distribution at a glance.\n"
		"Image histograms are present on many modern digital cameras. Photographers can "
		"use them as an aid to show the distribution of tones captured, and whether image "
		"detail has been lost to blown-out highlights or blacked-out shadows.\n"
		"The horizontal axis of the graph represents the tonal variations, while the vertical "
		"axis represents the number of pixels in that particular tone.[1] The left side "
		"of the horizontal axis represents the black and dark areas, the middle represents "
		"medium grey and the right hand side represents light and pure white areas. The vertical "
		"axis represents the size of the area that is captured in each one of these zones. "
		"Thus, the histogram for a very dark image will have the majority of its data points "
		"on the left side and center of the graph. Conversely, the histogram for a very "
		"bright image with few dark areas and/or shadows will have most of its data points "
		"on the right side and center of the graph.\n"
		"\n"
		"See http://en.wikipedia.org/wiki/Image_histogram"
		"\n"
	);

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );

	desc.setOverlayInteractDescriptor( new OFX::DefaultEffectOverlayWrap<HistogramOverlayDescriptor>() );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void ConvolutionPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels(
		"TuttleConvolution",
		"Convolution",
		"Convolution" );
	desc.setPluginGrouping( "tuttle/image/process/filter" );
	
	desc.setDescription(
"A convolution is defined as the integral of the product of the two functions"
"after one is reversed and shifted."
"\n"
"\n"
"In mathematics and, in particular, functional analysis, convolution is a"
"mathematical operation on two functions f and g, producing a third function"
"that is typically viewed as a modified version of one of the original functions. "
"Convolution is similar to cross-correlation. It has applications that include"
"probability, statistics, computer vision, image and signal processing,"
"electrical engineering, and differential equations."
"\n"
"The convolution can be defined for functions on groups other than Euclidean"
"space. In particular, the circular convolution can be defined for periodic"
"functions (that is, functions on the circle), and the discrete convolution"
"can be defined for functions on the set of integers. These generalizations of"
"the convolution have applications in the field of numerical analysis and"
"numerical linear algebra, and in the design and implementation of finite"
"impulse response filters in signal processing."
"\n"
"\n"
"http://en.wikipedia.org/wiki/Convolution"
);


	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void LutPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleLut", "Lut", "Color transformation through CLUT file" );
	desc.setPluginGrouping( "tuttle/image/process/color" );

	desc.setDescription( "Image Luter is used to lut components of an image." );

	// add the supported contexts
	desc.addSupportedContext( OFX::eContextGeneral );
	desc.addSupportedContext( OFX::eContextFilter );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	desc.setSupportsTiles( kSupportTiles );
	//desc.setRenderThreadSafety( OFX::eRenderFullySafe ); //< @todo tuttle: remove process data from LutPlugin
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void ViewerPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleViewer", "Viewer", "Viewer" );
	desc.setPluginGrouping( "tuttle/image/io" );

	desc.setDescription( kViewerHelp );

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void ColorTransferPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels(
		"TuttleColorTransfer",
		"ColorTransfer",
		"ColorTransfer" );
	desc.setPluginGrouping( "tuttle/image/process/color" );

	desc.setDescription(
			"ColorTransfer\n"
			"\n"
			"The standard usage of this node is to impose one image's color characteristics to another.\n"
			"If srcRef input clip is not the same as the source clip, "
			"it applies the tranformation from srcRef to dstRef on the source clip.\n"
			"\n"
			"Warning: pixel values <= 0.0001 will be clamp, because these values "
			"are undefined in the colorspace used for the transformation.\n"
			"\n"
			"Technically, the node modify the statistics of the image in a particular colorspace lambda-alpha-beta.\n"
			"This colorspace, created by Rederman and al., is closed to the human perception and minimizes "
			"the correlation between channels for many natural scenes.\n"
			"However, a choice parameter allows the user to choose in which colorspace the color transfer should be processed: "
			"LMS, lambda-alpha-beta or original/source colorspace.  \n"
			"According to the chosen colorspace, result varies (more or less colorfull, or dense...).\n\n"
			"For more details see the article:\n"
			"'Color Transfert between images' by Erik Reinhard, Michael Ashikhmin, Bruce Gooch and Peter Shirley. University of Utah.\n"
		);

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( true );
	desc.setRenderThreadSafety( OFX::eRenderInstanceSafe );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void ColorSpacePluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
    desc.setLabels("TuttleColorSpace", "ColorSpace", "Color convertions");
    desc.setPluginGrouping("tuttle/image/process/color");

    desc.setDescription("ColorSpace\n"
                        "Plugin is used to apply colorspace transformations on images.");

    // add the supported contexts
    desc.addSupportedContext(OFX::eContextFilter);
    desc.addSupportedContext(OFX::eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(OFX::eBitDepthUByte);
    desc.addSupportedBitDepth(OFX::eBitDepthUShort);
    desc.addSupportedBitDepth(OFX::eBitDepthFloat);

    // plugin flags
    desc.setSupportsTiles(kSupportTiles);
    desc.setRenderThreadSafety(OFX::eRenderFullySafe);
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void ColorTransformPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleColorTransform", "ColorTransform",
		            "ColorTransform" );
	desc.setPluginGrouping( "tuttle/image/process/color" );

	desc.setDescription( "Plugin under early development." );

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void PrintPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttlePrint", "TuttlePrint",
		            "TuttlePrint" );
        desc.setPluginGrouping( "tuttle/image/process/color" );

	desc.setDescription( "TuttlePrint\n"
	                     "Allows to print a part of the image." );

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
        desc.setRenderThreadSafety( OFX::eRenderFullySafe );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void OpenImageIOReaderPluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
    desc.setLabels("TuttleOpenImageIOReader", "OpenImageIOReader", "OpenImageIO file reader");
    desc.setPluginGrouping("tuttle/image/io");

    using namespace boost::assign;
    std::vector<std::string> supportedExtensions;
    supportedExtensions += "bmp", "cin", "dds", "dpx", "exr", "fits", "hdr", "ico", "j2k", "j2c", "jp2", "jpeg", "jpg",
        "jpe", "jfif", "jfi", "pbm", "pgm", "png", "pnm", "ppm", "pic", "psd", "rgbe", "sgi", "tga", "tif", "tiff", "tpic",
        "tx", "webp", "cr2";

    desc.setDescription("OpenImageIO Reader"
                        "\n\n"
                        "Compression is only available for Exr format."
                        "\n"
                        "supported extensions: \n" +
                        boost::algorithm::join(supportedExtensions, ", "));

    // add the supported contexts
    desc.addSupportedContext(OFX::eContextReader);
    desc.addSupportedContext(OFX::eContextGenerator);
    desc.addSupportedContext(OFX::eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(OFX::eBitDepthFloat);
    desc.addSupportedBitDepth(OFX::eBitDepthUByte);
    desc.addSupportedBitDepth(OFX::eBitDepthUShort);

    // add supported extensions
    desc.addSupportedExtensions(supportedExtensions);
    desc.setPluginEvaluation(40);

    // plugin flags
    desc.setRenderThreadSafety(OFX::eRenderFullySafe);
    desc.setHostFrameThreading(false);
    desc.setSupportsMultiResolution(false);
    desc.setSupportsMultipleClipDepths(true);
    desc.setSupportsTiles(kSupportTiles);
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out]   desc     Effect descriptor
 */
void CropPluginFactory::describe(OFX::ImageEffectDescriptor& desc)
{
    desc.setLabels("TuttleCrop", "Crop", "Image crop");
    desc.setPluginGrouping("tuttle/image/process/geometry");

    desc.setDescription("Crop\n"
                        "Plugin is used to crop an image.");

    // add the supported contexts
    desc.addSupportedContext(OFX::eContextFilter);
    desc.addSupportedContext(OFX::eContextGeneral);

    // add supported pixel depths
    desc.addSupportedBitDepth(OFX::eBitDepthUByte);
    desc.addSupportedBitDepth(OFX::eBitDepthUShort);
    desc.addSupportedBitDepth(OFX::eBitDepthFloat);

    // plugin flags
    desc.setSupportsTiles(kSupportTiles);
    desc.setRenderThreadSafety(OFX::eRenderFullySafe);

    desc.setOverlayInteractDescriptor(new OFX::DefaultEffectOverlayWrap<CropEffectOverlay>());
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void PushPixelPluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels(
		"TuttlePushPixel",
		"PushPixel",
		"Distort an image based on mask gradient." );
	desc.setPluginGrouping( "tuttle/image/process/geometry" );
	
	desc.setDescription(
		"Distort an image based on mask gradient." );

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
}
/**
 * @brief Function called to describe the plugin main features.
 * @param[in, out] desc Effect descriptor
 */
void SwscalePluginFactory::describe( OFX::ImageEffectDescriptor& desc )
{
	desc.setLabels( "TuttleSwscale", "Swscale", "Swscale" );
	desc.setPluginGrouping( "tuttle/image/process/geometry" );
	
	desc.setDescription( "SwScale: fast resizing plugin\n"
				"Plugin using swscale library from FFmpeg.\n"
				"Warning: Could not run with floating point images and\n"
				"			RGBA data different of 8 bit (32bpp).\n"
	);

	// add the supported contexts, only filter at the moment
	desc.addSupportedContext( OFX::eContextFilter );
	desc.addSupportedContext( OFX::eContextGeneral );

	// add supported pixel depths
	desc.addSupportedBitDepth( OFX::eBitDepthUByte );
	desc.addSupportedBitDepth( OFX::eBitDepthUShort );
	//desc.addSupportedBitDepth( OFX::eBitDepthFloat );

	// plugin flags
	desc.setSupportsTiles( kSupportTiles );
	desc.setRenderThreadSafety( OFX::eRenderFullySafe );
}