

#include <stdio.h>

#include "clarg.h"
#include "gradient.h"
#include "string-support.h"


static char *USAGE =
  "\n%s:  Compute the gradient of the PFM input image, outputting the PFM result.\n"
  "\n"
  "Arguments are:\n"
  "   -input FILE:          Specify the input file name (PFM)\n"
  "   -output FILE:         Specify the output file name (PFM)\n"
  "   -mag:                 Compute the magnitude of the gradient. (default)\n"
  "   -sqr:                 Compute the magnitude of the gradient squared instead.\n"
  "   -x:                   Compute the x component of the gradient instead.\n"
  "   -y:                   Compute the y component of the gradient instead.\n"
  "\n"
  "   -abs:                 Give the absolute value of the result.\n"
  "\n"
  "The requested component of the gradient is computed and output. If no input\n"
  "file is specified, input is from stdin, and if no output file is specified,\n"
  "output is to stdout.\n\n";


#define INPUT 	"i.nput"
#define OUTPUT 	"o.utput"
#define MAG	"m.ag"
#define SQR     "s.qr"
#define X	"x"
#define Y       "y"
#define TAKEABS "a.bs"

static CLINIT clinit[] = {{INPUT,   1, 1, NULL, 0},
			  {OUTPUT,  1, 1, NULL, 0},
			  {MAG,     0, 0, NULL, 0},
			  {SQR,     0, 0, NULL, 0},
			  {X,       0, 0, NULL, 0},
			  {Y,       0, 0, NULL, 0},
			  {TAKEABS, 0, 0, NULL, 0},
			  {NULL,    1, 1, NULL, 0}};


static char *depend[] = {MAG"+"SQR"+"X"+"Y" <= 1", "!(UNNAMED && "INPUT")", NULL};


void take_abs(float *x, int i, int j)
{
  if (*x < 0.0)
    *x = -*x;
}


int main(int argc, char **argv, char **envp)
{
  FloatImage img, grad = NULL;
  char *infile;
  

  if (cl_init(argc, argv, envp, clinit, depend, USAGE, CL_NORESTRICT))  /* parse args */
    return 0;

  infile   = (cl_opt(INPUT)
	      ? cl_arg1(INPUT)
	      : cl_opt(CL_UNNAMED) ? cl_arg1(CL_UNNAMED) : NULL);
  
  img = imLoad(IMAGE_FLOAT, infile);
  if (img == (FloatImage) NULL) {
    fprintf(stderr, "GRADIENT: Error reading input file\n");
    return -1;
  }

  if (cl_opt(SQR)) {
    if (gradientMagSqrd(img, &grad)) {
      fprintf(stderr, "GRADIENT: Error computing gradient\n");
      return -1;
    }
  }
  else if (cl_opt(X)) {
    if (gradientX(img, &grad)) {
      fprintf(stderr, "GRADIENT: Error computing gradient\n");
      return -1;
    }
  }
  else if (cl_opt(Y)) {
    if (gradientY(img, &grad)) {
      fprintf(stderr, "GRADIENT: Error computing gradient\n");
      return -1;
    }
  }
  else {				     /* magnitude */
    if (gradientMag(img, &grad)) {
      fprintf(stderr, "GRADIENT: Error computing gradient\n");
      return -1;
    }
  }

  if (cl_opt(TAKEABS)) {
    imApply(take_abs, grad);
  }

  imDocString(grad) = strNewComment(argc, argv, envp, imDocString(img), NULLSTRING);
  
  if (imSave(grad, cl_opt(OUTPUT) ? cl_arg1(OUTPUT) : NULL)) {
    fprintf(stderr, "GRADIENT: Error writing output\n");
    return -1;
  }

  return 0;
}

