/*
	Copyright (C) 2008  John Hobbs - john@velvetcache.org

	This file 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 3 of the License, or
	(at your option) any later version.

	This file 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 file.  If not, see <http://www.gnu.org/licenses/>.
*/
/*
	fxTest is a simple application based on the demonstration code provided
	by the OpenCV group. It is a testbed for creating and trying different
	methods with OpenCV. It is also a bit of a mess.

	Author: John Hobbs
	Homepage: http://www.velvetcache.org/
*/
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <sys/stat.h>
#include <sstream>
using namespace std;

int main(int argc, char * argv[]) {

	bool erode = false;
	bool circle = false;
	bool dilate = false;
	bool mirror = false;

	time_t seconds;
	stringstream utl;

	CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
	if( !capture ) {
		cerr << "ERROR: Failed to start capture device." << endl;
		return -1;
	}

	cout << "fxTest - Active filters: \n";

	for(int i = 1; i < argc; i++) {
		if(0 == strcmp(argv[i],"erode")) {
			erode = true;
			cout << "\terode (OpenCV)\n";
		}
		if(0 == strcmp(argv[i],"circle")) {
			circle = true;
			cout << "\tcircle (OpenCV)\n";
		}
		if(0 == strcmp(argv[i],"dilate")) {
			dilate = true;
			cout << "\tdilate (OpenCV)\n";
		}
		if(0 == strcmp(argv[i],"mirror")) {
			mirror = true;
			cout << "\tmirror (jmhobbs)\n";
		}
	}

	cout << "\n\nPress 'c' to capture and save an image.\n"
			 << "Press 'ESC' or 'q' to quit.\n\n"
			 << "Try not to quit using the UI, it won't shut down properly." << endl;

	// Create a window in which the captured images will be presented
	cvNamedWindow( "fxTest", CV_WINDOW_AUTOSIZE );

	// Show the image captured from the camera in the window and repeat
	while( 1 ) {
		// Get one frame
		IplImage* frame = cvQueryFrame( capture );

		if( !frame ) {
			cerr << "ERROR: Couldn't get a frame." << endl;
			break;
		}

		if(mirror) {
			int halfFrame = frame->width/2;
			int frameBytes = frame->width*3-1;
			for(int i = 0; i < frame->height; i++) {
				int offset = i*frame->width*3;
				for(int j = 0; j < halfFrame; j++) {
					int jBytes = offset+frameBytes-(j*3);
					int ojBytes = offset+(j*3);
					frame->imageData[jBytes-2] = frame->imageData[ojBytes];
					frame->imageData[jBytes-1] = frame->imageData[ojBytes+1];
					frame->imageData[jBytes] = frame->imageData[ojBytes+2];
				}
			}
		}

		if(erode)
			cvErode(frame,frame,0,2);
		if(circle)
			cvCircle(frame, cvPoint(100,100), 20, cvScalar(0,255,0), 1);
		if(dilate)
			cvDilate(frame,frame);

		cvShowImage( "fxTest", frame );

		int keypress = (cvWaitKey(10) & 255);
		if(keypress == 255) {
			// Do nothing, no keys pressed.
		}
		else if(keypress == 27 || keypress == 113) {
			// ESC or q pressed, bail out
			break;
		}
		else if(keypress == 99) {
			// c pressed, capture an image
			seconds = time (NULL);
			utl.str("");
			utl << "fxTest_capture_" << seconds << ".jpg";
			if(!cvSaveImage(utl.str().c_str(),frame))
				cout << "Could not save file: " << utl.str() << endl;
			else
				cout << "Saved file as: " << utl.str() << endl;
		}
		else {
			// Other key pressed, inform the user
			cout << "You pushed..." << keypress << endl;
		}
	}

	// Release the capture device housekeeping
	cvReleaseCapture( &capture );
	cvDestroyWindow( "fxTest" );

	cout << "\nAll done!" << endl;

	return 0;
}
