#include "ofCvFloatImage.h"
#include "ofCvGrayscaleImage.h"
#include "ofCvColorImage.h"

//------------------------------------------------------------------------------------
ofCvFloatImage::ofCvFloatImage(){
	width = height = 0;;
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::allocate(int _w, int _h){
	cvImage 			= cvCreateImage(cvSize(_w,_h), IPL_DEPTH_32F,1);
	cvImageTemp			= cvCreateImage(cvSize(_w,_h), IPL_DEPTH_32F,1);
	pixels 				= new unsigned char[_w*_h];
	width 				= _w;
	height 				= _h;
	tex.allocate(width, height, GL_LUMINANCE);
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::clear(){
	cvReleaseImage(&cvImage);
	cvReleaseImage(&cvImageTemp);
	delete pixels;
	tex.clear();
	width = height = 0;;
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::set(int value){
	cvSet(cvImage, cvScalar(value));
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::setFromGrayscaleImage(ofCvGrayscaleImage & mom){
	//cvCvtColor( mom.getCvImage() ,cvImage, CV_RGB2GRAY); 
	cvConvertScale( mom.getCvImage(), cvImage, 1, 0 );

}



//-------------------------------------------------------------------------------------
void ofCvFloatImage::setFromPixels(unsigned char * _pixels, int w, int h){
	
	IplImage		* cvTempImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U,1);
    
    cvSetImageData(cvTempImage,  _pixels, w); 
     
	for (int i = 0; i < h; i++){
		memcpy(pixels + (i * w), cvTempImage->imageData + (i * cvTempImage->widthStep), w);
	}
	
	cvConvertScale( cvTempImage, cvImage, 1, 0 );
	
	cvReleaseImage(&cvTempImage);
}

//-------------------------------------------------------------------------------------
unsigned char * ofCvFloatImage::getPixels(){
	// copy each line of pixels:
	IplImage		* cvTempImage = cvCreateImage(cvSize(width,height), IPL_DEPTH_8U,1);
    
    cvConvertScale( cvImage, cvTempImage, 1, 0 );
    
    for (int i = 0; i < height; i++){
		memcpy(pixels + (i * width), cvTempImage->imageData + (i * cvTempImage->widthStep), width);
	}
	
	cvReleaseImage(&cvTempImage);
	
	return pixels;
}


void ofCvFloatImage::draw(float x, float y){

	// note, this is a bit ineficient, as we have to
	// copy the data out of the cvImage into the pixel array
	// and then upload to texture.  We should add
	// to the texture class an override for pixelstorei
	// that allows stepped-width image upload:
	
	tex.loadData(getPixels(), width, height, GL_LUMINANCE);
	tex.draw(x,y,width, height);
	
	
	
	
}


//-------------------------------------------------------------------------------------
void ofCvFloatImage::swapTemp(){
	IplImage * temp;
	temp 			= cvImage;
	cvImage 		= cvImageTemp;
	cvImageTemp 	= temp;
}


//-------------------------------------------------------------------------------------
void ofCvFloatImage::blur(){
	cvSmooth(cvImage, cvImageTemp, CV_GAUSSIAN , 3);
	swapTemp();
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator =	( ofCvFloatImage & mom ){
	if (mom.width == width && mom.height == height){
		cvCopy(mom.getCvImage(), cvImage, 0);
	} else {
		// what do we do?
		// cvResize?
		// cvClone?
		printf("error in =, images are different sizes\n");
	}
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator -=	(  ofCvFloatImage & mom ){
	if (mom.width == width && mom.height == height){
		cvSub(cvImage, mom.getCvImage(), cvImageTemp);
		swapTemp();
	} else {
		printf("error in -=, images are different sizes\n");
	}
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator +=	(  ofCvFloatImage & mom ){
	if (mom.width == width && mom.height == height){
		cvAdd(cvImage, mom.getCvImage(), cvImageTemp);
		swapTemp();
	} else {
		// what do we do?
		// cvResize?
		// cvClone?
		printf("error in =, images are different sizes\n");
	}
}
//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator +=	(  ofCvGrayscaleImage & mom ){
	if (mom.width == width && mom.height == height){
	
		
		IplImage		* cvTemp = cvCreateImage(cvSize(width,height), IPL_DEPTH_32F,1);
	     
		cvConvertScale( mom.getCvImage(), cvTemp, 1, 0 );
		
    	cvAdd(cvImage, cvTemp, cvImageTemp);
     
     	swapTemp();
    	
    	cvReleaseImage(&cvTemp);
     
     
		
	} else {
		// what do we do?
		// cvResize?
		// cvClone?
		printf("error in =, images are different sizes\n");
	}
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator *=	(  ofCvFloatImage & mom ){
	if (mom.width == width && mom.height == height){
		float scalef = 1.0f / 255.0f;
		cvMul(cvImage, mom.getCvImage(), cvImageTemp, scalef);
		swapTemp();
	} else {
		// what do we do?
		// cvResize?
		// cvClone?
		printf("error in =, images are different sizes\n");
	}
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator -=	( float scalar ){
	cvSubS(cvImage, cvScalar(scalar), cvImageTemp);
	swapTemp();
}

//-------------------------------------------------------------------------------------
void ofCvFloatImage::operator +=	( float scalar ){
	cvAddS(cvImage, cvScalar(scalar), cvImageTemp);
	swapTemp();
}
//-------------------------------------------------------------------------------------
void ofCvFloatImage::addWeighted( ofCvGrayscaleImage mom, float f)
{
     
     IplImage		* cvTemp = cvCreateImage(cvSize(width,height), IPL_DEPTH_32F,1);
     cvConvertScale( mom.getCvImage(), cvTemp, 1, 0 );
     
     cvAddWeighted( cvTemp, f, cvImage, 1.0f-f,0, cvImageTemp);
     swapTemp();
     
     cvReleaseImage(&cvTemp);
}
//-------------------------------------------------------------------------------------
void ofCvFloatImage::setGrayscaleImage(ofCvGrayscaleImage & mom)
{
	 cvConvertScale(cvImage, mom.getCvImage(), 1, 0 );
    
    
     
    
}
//-------------------------------------------------------------------------------------
void ofCvFloatImage::copySubImageIntoMe( ofCvGrayscaleImage & mom, int x, int y, int w, int h)
{
	 IplImage		* cvTempImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_32F,1);
     
     cvSetImageROI( cvImage, cvRect(x,y,w,h) );
     
     cvConvertScale( mom.getCvImage(), cvTempImage, 1, 0 );
     cvCopy(cvTempImage, cvImage,  mom.getCvImage());
     
     cvResetImageROI( cvImage );
     
     cvReleaseImage(&cvTempImage);
     
    
}
		