/* ImLib3D
 * Copyright (c) 2001, ULP-IPB Strasbourg.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * 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 the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/*!
  \file   ImageProcessor.hxx
  \brief  This file contains the base class for all Image Processing classes

  <long description> 

  See AUTHORS and COPYING files for more information
  \date   2001-01-16
*/



#ifndef _ImageProcessor_hxx
#define _ImageProcessor_hxx

#include<ImLib3D/ImageProcessor.hpp>
#include<ImLib3D/InsertImage.hpp>

template <class ImageType>
void ImageProcessorArgs<ImageType>::AllSameSizeAssert()
{
	if(srcArgs.size()==0){ThrowError("ImageProcessorArgs::AllSameSizeAssert: no src args");}
	Size3D size=srcArgs[0].image->Size();
	uint i;
	for(i=1;i<srcArgs.size();i++)
	{
		if(size!=srcArgs[i].image->Size()){ThrowError("ImageProcessorArgs::AllSameSizeAssert: sizes differ");}
	}
	for(i=0;i<destArgs.size();i++)
	{
		if(size!=destArgs[i].image->Size()){ThrowError("ImageProcessorArgs::AllSameSizeAssert: sizes differ");}
	}
}

template <class ImageType>
void ImageProcessorArgs<ImageType>::InPlace()
{
	uint i;
	for(i=0;i<srcArgs.size();i++)
	{
		srcArgs[i].SetConst(false);
	}	
}

template <class ImageType>
void ImageProcessorArgs<ImageType>::SameSize()
{
	if(srcArgs.size()==0){ThrowError("ImageProcessorArgs::AllSameSizeAssert: no src args");}
	Size3D size=srcArgs[0].image->Size();
	uint i;
	for(i=1;i<srcArgs.size();i++)
	{
		if(size!=srcArgs[i].image->Size())
		{
			cout << "previous image size" << size << endl;
			cout << "image          size" << srcArgs[i].image->Size() << endl;
			ThrowError("ImageProcessorArgs::SameSize: src sizes differ");
		}
	}
	for(i=0;i<destArgs.size();i++)
	{
		destArgs[i].image->Resize(size);
	}
}

template <class ImageType>
void ImageProcessorArgs<ImageType>::SetDestSize(Size3D size)
{
	uint i;
	for(i=0;i<destArgs.size();i++)
	{
		destArgs[i].newSize=size;
	}
}

template <class ImageType>
void ImageProcessorArgs<ImageType>::UseLargerSrcBounds()
{
	uint i;
	useLargerSrcBounds=true;
	// find larger bounds
	for(i=0;i<srcArgs.size();i++)
	{
		bounds=bounds.LargerBound(srcArgs[i].image->Size());
	}
	// resize dest images
	for(i=0;i<destArgs.size();i++)
	{
		destArgs[i].newSize=bounds;
	}

}
template <class ImageType>
const ImageType &ImageProcessorArgs<ImageType>::GetSrc(int argn)
{
	if(!useLargerSrcBounds || srcArgs[argn].image->Size()==bounds)
	{
		return *srcArgs[argn].image;
	}
	else
	{
		// return resized duplicate of src
		ImageType *dup=new ImageType(bounds);
		srcArgs[argn].duplicate=dup;
		dup->Fill(dup->GetZero());
		IP3D::InsertImage(*dup,*srcArgs[argn].image,Vect3Di(0,0,0),*dup);
//		dup->InsertImage(*srcArgs[argn].image,Vect3Di(0,0,0));
		return *dup;
	}
}
template <class ImageType>
ImageType &ImageProcessorArgs<ImageType>::GetDest(int argn)
{
	// check if dest image needs to be duplicated
	for(uint i=0;i<srcArgs.size();i++)
	{
		// duplicate if src=dest and const
		// or if useLargerSrcBounds 
		if( (destArgs[argn].image==srcArgs[i].image && srcArgs[i].srcIsConst) ||
			(useLargerSrcBounds && destArgs[i].image->Size()!=bounds) 
			)
		{
			destArgs[argn].duplicate=new ImageType(*(srcArgs[i].image));
			if(destArgs[argn].newSize!=Size3D(0,0,0)){destArgs[argn].duplicate->Resize(destArgs[argn].newSize);}
			return *(destArgs[i].duplicate);
		}
	}
	if(destArgs[argn].newSize!=Size3D(0,0,0)){destArgs[argn].image->Resize(destArgs[argn].newSize);}
	return *(destArgs[argn].image);
}

template <class ImageType>
void  ImageProcessorArgs<ImageType>::Finished()
{
	uint i;
	for(i=0;i<destArgs.size();i++)
	{
		if(destArgs[i].duplicate)
		{
			(*destArgs[i].image)=(*destArgs[i].duplicate);
			delete destArgs[i].duplicate;
			destArgs[i].duplicate=NULL;
		}			
	}		

	for(i=0;i<srcArgs.size();i++)
	{
		if(srcArgs[i].duplicate)
		{
			delete srcArgs[i].duplicate;
		}			
	}		
}

#endif // _ImageProcessor_hxx
