// Composicion_Imagenes.cpp : Defines the entry point for the console application.
//
#include <stdio.h>

/*CUDA*/
#include <cuda_runtime.h>

/*OpenCV*/
#include <opencv2/highgui/highgui.hpp>

#include "ImageComposition.h"

//alpha parameter 
int alpha_int=50;
float alpha=0.5; //[0,1]
void Change_alpha(int,void *){
	alpha=(float)alpha_int/100;
}


int main(int argc, char **argv){
	cudaSetDevice(0);
	/*Host Variables*/
	int imageW, imageH;				  //Size of Image
	cv::Mat frame1_Original;   //Original Image
	cv::Mat frame2_Original;   //Original Image
	cv::Mat frame_Composed;
	
	/*Device Variables*/
	uchar3 *Image1_dev,*Image2_dev,*ComposedImage_dev;

	cv::namedWindow("Original Frame1",CV_WINDOW_AUTOSIZE);
	cv::namedWindow("Original Frame2",CV_WINDOW_AUTOSIZE);
	cv::namedWindow("Composed Frame",CV_WINDOW_AUTOSIZE);

	cv::createTrackbar("alpha", "Composed Frame",&alpha_int,100,Change_alpha,0);

	char name_imag[500];
	/*Load Image*/
	sprintf(name_imag,"../../Images/baboon.jpg");
	frame1_Original = cv::imread(name_imag,1);
	
	sprintf(name_imag,"../../Images/lena.jpg");
	frame2_Original = cv::imread(name_imag,1);


	/*Size of Image*/
	imageW=frame1_Original.cols;
	imageH=frame1_Original.rows;
	size_t size=imageW*imageH*sizeof(uchar3);

	/*Create host memory*/
	frame_Composed.create(imageH,imageW,CV_8UC(3));

	/*Create device memory*/
	cudaMalloc((void **)&Image1_dev,size);
	cudaMalloc((void **)&Image2_dev,size);
	cudaMalloc((void **)&ComposedImage_dev,size);

	/*Copy Memory (Host-->Device)*/
	cudaMemcpy(Image1_dev,frame1_Original.data,size,cudaMemcpyHostToDevice);
	cudaMemcpy(Image2_dev,frame2_Original.data,size,cudaMemcpyHostToDevice);

	/*Define the size of the grid and thread blocks*/
	dim3 threads(512,1,1);
	int N=imageW * imageH;
	dim3 grid(N/threads.x + (N%threads.x == 0 ? 0:1),1,1);
	
	cv::imshow("Original Frame1",frame1_Original);
	cv::imshow("Original Frame2",frame2_Original);

	while(1){
		/*Launch the Kernel Function*/
		CUDA_Compose_Images(ComposedImage_dev,Image1_dev,Image2_dev,alpha,N,grid,threads);

		/*Copy Memory (Device-->Host)*/
		cudaMemcpy(frame_Composed.data,ComposedImage_dev,size,cudaMemcpyDeviceToHost);

		cv::imshow("Composed Frame",frame_Composed);
		
		char key=cvWaitKey(2);
		if(key==27) {
			break;
		}	
	}

	/*Clean Memory*/
	/*Host*/
	cv::destroyWindow("Original Frame1");
	cv::destroyWindow("Original Frame2");
	cv::destroyWindow("Composed Frame");
	/*Device*/
	cudaFree(Image1_dev);
	cudaFree(Image2_dev);
	cudaFree(ComposedImage_dev);

	return(0);
}
