/*   DTICrop
Crop the DT image in nrrd format
---Li Yang, May 2008
*/


#include <iostream>
#include <string.h>
#include <stdio.h>
#include "itkDiffusionTensor3D.h"
#include "itkImage.h"
#include "itkImageFileWriter.h"
#include "itkImageFileReader.h"
#include "itkNrrdImageIO.h"
#include "itkNiftiImageIO.h"
#include "itkRegionOfInterestImageFilter.h"

int main(int argc, char *argv[])
{

	if( argc<9 )
	{
		std::cout<<"Usage: DTICrop input XBegin XEnd YBegin YEnd ZBegin ZEnd output\n";
		std::cout<<"  input: the input DT image in Nrrd format or Nifti\n";
		std::cout<<"  XBegin XEnd: the begin and end slice number in x dimension (start from 1)\n";
		std::cout<<"  YBegin YEnd: the begin and end slice number in y dimension (start from 1)\n";
		std::cout<<"  ZBegin ZEnd: the begin and end slice number in z dimension (start from 1)\n";
		std::cout<<"  output: the cropped image (could be different format from input)\n";
		exit(0);
	}  

	//get the crop range
	int XB= atoi(argv[2]);
	int XE= atoi(argv[3]);
	int YB= atoi(argv[4]);
	int YE= atoi(argv[5]);
	int ZB= atoi(argv[6]);
	int ZE= atoi(argv[7]);

	//read in the DT image
	typedef itk::DiffusionTensor3D<float> PixelType;
	typedef itk::Image< PixelType, 3 > ImageType;
	typedef itk::NrrdImageIO ImageIOTypeNrrd;
	typedef itk::NiftiImageIO ImageIOTypeNifti;
	typedef itk::ImageFileWriter< ImageType > WriterType;
	typedef itk::ImageFileReader< ImageType > ReaderType;
	typedef itk::RegionOfInterestImageFilter< ImageType, ImageType > FilterType;
	
	FilterType::Pointer filter = FilterType::New();
	WriterType::Pointer writer = WriterType::New();
	ReaderType::Pointer reader = ReaderType::New();
	ImageIOTypeNrrd::Pointer NrrdIO = ImageIOTypeNrrd::New();
	ImageIOTypeNifti::Pointer NiftiIO = ImageIOTypeNifti::New();
	ImageType::Pointer image = ImageType::New();

	ImageType::IndexType start;
	start[0] = XB-1;
	start[1] = YB-1;
	start[2] = ZB-1;
	
	ImageType::SizeType size;
	size[0] = XE-XB+1;
	size[1] = YE-YB+1;
	size[2] = ZE-ZB+1;

	ImageType::RegionType desiredRegion;
	desiredRegion.SetSize( size );
	desiredRegion.SetIndex( start );

	filter->SetRegionOfInterest( desiredRegion );

	writer->SetFileName( argv[8] );
	reader->SetFileName( argv[1] );

	if ((strstr(argv[1],".nhdr")!=NULL)||(strstr(argv[1],".nrrd")!=NULL))
	{
		reader->SetImageIO( NrrdIO );
	}
	else if ((strstr(argv[1],".nii")!=NULL)||(strstr(argv[1],".hdr")!=NULL))
	{
		reader->SetImageIO( NiftiIO );
	} 
	else
	{
		std::cout<<"only support Nrrd or Nifti format\n";
		exit(0);
	}  	
	
	reader->Update();
	image = reader->GetOutput();
	filter->SetInput( image );
	filter->Update();

	image = filter->GetOutput();
	//swap pixelValue[2] and pixelValue[3], the input and output are different format
	bool input = (strstr(argv[1],".nii")!=NULL)||(strstr(argv[1],".hdr")!=NULL);
    bool output = (strstr(argv[8],".nii")!=NULL)||(strstr(argv[8],".hdr")!=NULL);
	if (input!=output)
	{
		ImageType::RegionType Region = image->GetLargestPossibleRegion();
		ImageType::SizeType Size = Region.GetSize();
		ImageType::PixelType pixelValue;
		ImageType::IndexType pixelIndex;
		float temp = 0;

		for (int i=0; i<Size[0]; i++)
		{
			for (int j=0; j<Size[1]; j++)
			{
				for (int k=0; k<Size[2]; k++)
				{
					pixelIndex[0] = i;
					pixelIndex[1] = j;
					pixelIndex[2] = k;
					pixelValue = image->GetPixel( pixelIndex );

					temp = pixelValue[2];
					pixelValue[2] = pixelValue[3];
					pixelValue[3] = temp;

					image->SetPixel(pixelIndex, pixelValue);
				}
			}
		}
	}

	if ((strstr(argv[8],".nhdr")!=NULL)||(strstr(argv[8],".nrrd")!=NULL))
	{
		writer->SetImageIO( NrrdIO );
	}
	else if ((strstr(argv[8],".nii")!=NULL)||(strstr(argv[8],".hdr")!=NULL))
	{
		writer->SetImageIO( NiftiIO );
	} 
	else
	{
		std::cout<<"only support Nrrd or Nifti format\n";
		exit(0);
	}  	
	writer->SetInput( image );
		
	try
	{
		writer->Update();
	}
	catch( itk::ExceptionObject & err )
	{
		std::cerr << "ExceptionObject caught !" << std::endl;
		std::cerr << err << std::endl;
		return EXIT_FAILURE;
	}

}