/*======================================================================================

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkRGBRImage.h
	Version:		$Revision: 2723 $
	Date:			$Date: 2012-03-06 09:46:29 +0100 (Di, 06 Mrz 2012) $

	Copyright (c) 2010-2011
	Pattern Recognition Lab, 
    University Erlangen-Nuremberg, Germany
    All rights reserved.

	This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
	See RITKCopyright.txt for more information.

	http://www5.informatik.uni-erlangen.de/research/software/ritk

========================================================================================*/

#ifndef RGBRIMAGE_H__
#define RGBRIMAGE_H__

#include "ritkCommon.h"
#include "ritkRImage.h"

#include "ritkRGBMappingImageFilter.h"

namespace ritk
{

/**	@ingroup	Common
  *	@class		RGBRImage
  *	@author		Jakob Wasza
  *	@brief		Class tha extends and RImage by RGB information
  *
  *	@details
  *	Due to the importance of an RGB image payload this class provides a convenience extension to the RImage base class. \n
  *	Note that all overloaded methods will also call the superclass' implementation
  */
template<class TReal, class TRGB, unsigned int NDimension=2>
class RGBRImage : public RImage<TReal,NDimension>
{
public:
	/** @name Standard typedefs */
	//@{
	typedef RGBRImage						Self;
	typedef RImage<TReal,NDimension>		Superclass;
	typedef itk::SmartPointer<Self>			Pointer;
	typedef itk::SmartPointer<const Self>	ConstPointer;
	//@}

	/**	@name Typedefs for region,spacing,etc */
	//@{
	typedef typename Superclass::IndexType		IndexType;
	typedef typename Superclass::SizeType		SizeType;
	typedef typename Superclass::RegionType		RegionType;
	typedef typename Superclass::SpacingType	SpacingType;
	typedef typename Superclass::DirectionType	DirectionType;
	typedef typename Superclass::PointType		PointType;
	//@}

	/**	@name Typedefs for generic payloads */
	//@{
	typedef typename Superclass::GenericPayloadContainerType			GenericPayloadContainerType;
	typedef typename Superclass::GenericPayloadContainerPointer			GenericPayloadContainerPointer;
	typedef typename Superclass::GenericPayloadContainerConstPointer	GenericPayloadContainerConstPointer;
	//@}

	/**	@name Typedefs for the RGB image */
	//@{
	typedef TRGB									RGBType;
	typedef itk::Image<RGBType,NDimension>			RGBImageType;
	typedef typename RGBImageType::Pointer			RGBImagePointer;
	typedef typename RGBImageType::ConstPointer		RGBImageConstPointer;
	//@}

	/**	@name	Transformation typedefs */
	//@{
	typedef vnl_double_3		TransVectorType;
	typedef vnl_double_3x3		RotMatrixType;
	//@}

	/// Object creation
	itkNewMacro(Self);

	/// RTTI
	itkTypeMacro(RGBRImage, RImage);

	/// Image dimension
	itkStaticConstMacro(ImageDimension, unsigned int, Superclass::ImageDimension);

	/**	@brief	Modify the RGBRImage
	 *
	 *	@details
	 *	Modified() calls will affect this object and will be propagated to all wrapped/encapsulated sub-images. All subclass
	 *	should overload this method.
	 */
	virtual void Modified() const;

	/**	@name LargestPossibleRegion, BufferedRegion, RequestedRegion. Will be delegated to the internal RGB image a */
	//@{
	//virtual void SetLargestPossibleRegion(const RegionType &region);
	//virtual void SetRequestedRegion(const RegionType &region);
	//virtual void SetBufferedRegion(const RegionType &region);

	virtual void CopyInformation(const DataObject *Data);

	//virtual void SetLargestPossibleRegion(const RegionType &Region, int FrameType);
	//virtual void SetRequestedRegion(const RegionType &Region, int FrameType);
	//virtual void SetBufferedRegion(const RegionType &Region, int FrameType);
	//@}

	/// Set the spacing. Will be delegated to the internal images
	virtual void SetSpacing(const SpacingType &Spacing);

	/// Set the origin. Will be delegated to the internal images
	virtual void SetOrigin(const PointType &Origin);

	/// Set the direction. Will be delegated to the internal images
	virtual void SetDirection(const DirectionType direction);

