/********************************************************************************
*         CS 791E Programming Assignment # 2 (2.1)
*              Canny Algorithm Application
*
*  
*  Name:   canny.c
*  Usage:  1). make
*          2). canny <input-image-file-name> 
*                    <output-image-FILEBASE-name> <mask-size>
*  Autor:  Beifang Yi
*  Date:   3/16/03
*
*
********************************************************************************/

#ifdef _CH_
#pragma package <opencv>
#endif

#ifndef _EiC
#include "cv.h"
#include "highgui.h"
#endif

#include <stdlib.h>
#include <string.h>
#include <iostream.h>

//parameters for cvCanny function
int lowThreshold = 50;
int highThreshold = 100;
int maskSize = 3;

//image structures
IplImage *sourceI = 0;
IplImage *tempI = 0;
IplImage *destI = 0;
char destIF[80];

//a callback function for canny edge detection
void canny_image(int h);

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

  if (argc < 4 ) {
    cout << " Please give input and output filenames, and mask size. "<<endl;
    exit(0);
  }
    
  // check and load source image
  if( (sourceI = cvLoadImage(argv[1], 0)) == 0 ) {
    cout << " Can not load image. " << endl;
    return -1;
  }
  
  //get mask size
  maskSize = atoi(argv[3]);

  //get specifics about the input image
  double minVal, maxVal;
  CvPoint *minLoc, *maxLoc;
  minLoc = new CvPoint; maxLoc = new CvPoint;
  cvMinMaxLoc( sourceI, &minVal, &maxVal, minLoc, maxLoc);

  // Create the temporary and destination images
  destI = cvCloneImage( sourceI );
  tempI = cvCloneImage( sourceI );

  // Create windows for displaying  the effect
  cvNamedWindow("Source", 1);
  cvNamedWindow("CanniedImage", 1);

  // Show the source image.
  cvShowImage("Source", sourceI);

  // Create toolbars: for low/high threshold adjustment
  cvCreateTrackbar( "Low Threshold", "CanniedImage", &lowThreshold, 
		    ((int) maxVal)*maskSize*maskSize, canny_image );
  cvCreateTrackbar( "High Threshold", "CanniedImage", &highThreshold, 
		    ((int) maxVal)*maskSize*maskSize, canny_image );

  //canny the image for the first time by using the default parameters
  canny_image(0);

  // Wait for a key stroke, and save the processed (edge) images
  int key;  char tempC[10];
  key = cvWaitKey(0);
  while (key != 32) {
    cout<<"   key:  " <<key<<endl;
    if (key == 83 || key == 115) {      //if key == 'S' or 's'
      strcpy(destIF, argv[2]);
      sprintf(tempC, "%d", lowThreshold);
      strcat(destIF, tempC); strcat(destIF, "x");
      sprintf(tempC, "%d", highThreshold);
      strcat(destIF, tempC); strcat(destIF, "x");
      sprintf(tempC, "%d", maskSize);
      strcat(destIF, tempC); strcat(destIF, ".jpg");
      cvSaveImage(destIF, destI);
    }   
    key = cvWaitKey(0);
  }

  //release the images
  cvReleaseImage(&tempI);
  cvReleaseImage(&destI);
  cvDestroyWindow("Source");
  cvDestroyWindow("CanniedImage");

  return 0;
}

// CALLBACK: when either the threshold changes,
//           this function will be called.
//           FOR Canny edge detection based on the changed parameters
void canny_image(int h)
{

    // Canny detection
    cvCanny(tempI, destI, lowThreshold, highThreshold, maskSize);
    // Show image. HighGUI use.
    cvShowImage( "CanniedImage", destI );
}
