/*****************************************************************************
 * ass1sobel.cpp
 ***************************************************************************** 
 *
 * Description: Assignment 1 (COMPSCI775)
 *
 * Topic: Edge Detection in Colour Images - Sobel
 *
 * (c) 2002 Christian Graf, Uli Schroeder (Group 7)
 *
 *****************************************************************************
 *
 * $Revision: 1.0 $
 *
 */

#include <math.h>
#include <iostream.h>
#include "HalconCpp.h"

class Sobel {

  private:

	int max;

  public:

    Sobel(HByteImage inImg, HByteImage *outImg, float aThres) {
	  max = 0;
	  for (int x=1; x<inImg.Width()-1; x++) {
        for (int y=1; y<inImg.Height()-1; y++) {
          (*outImg).SetPixVal(x, y, (abs (-inImg(x-1,y+1)-2*inImg(x-1,y)-inImg(x-1,y-1)
                                         +inImg(x+1,y+1)+2*inImg(x+1,y)+inImg(x+1,y-1)) +
	                                 abs (-inImg(x-1,y+1)-2*inImg(x,y+1)-inImg(x+1,y+1)
	                                     +inImg(x-1,y-1)+2*inImg(x,y-1)+inImg(x+1,y-1))));
		  if ((HByte)(*outImg).GetPixVal(x,y)>max) max=(*outImg).GetPixVal(x,y); 
        }
      }
      for (int x=0; x<(*outImg).Width(); x++) {
        for (int y=0; y<(*outImg).Height(); y++) {
          if ((HByte)(*outImg).GetPixVal(x,y)<max*aThres) {
	        (*outImg).SetPixVal(x, y, 255);
          } else {
	        (*outImg).SetPixVal(x, y, 0);
          }
        }
      }
    }

};

main(int argc, char* argv[]) {
  cout << "---------------------------------" << endl;
  cout << " Assignment 1 (COMPSCI775):      " << endl;
  cout << " Edge Detection in Colour Images " << endl;
  cout << " (Sobel)                         " << endl;
  cout << "---------------------------------" << endl;
  cout << " Group 7:                        " << endl;
  cout << " Christian Graf                  " << endl;
  cout << " Uli Schroeder                   " << endl;
  cout << "---------------------------------" << endl << endl;
  if (argc != 4) {
    cout << " Wrong number of arguments!" << endl << endl;
    cout << " Program usage:" << endl;
    cout << " ./ass1sobel inputimage outputimage threshold" << endl << endl;
    return(-1);
  }
  cout << " Processing image " << argv[1] << "..." << endl;
  HImage     myImage(argv[1]);
  HByteImage r, g, b, r_edges, g_edges, b_edges, result;
  r = myImage.Decompose3(&g, &b);
  g = myImage.Decompose3(&r, &b);
  b = myImage.Decompose3(&r, &g);
  r_edges = HByteImage(myImage.Width(),myImage.Height());
  g_edges = HByteImage(myImage.Width(),myImage.Height());
  b_edges = HByteImage(myImage.Width(),myImage.Height());
  result = HByteImage(myImage.Width(),myImage.Height());
  // Apply Median
  r.MedianImage("circle",1,0);
  g.MedianImage("circle",1,0);
  b.MedianImage("circle",1,0);
  // Apply Sobel
  new Sobel(r, &r_edges, atof(argv[3]));
  new Sobel(g, &g_edges, atof(argv[3]));
  new Sobel(b, &b_edges, atof(argv[3]));
  // Compose  result (An edge has to be in at least two pictures.)
  for (int x=0; x<result.Width(); x++) {
    for (int y=0; y<result.Height(); y++) {
      if (r_edges(x,y)+g_edges(x,y)+b_edges(x,y)<256) {
        result(x,y) = 0;
      } else {
        result(x,y) = 255;
      }
    }
  }
  cout << " Image processing finished..." << endl;
  // Write result to file
  result.WriteImage("jpeg 50", 0xffffff, argv[2]);
/*
  // Display result
  HWindow img1;
  result.Display (img1);
  img1.Click();
*/
  cout << " The End!" << endl << endl;
  return(0);
}