// file: $USFS/util/ppm_diff/v1.0/ppm_diff.cc
//
// a program that differences two images
//

// isip include files
//
#include "ppm_diff.h"
#include <ppm.h>

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

  // declare command line arguments
  //
  float_4 alpha = PPM_DEFAULT_A;
  float_4 beta = PPM_DEFAULT_B;
  char_1 file0[ISIP_MAX_FNAME_SIZE];
  char_1 file1[ISIP_MAX_FNAME_SIZE];
  char_1 file2[ISIP_MAX_FNAME_SIZE];

  // declare an object
  //
  Ppm ppm_0;
  Ppm ppm_1;
  Ppm ppm_2;

  // parse the command line
  //
  if (get_parameters_cc(argc, argv,
			alpha, beta, file0, file1, file2) == ISIP_FALSE) {
    fprintf(stdout, "%s: error in command line arguments\n", argv[0]);
    return ISIP_ERROR;
  }

  // echo command lines options
  //
  fprintf(stdout, "alpha = %f\n", alpha);
  fprintf(stdout, "beta = %f\n", beta);
  fprintf(stdout, "\n");

  // open the input files
  //
  if (ppm_0.open_cc(file0, ISIP_READ_ONLY) == ISIP_FALSE) {
    return ISIP_ERROR;
  }

  if (ppm_1.open_cc(file1, ISIP_READ_ONLY) == ISIP_FALSE) {
    return ISIP_ERROR;
  }

  // check to make sure the image sizes are compatible
  //
  int_4 width_0 = ppm_0.get_width_cc();
  int_4 width_1 = ppm_1.get_width_cc();
  if (width_0 != width_1) {
    fprintf(stdout, "%s: image widths incompatible (%ld and %ld)\n",
	    argv[0], width_0, width_1);
    return ISIP_ERROR;
  }

  int_4 height_0 = ppm_0.get_height_cc();
  int_4 height_1 = ppm_1.get_height_cc();
  if (height_0 != height_1) {
    fprintf(stdout, "%s: image heights incompatible (%ld and %ld)\n",
	    argv[0], height_0, height_1);
    return ISIP_ERROR;
  }

  // create the output file
  //
  if (ppm_2.open_cc(file2, ISIP_WRITE_ONLY) == ISIP_FALSE) {
    return ISIP_ERROR;
  }
  
  if (ppm_2.write_header_cc(width_0, height_0, PPM_DEFAULT_MAX_COLORS) ==
      ISIP_FALSE) {
    return ISIP_ERROR;
  }

  // define a block size and associated buffers
  //
  int_4 bsize = PPM_DEFAULT_BSIZE;

  uint_1* b_r_0 = new uint_1[bsize*bsize];
  uint_1* b_gr_0 = new uint_1[bsize*bsize];
  uint_1* b_bl_0 = new uint_1[bsize*bsize];  
  
  uint_1* b_r_1 = new uint_1[bsize*bsize];
  uint_1* b_gr_1 = new uint_1[bsize*bsize];
  uint_1* b_bl_1 = new uint_1[bsize*bsize];  
  
  uint_1* b_r_2 = new uint_1[bsize*bsize];
  uint_1* b_gr_2 = new uint_1[bsize*bsize];
  uint_1* b_bl_2 = new uint_1[bsize*bsize];  
  
  // loop over the entire image, reading sub-images:
  // note that we don't have to check for sub-images extending
  // beyond the edges of the image, because this is done at a lower-level
  // by read and write.
  //
  for (int_4 i=0; i<height_0; i+=bsize) {
    for (int_4 j=0; j<width_0; j+=bsize) {
      
      // give some status
      //
      fprintf(stdout, "processing block located at (%ld,%ld)...\n", j, i);

      // get the sub-images
      //
      if (ppm_0.read_cc(b_r_0, b_gr_0, b_bl_0,
			j, i, bsize, bsize) == ISIP_FALSE) {
	fprintf(stdout, "%s: error reading image 0\n", argv[0]);
      }
      if (ppm_1.read_cc(b_r_1, b_gr_1, b_bl_1,
			j, i, bsize, bsize) == ISIP_FALSE) {
	fprintf(stdout, "%s: error reading image 1\n", argv[0]);
      }

      // difference the images
      //
      ppm_2.diff_cc(alpha, beta, bsize, bsize,
		    b_r_2, b_gr_2, b_bl_2,
		    b_r_0, b_gr_0, b_bl_0,
		    b_r_1, b_gr_1, b_bl_1);

      // write the data
      //
      if (ppm_2.write_cc(b_r_2, b_gr_2, b_bl_2,
			 j, i, bsize, bsize) == ISIP_FALSE) {
	fprintf(stdout, "%s: error writing image 2\n", argv[0]);
      }
    }
  }
  
  // close files
  //
  ppm_0.close_cc();
  ppm_1.close_cc();
  ppm_2.close_cc();

  // exit gracefully
  //
  fprintf(stdout, "\n<end of program %s>\n", argv[0]);

  return ISIP_NO_ERROR;
}
