/* 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  BitImage3D.hxx  */

#ifndef _BitImage3D_hxx
#define _BitImage3D_hxx

// *******************************************************
// template implementations for BitImage3D
// *******************************************************


template<class FieldType,int bitsPerValue,class ValueType>
string 
BitImage3D<FieldType,bitsPerValue,ValueType>::GetTypeName() const 
{
	return SPrintf("BitImage3D<%s,%d,%s>",TypeName<FieldType>(),bitsPerValue,TypeName<ValueType>());
}


template<class FieldType,int bitsPerValue,class ValueType>
void 
BitImage3D<FieldType,bitsPerValue,ValueType>::Write(ImLib3DFile *file,XMLNode *parentNode,XMLNode *node) const
{
	node=CreateWriteNode(file,parentNode,node);
	// **** Optionally add unset image properties ***
	// set image type (Image3Df, Field3D etc....) 
	if(!file->HasProperty(node,"Type")){node->add_property("Type",GetTypeName());}
	// store Data (underlying image) information
	imageData.Write(file,node);
	// write parents data (image size and properties)
	Image3D::Write(file,NULL,node);
}
template<class FieldType,int bitsPerValue,class ValueType>
void 
BitImage3D<FieldType,bitsPerValue,ValueType>::Read(ImLib3DFile *file,XMLNode *parentNode,XMLNode *node)
{
	node=CreateReadNode(file,parentNode,node);
	Image3D::Read(file,NULL,node);
	//type checking
	string type=file->GetProperty(node,"Type");
	if(type!=GetTypeName()){ThrowError("ReadFromXMLTree: Expected type:\"%s\" found type:\"%s\"",GetTypeName(),type);}
	//image data
	imageData.Read(file,node);
}

// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
void 
BitImage3D<FieldType,bitsPerValue,ValueType>::Resize(const Size3D &newSize)
{
//	if(newSize==Size()){return;}
	Image3D::Resize(newSize);
	imageData.Resize(Size3D((newSize.width*bitsPerValue+bitsPerField-1)/bitsPerField,newSize.height,newSize.depth));
	widthXheight=width*height;
	imageDataEnd=iteratorFast(this,GetNVoxels());
	const_imageDataEnd=const_iteratorFast(this,GetNVoxels());
}


// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>& 
BitImage3D<FieldType,bitsPerValue,ValueType>::operator=(const BitImage3D<FieldType,bitsPerValue,ValueType> & other)
{
	if(other.Size()!=Size()){Resize(other.Size());}
	if (this == &other){return *this;}
	// call parent operator =
	*((Image3D*)this)=other;
	// now copy the actual image data	
	imageData=other.imageData;
	return *this;
}


// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
bool 
BitImage3D<FieldType,bitsPerValue,ValueType>::operator==(const BitImage3D<FieldType,bitsPerValue,ValueType> & other) const
{
	if(other.Size()!=Size()){return false;}

	const_iteratorFast pOrig;
	const_iteratorXYZ p;
	for (p = begin(),pOrig=other.begin(); p != end(); p++,pOrig++)
	{
		if(!((*p) == (*pOrig))){return false;}
	}		
	
	if(!(properties==other.properties)){return false;}
	
	return true;
}



// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>::~BitImage3D()
{
}

// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>::BitImage3D(int _width, int _height, int _depth) : 
	Image3D(_width,_height,_depth)
{
	Resize(Size3D(_width,_height,_depth));
}
// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>::BitImage3D():
	Image3D()
{
	Resize(Size3D(0,0,0));
}

// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>::BitImage3D(int cubeSideSize) :
	Image3D(cubeSideSize,cubeSideSize,cubeSideSize)
{
	Resize(Size3D(cubeSideSize,cubeSideSize,cubeSideSize));
}

// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>::BitImage3D(const Size3D &size):
	Image3D(size)
{
	Resize(size);
}

// *******************************************************
template<class FieldType,int bitsPerValue,class ValueType>
BitImage3D<FieldType,bitsPerValue,ValueType>::BitImage3D(const BitImage3D & origCont) :
	Image3D(origCont)
{
	Resize(origCont.Size());
	(*this)=origCont;
}

#endif // _BitImage3D_hxx
