



#pragma once



#include "ofMain.h"



#include "ofxOpenCvBlob.h"

// opencv
#include "opencv2/core/core_c.h"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"




#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
#include <pthread.h>






// ofxOpenCV version 1.0 does not exist, but is based on the Processing OpenCv native library version 1.0
// set to 2.0 (or more) to fit to Processing library developpement
#define OFX_OPENCV_VERSION				"2.0 beta 4"
#define OFX_OPENCV_LIB_VERSION			CV_VERSION


#define OFX_OPENCV_FPS					(int)(1000.f*(1.f/30.f))


#define OFX_OPENCV_MOVIE_WIDTH			CV_CAP_PROP_FRAME_WIDTH
#define OFX_OPENCV_MOVIE_HEIGHT			CV_CAP_PROP_FRAME_HEIGHT
#define OFX_OPENCV_MOVIE_FPS			CV_CAP_PROP_FPS
#define OFX_OPENCV_MOVIE_FRAME			CV_CAP_PROP_POS_FRAMES
#define OFX_OPENCV_MOVIE_FRAMECOUNT		CV_CAP_PROP_FRAME_COUNT
#define OFX_OPENCV_MOVIE_RATIO			CV_CAP_PROP_POS_AVI_RATIO
#define OFX_OPENCV_MOVIE_MILLIS			CV_CAP_PROP_POS_MSEC

#define OFX_OPENCV_CAMERA_WIDTH			CV_CAP_PROP_FRAME_WIDTH
#define OFX_OPENCV_CAMERA_HEIGHT		CV_CAP_PROP_FRAME_HEIGHT
#define OFX_OPENCV_CAMERA_FPS			CV_CAP_PROP_FPS

#define	OFX_OPENCV_BLUR					CV_BLUR
#define	OFX_OPENCV_GAUSSIAN				CV_GAUSSIAN
#define	OFX_OPENCV_MEDIAN				CV_MEDIAN
#define	OFX_OPENCV_BILATERAL			CV_BILATERAL

#define OFX_OPENCV_INTER_NN				CV_INTER_NN
#define	OFX_OPENCV_INTER_LINEAR			CV_INTER_LINEAR
#define	OFX_OPENCV_INTER_CUBIC			CV_INTER_CUBIC
#define	OFX_OPENCV_INTER_AREA			CV_INTER_AREA


#define OFX_OPENCV_MAX_NUMOF_BLOBS		256
#define OFX_OPENCV_MAX_VERTICES			1024



/**
 * Type of Image
 */
#define OFX_OPENCV_SOURCE				0
#define OFX_OPENCV_BUFFER				1
#define OFX_OPENCV_MEMORY				2
#define OFX_OPENCV_CAPTURE				4


/**
 * Colorspace of image
 */
#define OFX_OPENCV_GRAY					12
#define OFX_OPENCV_RGB					1
#define OFX_OPENCV_HSB					3
#define OFX_OPENCV_HSV					OFX_OPENCV_HSB

/**
 * Flip mode
 */
#define OFX_OPENCV_FLIP_VERTICAL		0
#define OFX_OPENCV_FLIP_HORIZONTAL		1
#define OFX_OPENCV_FLIP_V				OFX_OPENCV_FLIP_VERTICAL
#define OFX_OPENCV_FLIP_H				OFX_OPENCV_FLIP_HORIZONTAL
#define OFX_OPENCV_FLIP_BOTH			-1
#define OFX_OPENCV_FLIP_NONE			-2








// namespace
using namespace std;




// Processing native based object
// Openframeworks ofxOpenCV object
class ofxOpenCV
{
	public :
			
			
		ofxOpenCV();
		virtual ~ofxOpenCV();
		
		
		
		
		void allocate ( int width, int height, int mode=OFX_OPENCV_RGB );
		void deallocate( int type=-1 );
		
		unsigned char * pixels( int kind );
		
		// --
		
