/* 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   SplineInterpolation.hpp
*/

#ifndef _SplineInterpolation_hpp
#define _SplineInterpolation_hpp

#include<ImLib3D/Image3D.hpp>
#include<ImLib3D/Interpolator3D.hpp>

typedef float Scalar;


enum InterpolationBoundaryType
{
	BOUNDARY_MIRROR,//! mirrors image at boundaries, theoritacally sound, but annoying
	BOUNDARY_ZERO,// assume image=0 outside, this is not properly implemented ...
	BOUNDARY_BACKGROUND// assume image=properties.background outside, this is not properly implemented ...
};
// ********************** SplineInterpolator3D ***********
//! Interpolation using B-splines
/*! B-spline interpolation is a 2 step method, first
compute a coefficient image then interpolate the coefficient
image
********************************************************/
template<class Im3DValue>
class SplineInterpolator3D : public Interpolator3D<Im3DValue>
{
	friend class AdaptativeSuperSampler;
	typedef Image3Dlinear<Im3DValue> ImageType;
	const ImageType *srcImage;
	ImageType *coeffImage;
	int splineDegree;
	void     ConvertToInterpolationCoefficients(vector<Im3DValue> &c,vector<Scalar> &z, Scalar Tolerance);
	Scalar   InitialCausalCoefficient          (vector<Im3DValue> &c,Scalar z, Scalar Tolerance);
	Scalar   InitialAntiCausalCoefficient      (vector<Im3DValue> &c,Scalar z );
	virtual Im3DValue ValueFast(const ImageType &ima,const float x,const float y,const float z);
	inline void ComputeInterpolationWeights(Scalar *xWeight,Scalar *yWeight,Scalar *zWeight,float x,float y,float z,int x0,int y0,int z0);
	;
	Im3DValue *background;
	InterpolationBoundaryType boundary;
public:
	void SetBackground(const Im3DValue &bg){background=new Im3DValue(bg);}
	int DBGvaluect;
	int DBGvaluefastct;
	//! In-place conversion of image to coefficients
	void     SamplesToCoefficients(ImageType &ima);
	//! compute value at non integer position using B-spline interpolation
	virtual Im3DValue Value(const ImageType &ima,const float x,const float y,const float z);
	ImageType *GetCoeffImage(){return coeffImage;}
	virtual void Reset(const ImageType *_srcImage)
	{
		if(coeffImage){delete coeffImage;coeffImage=NULL;}
		srcImage=_srcImage;
		if(!srcImage){return;}
		coeffImage=new ImageType();
		*coeffImage=*srcImage;
		SamplesToCoefficients(*coeffImage);
	}
	virtual ~SplineInterpolator3D()
	{
		if(coeffImage){delete coeffImage;}
	}

	SplineInterpolator3D(int _splineDegree,InterpolationBoundaryType _boundary=BOUNDARY_MIRROR):
		srcImage(NULL),coeffImage(NULL),
		splineDegree(_splineDegree),background(NULL),boundary(_boundary)
	{
		DBGvaluect=1;
		DBGvaluefastct=1;
	}
};


// ***************** type declarations  *****************************
typedef SplineInterpolator3D<float> SplineInterpolator3Df;


#include<ImLib3D/SplineInterpolation.hxx>
#endif // _SplineInterpolation_hpp
