#ifndef CLAMPINTENSITYIMAGEFILTER_H__
#define CLAMPINTENSITYIMAGEFILTER_H__

#include <itkImageToImageFilter.h>
#include "itkSimpleDataObjectDecorator.h"

using namespace itk;

/**	@class ClampIntensityImageFilter
 *	@author	Jakob Wasza
 *	@brief	Filter that clamps image intensities into a given interval
 *
 *	@details
 *	This filter clamps the intensity values into a given interval defined
 *	by a lower bound and an upper bound. If an input value is 
 *	smaller (larger) than the lower (upper) bound the corresponding output
 *	value will be set to the lower (upper) bound value. \n
 *	This filter additionally provides a mask image that indicates whether a specific
 *	pixel was clamped. The value for clamped and not clamped can be set by the user.
 */ 

template<class TInput, class TOutput, class TMaskImage>
class ClampIntensityImageFilter : public itk::ImageToImageFilter<TInput,TOutput>
{
public:
	/** @name	Typedefs */
	//@{

	/** @name	Standard typedefs */
	//@{
	typedef ClampIntensityImageFilter					Self;
	typedef itk::ImageToImageFilter<TInput,TOutput>		Superclass;
	typedef itk::SmartPointer<Self>						Pointer;
	typedef itk::SmartPointer<const Self>				ConstPointer;
	typedef itk::DataObject::Pointer					DataObjectPointer;
	//@}

	/**	@name	Input, output and mask typedefs */
	//@{
	typedef typename Superclass::InputImageType		InputImageType;
	typedef typename InputImageType::Pointer		InputImagePointer;
	typedef typename InputImageType::ConstPointer	InputImageConstPointer;
	typedef typename InputImageType::PixelType		InputPixelType;
	typedef typename Superclass::OutputImageType	OutputImageType;
	typedef typename OutputImageType::Pointer		OutputImagePointer;
	typedef typename OutputImageType::PixelType		OutputImagePixelType;
	typedef TMaskImage								MaskImageType;
	typedef typename MaskImageType::Pointer			MaskImagePointer;
	typedef typename MaskImageType::ConstPointer	MaskImageConstPointer;
	//@}

	//@}

	/// Object creation
	itkNewMacro(Self);

	/// RTTI
	itkTypeMacro(ClampIntensityImageFilter, itk::ImageToImageFilter);

	/**	@name	Input mask */
	//@{
	itkSetInputMacro(MaskImage, MaskImageType, 1);
	itkGetInputMacro(MaskImage, MaskImageType, 1);
	//@}

	/// Set the lower bound
	void SetLowerBound(InputPixelType value);
	/// Get the lower bound
	InputPixelType GetLowerBound();
	/// Set the upper bound 
	void SetUpperBound(InputPixelType value);
	/// Get the upper bound
	InputPixelType GetUpperBound();

	/// Set the mask value for clamped and not clamped
	void SetValidFlag(typename MaskImageType::PixelType Value);

	/// Get the Mask image
	MaskImagePointer GetMaskOutput();

protected:
	/// Constructor
	ClampIntensityImageFilter();
	/// Destructor
	~ClampIntensityImageFilter();

	/// Create an output object of the correct type.
    virtual DataObjectPointer MakeOutput(unsigned int idx);

	/** @name  Threaded data generation */
	//@{
	virtual void BeforeThreadedGenerateData();
	virtual void ThreadedGenerateData(const typename OutputImageType::RegionType &OutputRegionForThread,int threadId);
	virtual void AfterThreadedGenerateData();
	//@}

protected:
	/// The lower bound
	float m_LowerBound;
	/// The upper bound
	float m_UpperBound;
	/// The valid flag
	typename MaskImageType::PixelType m_ValidFlag;


private:
	/// purposely not implemented
	ClampIntensityImageFilter(Self&); 
	/// purposely not implemented
	void operator=(const Self&);
};

#include "ClampIntensityImageFilter.txx"


#endif // CLAMPINTENSITYIMAGEFILTER_H__