		// frame rate set to 0 disable internal thread
		bool capture( int w, int h, int index=0, float framerate=-1 );		// -1 means try to retrieve device rate or use by default 30 fps
		bool movie( string file, int w=-1, int h=-1, float framerate=-1 );	// -1 means try to retrieve movie properties (30fps by default)
		bool image( string file, int w=-1, int h=-1 );						// -1 means use image dimensions
		
		
		// TODO : all movie methods must be inside CvPlayer class
		void read(); // grab frame from camera or movie file
		void next();
		void previous();
		void jump( float value, int type=CV_CAP_PROP_POS_AVI_RATIO );
		float property( int which );
		
		void flip( int mode=OFX_OPENCV_FLIP_H );
		
		
		#define loadImage image // Processing syntax
		// TODO: ofImage image() ?
		
		// --
		
		void remember( int kind=OFX_OPENCV_SOURCE, int mode=OFX_OPENCV_FLIP_NONE );
		void restore( int type=OFX_OPENCV_RGB );
		void absDiff();
		void threshold( float value, float max=255, int type=CV_THRESH_BINARY );
		void adaptiveThreshold( float max, int method=CV_ADAPTIVE_THRESH_MEAN_C, int type=CV_THRESH_BINARY, int block_size=3, float mean_constant=5.0 );
		void convert( int type );
		
		// --
		
		void interpolation( int type );
		
		bool copy( string file, float x=0, float y=0 );
		bool copy( string file, float srcx, float srcy, float srcw, float srch, float dstx, float desty, float dstw, float dsth );
		bool copy( IplImage * src, float x=0, float y=0 );
		bool copy( IplImage * src, float srcx, float srcy, float srcw, float srch, float dstx, float desty, float dstw, float dsth );
		bool copy( unsigned char* pixels, int step, float x=0, float y=0 );
		bool copy( unsigned char* pixels, int step, float srcx, float srcy, float srcw, float srch, float dstx, float dsty, float dstw, float dsth );
		
		// -- 
		
		int blobs( vector<ofxOpenCvBlob> &list, int minArea, int maxArea, int maxBlobs=1, bool findHoles=false, bool approx=true );
		
		// --
	
		#define clearROI() ROI();
		void ROI( float x=0, float y=0, float width=0, float height=0 );
		void invert();
		void blur( int type, int param1, int param2=0, float param3=0.f, float param4=0.f );
		void brightnessContrast( int brightness, int contrast );
		
		
		// -- detection 
		bool cascade( string file );
		int detect( vector<ofRectangle> &list, float scale=1.1f, int min_neighbors=3, int flags=0, int minw=0, int minh=0 );
		
		
		// -- draw
		void draw( float x=0, float y=0, int kind=OFX_OPENCV_BUFFER );
		void draw( float x, float y, float width, float height, int kind=OFX_OPENCV_BUFFER, int mode=GL_BGR );
		
		
		// --
		
		static bool blobarea_comparator( const CvSeq *contour1, const CvSeq *contour2 );
		
		
		
		int width;
		int height;
		int interpolation_mode;
		
		
		
		// the buffer color space
		// could be RGB, GRAY, HSV (HSB)
		int colormode;
		
		int flipmode;
		
		IplImage	* buffer;
		IplImage	* source;
		IplImage	* memory;
		
		
		CvCapture	* cam;
		CvHaarClassifierCascade	* haarcascade;
		
		
		GLuint tex;
	
		
		
		// working with input stream	
	
		void start();			// start reading movie file or input stream
		void stop();			// stop  reading movie and go to the begining or stop input stream
		void pause();			// pause the movie playback or input stream
		bool playing();			// whether the camera capture or movie reader is running
		bool available();		// returns true when there is a new frame
		
		//void speed( float rate );
		
		#define isPlaying playing		// if isPlaying() is more explicite
		#define isRunning playing		// or isRunning()
		#define play start				// for whose prefer use play() instead of start()
		#define isFrameNew available	// like other addon syntax
		
		
	// ---------------------------------------------------------------------------------------------
	
	protected:
		
		
		
		int fps;
		bool bnew_frame;
		
	
		// thread
		bool				running;		// whether the camera capture or movie reader is running
		pthread_t			thread;
		pthread_mutex_t		mutex;
		
		static void * run( void *ptr );


	// ---------------------------------------------------------------------------------------------
	
	//private:
	
		
			
};
