// file: $USFS/class/image_analysis/v6.2/imaga_edge_23.cc
//

// system include files
//
#include <string.h>

// isip include files
//
#include "image_analysis.h"
#include "image_analysis_constants.h"
#include "ppm.h"

// method: detect_lines_cc
//
// arguments:
//  char_1* in_img_fname: (input) the input image file name
//  char_1* out_data_fname: (input) the output data file name
//  char_1* out_img_fname: (input) the output image file name
//
// return:
//  a logical_1 value indicating status
//
// this method computes edges and lines on a color PPM image file and
// outputs the computed image and data
//
logical_1 Image_analysis::detect_lines_cc(char_1* in_img_fname_a,
					  char_1* out_data_fname_a,
					  char_1* out_img_fname_a) {

  // declare a ppm object
  //
  Ppm ppm;
  
  // open the ppm image
  //
  if (ppm.open_cc(in_img_fname_a, ISIP_READ_ONLY) == ISIP_FALSE) {
    error_handler_cc((char_1*)"edge_compute_cc",
		     (char_1*)"error opening the image file");
    return ISIP_FALSE;
  }
  
  // read the dimensions of the image
  //
  int_4 width = ppm.get_width_cc();
  int_4 height = ppm.get_height_cc();
  
  // intialize the buffers for reading image data
  //
  uint_1* b_red = new uint_1[width * height];
  uint_1* b_green = new uint_1[width * height];
  uint_1* b_blue = new uint_1[width * height];

  memset(b_red, 0, width * height);
  memset(b_green, 0, width * height);
  memset(b_blue, 0, width * height);
  
  // read the ppm file block by block
  //
  if (ppm.read_cc(b_red, b_green, b_blue, IMAGA_EDGE_WOFF, IMAGA_EDGE_HOFF,
		  width, height) == ISIP_FALSE) {
    error_handler_cc((char_1*)"edge_compute_cc",
		     (char_1*)"error while reading the file");
    return ISIP_FALSE;
  }
    
  // initialize the parameters related to edge detection processing
  //
  edge_r_xmean_d = IMAGA_EDGE_XMEAN;
  edge_r_ymean_d = IMAGA_EDGE_YMEAN;
  edge_r_sigma_d = IMAGA_EDGE_SIGMA;
  edge_r_msize_d = IMAGA_EDGE_MSIZE;

  // declare memory to store the gray scale values
  //
  float_4* edge_gray = new float_4[width * height];  
  memset(edge_gray, 0, width * height * sizeof(float_4));

  // compute the equivalent gray scale value
  //
  if (edge_gray_cc(edge_gray, width, height, b_red, b_green,
		   b_blue) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error computing the gray scale value");
    return ISIP_FALSE;
  }

  // delete memory
  //
  delete [] b_red;
  delete [] b_green;
  delete [] b_blue;
    
  // declare memory to read the gaussian mask values
  //
  float_4* edge_gauss = new float_4[IMAGA_EDGE_MSIZE * IMAGA_EDGE_MSIZE];
  memset(edge_gauss, 0, IMAGA_EDGE_MSIZE * IMAGA_EDGE_MSIZE * sizeof(float_4));
  
  // compute the gaussian matrix
  //
  if (edge_gauss_cc(edge_gauss) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error computing the gaussian coeffients");
    return ISIP_FALSE;
  }
  
  // declare memory to store the gaussian smoothed image
  //
  float_4* gauss_result = new float_4[width * height];
  memset(gauss_result, 0, width * height * sizeof(float_4));
  
  // convolve the gray scaled image with the gaussian mask
  //
  if (edge_convolve_cc(gauss_result, edge_gray, edge_gauss,
		       width, height) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error convolving the image with gaussian mask");
    return ISIP_FALSE;
  }
  
  // delete the memory
  //
  delete [] edge_gray;
  delete [] edge_gauss;

  // declare memory to read the x and the y derivative masks
  //
  float_4* edge_xderiv = new float_4[IMAGA_EDGE_MSIZE * IMAGA_EDGE_MSIZE];
  float_4* edge_yderiv = new float_4[IMAGA_EDGE_MSIZE * IMAGA_EDGE_MSIZE];

  memset(edge_xderiv, 0,
	 IMAGA_EDGE_MSIZE * IMAGA_EDGE_MSIZE * sizeof(float_4));
  memset(edge_yderiv, 0,
	 IMAGA_EDGE_MSIZE * IMAGA_EDGE_MSIZE * sizeof(float_4));
  
  // compute the derivatives matrix
  //
  if (edge_derivatives_cc(edge_xderiv, edge_yderiv) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error computing the derivative coefficients");
    return ISIP_FALSE;
  }
    
  // declare memory to store the image convolved with
  // x and y derivative masks
  //
  float_4* xderiv_image = new float_4[width * height];
  float_4* yderiv_image = new float_4[width * height];

  memset(xderiv_image, 0, width * height * sizeof(float_4));
  memset(yderiv_image, 0, width * height * sizeof(float_4));
  
  // convolve the gaussian smoothed image with the x derivative
  // and y derivative masks
  //
  if (edge_convolve_cc(xderiv_image, gauss_result, edge_xderiv,
		       width, height) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error convolving image with the x derivative");
    return ISIP_FALSE;
  }

  // delete memory
  //
  delete [] edge_xderiv;
  
  if (edge_convolve_cc(yderiv_image, gauss_result, edge_yderiv,
		       width, height) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error convolving image with the y derivative");
    return ISIP_FALSE;
  }
  
  // delete the memory
  //
  delete [] gauss_result;
  delete [] edge_yderiv;
  
  // declare memory to store the gradient of the image
  //
  float_4* edge_grad = new float_4[width * height];
  memset(edge_grad, 0, width * height * sizeof(float_4));
  
  // compute the gradient
  //
  if (edge_gradient_cc(edge_grad, width, height, xderiv_image,
		       yderiv_image) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error computing the gradient");
    return ISIP_FALSE;
  }
  
  // delete the memory
  //
  delete [] xderiv_image;
  delete [] yderiv_image;
  
  // declare memory to read the edge_detected image
  //
  float_4* out_image = new float_4[width * height];
  memset(out_image, 0, width * height * sizeof(float_4));
  
  // detect edges according to the gradient data
  //
  if (edge_maxsup_cc(out_image, edge_grad, width, height) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error detecting edges");
    return ISIP_FALSE;
  }

  // delete memory
  //
  delete [] edge_grad;
  
  // prepare output data file
  //
  FILE* fp_out_data = fopen((char*)out_data_fname_a, "w");
  if (fp_out_data == (FILE*)NULL) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error opening file");
    return ISIP_FALSE;
  }

  fprintf(fp_out_data, "%s\n", in_img_fname_a);
  
  // detect lines and output the results
  //
  if (edge_lines_cc(out_image, width, height, fp_out_data) == ISIP_FALSE) {
    error_handler_cc((char_1*)"compute_edge_cc",
		     (char_1*)"error detecting lines");
    return ISIP_FALSE;
  }
  
  // output the detected line image if necessary
  //
  if (out_img_fname_a != (char_1*)NULL) {
    if (write_cc(out_image, out_img_fname_a, width, height) == ISIP_FALSE) {
      error_handler_cc((char_1*)"compute_edge_cc",
		       (char_1*)"error writing the data");
      return ISIP_FALSE;
    }
  }
		       
  // close files
  //
  ppm.close_cc();
  fclose(fp_out_data);
  
  // delete memory
  //
  delete [] out_image;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
