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

	Program:		Range Imaging Toolkit (RITK)
	Module:			ritkRImage2DActorPipeline.cxx
	Version:		$Revision: 3133 $
	Date:			$Date: 2012-04-19 10:50:33 +0200 (Do, 19 Apr 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

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

#include "ritkRImage2DActorPipeline.h"

#include <vtkObjectFactory.h>

#include <itkRescaleIntensityImageFilter.h>
#include <itkImageRegionIterator.h>
#include <vtkBMPReader.h>


namespace ritk
{

// Implements static RImage2DActorPipeline *New();
vtkStandardNewMacro(RImage2DActorPipeline);


//----------------------------------------------------------------------------
RImage2DActorPipeline::RImage2DActorPipeline()
{
	// Default visualization mode is RGB
	m_VisualizationMode = RGB;

	// By default, no LUT
	m_UseLUT = false;

	// Initialize the LUT
	m_LUT = vtkSmartPointer<vtkLookupTable>::New();
	unsigned int JetLength = 200;
	m_LUT->SetNumberOfColors(LUT_Jet_Length);
	for( unsigned int i = 0; i < JetLength; i++ ) 
		m_LUT->SetTableValue(JetLength-1-i, LUT_Jet[i][0], LUT_Jet[i][1], LUT_Jet[i][2], 1.0); 

	// Initialize the ITK to VTK converter @todo RGB_ISSUE
	// m_ImageToVTKImageFilter = ImageToVTKImageFilterType::New();
}


//----------------------------------------------------------------------------
RImage2DActorPipeline::~RImage2DActorPipeline()
{
}


//----------------------------------------------------------------------------
void
RImage2DActorPipeline::SetVisualizationMode(VisualizationMode Mode)
{
	// We're changing the pipeline so lock!
	Lock();

	// Update the mode
	m_VisualizationMode = Mode;

	// Done here
	Unlock();
}


//----------------------------------------------------------------------------
void
RImage2DActorPipeline::UseLUT(bool UseLUT)
{
	// We're changing the pipeline so lock!
	Lock();

	// Update the flag
	m_UseLUT = UseLUT;

	// Done here
	Unlock();
}


//----------------------------------------------------------------------------
void
RImage2DActorPipeline::SetData(VTKImageDataPointer Data, bool DeepCopy)
{
	// Note: Don't lock here as this will be done in the superclass. Locking here
	// would cause a dead lock
	Superclass::SetData(Data, DeepCopy);
}



//----------------------------------------------------------------------------
void
RImage2DActorPipeline::SetData(const RImageType *Image)
{
	// @todo RGB_ISSUE
#if 0
	// We're using a 8bit grey level image to get the plain data from the range image
	typedef itk::Image<unsigned char,2>  PlainImageType;
	PlainImageType::Pointer PlainImage = NULL;

	if ( m_VisualizationMode == RGB )
	{
    /**
		// Rescale and cast the Grayscale image
		typedef itk::RescaleIntensityImageFilter<RImageType::GrayscaleImageType,PlainImageType> RescalerType;
		RescalerType::Pointer Rescaler = RescalerType::New();
		Rescaler->SetOutputMinimum(0);
		Rescaler->SetOutputMaximum(255);
		Rescaler->SetInput(Image->GetGrayscaleImage());
		Rescaler->GetOutput()->SetRequestedRegion(Image->GetGrayscaleImage()->GetRequestedRegion());
		Rescaler->Update();
		PlainImage = Rescaler->GetOutput();
*/
		// Create the VTK image data from the image
    m_ImageToVTKImageFilter->SetInput(Image->GetRGBImage());
		m_ImageToVTKImageFilter->Update();

		// Pass the data to the superclass. We don't need a deep copy anymore due to our smartpointer
		Superclass::SetData(m_ImageToVTKImageFilter->GetOutput(), false);
	}
	else if ( m_VisualizationMode == ZBUFFER )
	{
		// Extract the z values
		typedef itk::Image<RImageType::WorldCoordRealType> zImageType;
		zImageType::Pointer zImage = zImageType::New();
		zImage->SetRegions(Image->GetRequestedRegion());
		zImage->Allocate();
		typedef itk::ImageRegionConstIterator<RImageType::WorldCoordImageType> WCIteratorType;
		typedef itk::ImageRegionIterator<zImageType> zIteratorType;
		WCIteratorType itWC(Image->GetWorldCoordImage(),Image->GetWorldCoordImage()->GetRequestedRegion());
		zIteratorType itZ(zImage,zImage->GetRequestedRegion());
		for ( itWC.GoToBegin(),itZ.GoToBegin(); !itZ.IsAtEnd(); ++itWC,++itZ )
			itZ.Value() = itWC.Value()[2];

		// Rescale and cast the z image
		typedef itk::RescaleIntensityImageFilter<zImageType,PlainImageType> RescalerType;
		RescalerType::Pointer Rescaler = RescalerType::New();
		Rescaler->SetOutputMinimum(0);
		Rescaler->SetOutputMaximum(255);
		Rescaler->SetInput(zImage);
		Rescaler->Update();
		PlainImage = Rescaler->GetOutput();

    RImageType::RGBImagePointer rgbImg = RImageType::RGBImageType::New();
    rgbImg->SetRegions(Image->GetRequestedRegion());
    rgbImg->Allocate();
    typedef itk::ImageRegionConstIterator<PlainImageType> PlainIt;
    typedef itk::ImageRegionIterator<RImageType::RGBImageType> RGBIt;
    PlainIt itPlain(PlainImage, PlainImage->GetRequestedRegion());
    RGBIt itRGB(rgbImg, rgbImg->GetRequestedRegion());
    for(itPlain.GoToBegin(),itRGB.GoToBegin(); !itPlain.IsAtEnd(); ++itPlain, ++itRGB)
    {
      itRGB.Value()[0] = itPlain.Value();
      itRGB.Value()[1] = itPlain.Value();
      itRGB.Value()[2] = itPlain.Value();
    }

		// Create the VTK image data from the range image
		m_ImageToVTKImageFilter->SetInput(rgbImg);
		m_ImageToVTKImageFilter->Update();

		//// Pass the data to the superclass. We don't need a deep copy anymore due to our smartpointer
		Superclass::SetData(m_ImageToVTKImageFilter->GetOutput(), false);

		//// Note: Instead of rescaling previous versions had a fixed min and max.
		//// This makes sense as we would have a frame independent range
		///*double max = 1000;
		//double d2norm = (itWC.Value()[2]-minZ)/(maxZ-minZ)*255;*/
	}
	else
	{
		// This should never happen...
		std::cout << "RImage2DActorPipeline: Unknown visualization type..." << std::endl;
	}

	return;
#endif
}

} // end namespace ritk
