text: ////////////////////////////////////////////////////////////////////////////
  //	File:		SiftGPU.h
  //	Author:		Changchang Wu
  //	Description :	interface for the SIFTGPU class.
  //					SiftGPU:	The SiftGPU Tool.  
  //					SiftGPUEX:	SiftGPU + viewer
  //					SiftParam:	Sift Parameters
  //					SiftMatchGPU: GPU SIFT Matcher;
  //
  //
  //	Copyright (c) 2007 University of North Carolina at Chapel Hill
  //	All Rights Reserved
  //
  //	Permission to use, copy, modify and distribute this software and its
  //	documentation for educational, research and non-profit purposes, without
  //	fee, and without a written agreement is hereby granted, provided that the
  //	above copyright notice and the following paragraph appear in all copies.
  //	
  //	The University of North Carolina at Chapel Hill make no representations
  //	about the suitability of this software for any purpose. It is provided
  //	'as is' without express or implied warranty. 
  //
  //	Please send BUG REPORTS to ccwu@cs.unc.edu
  //
  ////////////////////////////////////////////////////////////////////////////
  
  
  #ifndef GPU_SIFT_H
  #define GPU_SIFT_H
  
  #if  defined(_WIN32) 
  	#ifdef SIFTGPU_DLL
  		#ifdef DLL_EXPORT
  			#define SIFTGPU_EXPORT __declspec(dllexport)
  		#else
  			#define SIFTGPU_EXPORT __declspec(dllimport)
  		#endif
  	#else
  		#define SIFTGPU_EXPORT
  	#endif
  
      #define SIFTGPU_EXPORT_EXTERN SIFTGPU_EXPORT
  
  	#if _MSC_VER > 1000
  		#pragma once
  	#endif
  #else
  	#define SIFTGPU_EXPORT
      #define SIFTGPU_EXPORT_EXTERN extern "C"
  #endif
  
  ///////////////////////////////////////////////////////////////////
  //clss SiftParam
  //description: SIFT parameters
  ////////////////////////////////////////////////////////////////////
  class GlobalUtil;
  class SiftParam
  {
  public:
  	float*		_sigma;
  	float		_sigma_skip0; // 
  	float		_sigma_skip1; //
  	
  	//sigma of the first level
  	float		_sigma0;
  	float		_sigman;
  	int			_sigma_num;
  
  	//how many dog_level in an octave
  	int			_dog_level_num;
  	int			_level_num;
  
  	//starting level in an octave
  	int			_level_min;
  	int			_level_max;
  	int			_level_ds;
  	//dog threshold
  	float		_dog_threshold;
  	//edge elimination
  	float		_edge_threshold;
  	void		 ParseSiftParam();
  public:
  	float GetLevelSigma(int lev);
  	float GetInitialSmoothSigma(int octave_min);
  	SIFTGPU_EXPORT SiftParam();
  };
  
  class LiteWindow;
  class GLTexInput;
  class ShaderMan;
  class SiftPyramid;
  class ImageList;
  ////////////////////////////////////////////////////////////////
  //class SIftGPU
  //description: Interface of SiftGPU lib
  ////////////////////////////////////////////////////////////////
  class SiftGPU:public SiftParam
  {
  public:
  	enum
  	{
  		SIFTGPU_NOT_SUPPORTED = 0,
  		SIFTGPU_PARTIAL_SUPPORTED = 1, // detction works, but not orientation/descriptor
  		SIFTGPU_FULL_SUPPORTED = 2
  	};
  	typedef struct SiftKeypoint
  	{
  		float x, y, s, o; //x, y, scale, orientation.
  	}SiftKeypoint;
  protected: 
  	//when more than one images are specified
  	//_current indicates the active one
  	int		_current;
  	//_initialized indicates if the shaders and OpenGL/SIFT parameters are initialized
  	//they are initialized only once for one SiftGPU inistance
  	//that is, SIFT parameters will not be changed
  	int		_initialized;
  	//_image_loaded indicates if the current images are loaded
  	int		_image_loaded;
  	//the name of current input image
  	char*	_imgpath;
  	//_outpath containes the name of the output file
  	char*	_outpath;
  	//the list of image filenames
  	ImageList *    _list;
  	//the texture that holds loaded input image
  	GLTexInput *   _texImage;
  	//the SiftPyramid
  	SiftPyramid *  _pyramid;
  	//print out the command line options
  	static void PrintUsage();
  	//Initialize OpenGL and SIFT paremeters, and create the shaders accordingly
  	void InitSiftGPU();
  	//load the image list from a file
  	void LoadImageList(const char *imlist);
  public:
  	//timing results for 10 steps
  	float			    _timing[10];
      inline const char*  GetCurrentImagePath() {return _imgpath; }
  public:
  	//set the image list for processing
  	SIFTGPU_EXPORT virtual void SetImageList(int nimage, const char** filelist);
  	//get the number of SIFT features in current image
  	SIFTGPU_EXPORT virtual int	GetFeatureNum();
  	//save the SIFT result as a ANSCII/BINARY file 
  	SIFTGPU_EXPORT virtual void SaveSIFT(const char * szFileName);
  	//Copy the SIFT result to two vectors
  	SIFTGPU_EXPORT virtual void GetFeatureVector(SiftKeypoint * keys, float * descriptors);
  	//Set keypoint list before running sift to get descriptors
  	SIFTGPU_EXPORT virtual void SetKeypointList(int num, const SiftKeypoint * keys, int keys_have_orientation = 1);
  	//Enable downloading results to CPU. 
  	//create a new OpenGL context for processing
  	//call VerifyContextGL instead if you want to crate openGL context yourself, or your are 
  	//mixing mixing siftgpu with other openGL code
  	SIFTGPU_EXPORT virtual int CreateContextGL();
  	//verify the current opengl context..
  	//(for example, you call wglmakecurrent yourself and verify the current context)
  	SIFTGPU_EXPORT virtual int VerifyContextGL();
  	//check if all siftgpu functions are supported
  	SIFTGPU_EXPORT virtual int IsFullSupported();
  	//set verbose mode
  	SIFTGPU_EXPORT virtual void SetVerbose(int verbose = 4);
  	//set SiftGPU to brief display mode, which is faster
  	inline void SetVerboseBrief(){SetVerbose(2);};
  	//parse SiftGPU parameters
  	SIFTGPU_EXPORT virtual void ParseParam(int argc, char **argv);
  	//run SIFT on a new image given filename
  	SIFTGPU_EXPORT virtual int  RunSIFT(const char * imgpath);
  	//run SIFT on an image in the image list given the file index
  	SIFTGPU_EXPORT virtual int	RunSIFT(int index);
  	//run SIFT on a new image given the pixel data and format/type;
  	//gl_format (e.g. GL_LUMINANCE, GL_RGB) is the format of the pixel data
  	//gl_type (e.g. GL_UNSIGNED_BYTE, GL_FLOAT) is the data type of the pixel data;
  	//Check glTexImage2D(...format, type,...) for the accepted values
  	//Using image data of GL_LUMINANCE + GL_UNSIGNED_BYTE can minimize transfer time
  	SIFTGPU_EXPORT virtual int  RunSIFT(int width, int height,	const void * data, 
  										unsigned int gl_format, unsigned int gl_type);
  	//run SIFT on current image (specified by arguments), or processing the current image again
  	SIFTGPU_EXPORT virtual int  RunSIFT();
  	//run SIFT with keypoints on current image again. 
  	SIFTGPU_EXPORT virtual int  RunSIFT(int num, const SiftKeypoint * keys, int keys_have_orientation = 1);
  	//constructor, the parameter np is ignored..
  	SIFTGPU_EXPORT SiftGPU(int np = 1);
  	//destructor
  	SIFTGPU_EXPORT virtual ~SiftGPU();
  	//set the active pyramid...dropped function
      SIFTGPU_EXPORT virtual void SetActivePyramid(int index) {}
  	//retrieve the number of images in the image list
  	SIFTGPU_EXPORT virtual int GetImageCount();
  	//set parameter GlobalUtil::_ForceTightPyramid
  	SIFTGPU_EXPORT virtual void SetTightPyramid(int tight = 1);
  	//allocate pyramid for a given size of image
  	SIFTGPU_EXPORT virtual int AllocatePyramid(int width, int height);
  	//none of the texture in processing can be larger
  	//automatic down-sample is used if necessary. 
  	SIFTGPU_EXPORT virtual void SetMaxDimension(int sz);
  	///
  public:
  	//overload the new operator because delete operator is virtual
  	//and it is operating on the heap inside the dll (due to the 
  	//compiler setting of /MT and /MTd). Without the overloaded operator
  	//deleting a SiftGPU object will cause a heap corruption in the 
  	//static link case (but not for the runtime dll loading).
  	SIFTGPU_EXPORT void* operator new (size_t size); 
  };
  
  
  
  ////////////////////////////////////////////////////////////////
  //class SIftGPUEX
  //description: adds some visualization functions to the interface of SiftGPU
  ////////////////////////////////////////////////////////////////
  
  class SiftGPUEX:public SiftGPU
  {
  	//view mode
  	int	_view;
  	//sub view mode
  	int _sub_view;
  	//whether display a debug view
  	int _view_debug;
  	//colors for SIFT feature display
  	enum{COLOR_NUM = 36};
  	float _colors[COLOR_NUM*3];
  	//display functions
  	void DisplayInput();	//display gray level image of input image	
  	void DisplayDebug();	//display debug view
  	void DisplayFeatureBox(int i);	//display SIFT features
  	void DisplayLevel(void (*UseDisplayShader)(), int i);		//display one level image
  	void DisplayOctave(void (*UseDisplayShader)(), int i);		//display all images in one octave
  	//display different content of Pyramid by specifying different data and display shader
  	//the first nskip1 levels and the last nskip2 levels are skiped in display
  	void DisplayPyramid( void (*UseDisplayShader)(), int dataName, int nskip1 = 0, int nskip2 = 0);
  	//use HSVtoRGB to generate random colors
  	static void HSVtoRGB(float hsv[3],float rgb[3]);
  
  public:
  	SIFTGPU_EXPORT SiftGPUEX();
  	//change view mode
  	SIFTGPU_EXPORT void SetView(int view, int sub_view, char * title);
  	//display current view
  	SIFTGPU_EXPORT void DisplaySIFT();
  	//toggle debug mode on/off
  	SIFTGPU_EXPORT void ToggleDisplayDebug();
  	//randomize the display colors
  	SIFTGPU_EXPORT void RandomizeColor();
  	//retrieve the size of current input image
  	SIFTGPU_EXPORT void GetImageDimension(int &w, int&h);
  	//get the location of the window specified by user
  	SIFTGPU_EXPORT void GetInitWindowPotition(int& x, int& y);
  };
  
  ///matcher export
  //This is a gpu-based sift match implementation. 
  class SiftMatchGPU
  {
  public:
  	enum SIFTMATCH_LANGUAGE	{
  		SIFTMATCH_SAME_AS_SIFTGPU = 0, //when siftgpu already initialized.
  		SIFTMATCH_GLSL = 2,
  		SIFTMATCH_CUDA = 3,
          SIFTMATCH_CUDA_DEVICE0 = 3 //to use device i, use SIFTMATCH_CUDA_DEVICE0 + i
  	};
  private:
  	int				__max_sift;
  	int				__language;
  	SiftMatchGPU *	__matcher;
  	virtual void   InitSiftMatch(){}
  protected:
  	//move the two functions here for derived class
  	SIFTGPU_EXPORT virtual int  _CreateContextGL();
  	SIFTGPU_EXPORT virtual int  _VerifyContextGL();
  public:
  	//OpenGL Context creation/verification, initialization is done automatically inside
  	inline int  CreateContextGL() {return _CreateContextGL();}
  	inline int  VerifyContextGL() {return _VerifyContextGL();}
  
  	//Consructor, the argument specifies the maximum number of features to match
  	SIFTGPU_EXPORT SiftMatchGPU(int max_sift = 4096);
  
  	//change gpu_language, check the enumerants in SIFTMATCH_LANGUAGE.
  	SIFTGPU_EXPORT virtual void SetLanguage(int gpu_language);
  
      //after calling SetLanguage, you can call SetDeviceParam to select GPU
      //-winpos, -display, -cuda [device_id] 
      //This is only used when you call CreateContextGL..
  	//This function doesn't change the language. 
      SIFTGPU_EXPORT virtual void SetDeviceParam(int argc, char**argv);
  
  	//change the maximum of features to match whenever you want
  	SIFTGPU_EXPORT virtual void SetMaxSift(int max_sift);
  	//desctructor
  	SIFTGPU_EXPORT virtual ~SiftMatchGPU();
  
  	//Specifiy descriptors to match, index = [0/1] for two features sets respectively
  	//Option1, use float descriptors, and they be already normalized to 1.0
  	SIFTGPU_EXPORT virtual void SetDescriptors(int index, int num, const float* descriptors, int id  = -1);
  	//Option 2 unsigned char descriptors. They must be already normalized to 512
  	SIFTGPU_EXPORT virtual void SetDescriptors(int index, int num, const unsigned char * descriptors, int id = -1);
  
  	//match two sets of features, the function RETURNS the number of matches.
  	//Given two normalized descriptor d1,d2, the distance here is acos(d1 *d2);
  	SIFTGPU_EXPORT virtual int  GetSiftMatch(
  				int max_match,	// the length of the match_buffer.
  				int match_buffer[][2], //buffer to receive the matched feature indices
  				float distmax = 0.7,	//maximum distance of sift descriptor
  				float ratiomax = 0.8,	//maximum distance ratio
  				int mutual_best_match = 1); //mutual best match or one way
  
  	//two functions for guded matching, two constraints can be used 
  	//one homography and one fundamental matrix, the use is as follows
  	//1. for each image, first call SetDescriptor then call SetFeatureLocation
  	//2. Call GetGuidedSiftMatch
  	//input feature location is a vector of [float x, float y, float skip[gap]]
  	SIFTGPU_EXPORT virtual void SetFeautreLocation(int index, const float* locations, int gap = 0);
  	inline void SetFeatureLocation(int index, const SiftGPU::SiftKeypoint * keys)
  	{
  		SetFeautreLocation(index, (const float*) keys, 2);
  	}
  
  	//use a guiding Homography H and a guiding Fundamental Matrix F to compute feature matches
  	//the function returns the number of matches.
  	SIFTGPU_EXPORT virtual int  GetGuidedSiftMatch(
  					int max_match, int match_buffer[][2], //buffer to recieve 
  					float H[3][3],			//homography matrix,  (Set NULL to skip)
  					float F[3][3],			//fundamental matrix, (Set NULL to skip)
  					float distmax = 0.7,	//maximum distance of sift descriptor
  					float ratiomax = 0.8,   //maximum distance ratio
  					float hdistmax = 32,    //threshold for |H * x1 - x2|_1 
  					float fdistmax = 16,    //threshold for sampson error of x2'FX1
  					int mutual_best_match = 1); //mutual best or one way
  
  public:
  	//overload the new operator, the same reason as SiftGPU above
  	SIFTGPU_EXPORT void* operator new (size_t size);
  };
  
  typedef SiftGPU::SiftKeypoint SiftKeypoint;
  
  //Two exported global functions used to create SiftGPU and SiftMatchGPU
  SIFTGPU_EXPORT_EXTERN SiftGPU * CreateNewSiftGPU(int np =1);
  SIFTGPU_EXPORT_EXTERN SiftMatchGPU* CreateNewSiftMatchGPU(int max_sift = 4096);
  
  
  ////////////////////////////////////////////////////////////////////////////
  class ComboSiftGPU: public SiftGPU, public SiftMatchGPU 
  {
  public:
  	///////////////////////////////////////////////
  	SIFTGPU_EXPORT void* operator new (size_t size); 
  };
  SIFTGPU_EXPORT_EXTERN ComboSiftGPU* CreateComboSiftGPU(); 
  
  /////////////////////////////////////////////////////////////////////////////////////////////
  //Multi-process mode and remote mode
  SIFTGPU_EXPORT_EXTERN ComboSiftGPU* CreateRemoteSiftGPU(int port = 7777, char* remote_server = NULL);
  //Run SiftGPU computation on a remote computer/process/thread
  //if( remote_server == NULL) 
  //			a local server is created in a different process and connected
  //			multiple-GPU can be used by creating multiple instances
  //			GPU selection done through SiftGPU::ParseParam function
  //otherwise, 
  //			Assumes the existenc of a remote server and connects to it
  //			GPU selection skipped if already done on the server-end
  //			RUN server: server_siftgpu -server port [siftgpu_param]
  //example:
  //	ComboSiftGPU * combo = CreateRemoteSiftGPU(7777, "my.gpuserver.com");
  //	SiftGPU* siftgpu = combo, SiftMatchGPU * matcher = combo;
  //  siftgpu->ParseParam... siftgpu->CreateContextGL..
  //  matcher->SetLanguage...matcher->VerifyContextGL...
  //  // GPU-selection is done throught siftgpu->ParseParam, 
  //  // it doesn't really initialize SiftGPU untill you call CreateContextGL/VerifyContextGL
  //  delete combo;
  
  ////////////////////////////////////////////////////////////////////////
  //two internally used function.
  SIFTGPU_EXPORT int  CreateLiteWindow(LiteWindow* window);
  SIFTGPU_EXPORT void RunServerLoop(int port, int argc, char** argv);
  #endif 
  