	virtual void SetLargestPossibleRegion(const RegionType &Region);
	virtual void SetRequestedRegion(const RegionType &Region);
	virtual void SetBufferedRegion(const RegionType &Region);

	/**	@brief	Graft from another image
	 *	@param	data	The object to graft
	 *
	 *	@details
	 *	This method will graft the data and information from another object.
	 *	If the object can be casted to a KinectImage the RGBImage will be grafted, too.
	 */
	virtual void Graft(const DataObject *data);

	/**	@brief	Perform a deep copy
	 *	@param	data	The data to copy from
	 *
	 *	@details
	 *	This method will perform a deep copy (in contrast to the Graft() 
	 *	method that performs a shallow copy) from the given object. 
	 *	If the object can be casted to a KinectImage the RGBImage will be grafted, too.
	 */
	virtual void DeepCopy(const DataObject *data);

	/**	@brief	Allocate the internal images (inherited from itk::ImageBase).
	 *
	 *	@details
	 *	Will allocate internal images. However, due to performance reasons, the world coordinate image will not be allocated automatically. 
	 *	Instead this should be done when the world coordinate image is explicitely requested (e.g. during ComputeRangeToWorldCoords()).
	 */
	virtual void Allocate();

	/// Disconnect the image from the pipeline
	virtual void DisconnectPipeline();

	/// Synchronize the RGB payload
	virtual void SynchronizeGenericImportImageContainers();

	/**	@name RGB image access */
	//@{
	virtual RGBImagePointer GetRGBImage();
	virtual RGBImageConstPointer GetRGBImage() const;
	virtual void SetRGBImage(RGBImagePointer RGBI);
	//@}

	/**	@name RGB image access */
	//@{
	virtual RGBImagePointer GetMappedRGBImage();
	virtual RGBImageConstPointer GetMappedRGBImage() const;
	virtual void SetMappedRGBImage(RGBImagePointer RGBI);
	//@}
	
	/**	@name	Get/set the camera parameters for the RGB camera */
	//@{
	virtual CameraParameters& GetCameraParametersRGB();
	virtual const CameraParameters& GetCameraParametersRGB() const;
	virtual void SetCameraParametersRGB(CameraParameters CameraParameters);
	//@}
	
	/**	@name	Get/set the camera translation */
	//@{
	virtual const TransVectorType& GetCameraTranslation() const;
	virtual void SetCameraTranslation(TransVectorType CameraTranslation);
	//@}
	
	/**	@name	Get/set the camera rotation */
	//@{
	virtual const RotMatrixType& GetCameraRotation() const;
	virtual void SetCameraRotation(RotMatrixType CameraRotation);
	//@}

	/// In general just computes the worldcoords, but here it needs to calculate a mapping as well
	virtual void Finish();

protected:
	/// Constructor
	RGBRImage();
	/// Destructor
	virtual ~RGBRImage();

	/// Print the object on a stream
	virtual void PrintSelf(std::ostream& os, itk::Indent indent) const;

	/// Maps the RGB image according to the relative transformation
	virtual void MapRGBData();

	/// Activate the mapping
	void SetMapping(bool activate);

protected:
	/// Payload idx for the RGB image
	unsigned int m_RGBDataPayloadIdx;

	/// Payload idx for the mapped RGB image
	unsigned int m_MappedRGBDataPayloadIdx;

	/// Whether mapping is activated
	bool m_MappingActive;
	/// The factor for resampling the world coordinate system
	int m_ResampleFactor;

	/// The camera parameters for the RGB camera
	CameraParameters m_CameraParametersRGB;
	/// The camera translation
	TransVectorType m_CameraTranslation;
	/// The camera rotation
	RotMatrixType m_CameraRotation;

	/**	@name	Mapping filter */
	//@{
	typedef RGBMappingImageFilter<typename Superclass::WorldCoordImageType,RGBImageType> MappingFilterType;
	typename MappingFilterType::Pointer m_MappingFilter;
	//@}

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

/** @name Template instantiations */
//@{
typedef RGBRImage<float,itk::Vector<unsigned char,3> > RGBRImageUCF2;
//@}	

} // namespace ritk

#endif // RGBRIMAGE_H__
