 

#include <stdio.h>

#include "clarg.h"
#include "image.h"


static char *USAGE     = "\n%s: Find ridges in the input PFM image\n\n";
static CLINIT clinit[] = {{NULL, 0, 0, NULL, 0}};
static char *depend[]  = {NULL};

 




double sqrt(double x);

inline float square(float x)
{
  return x*x;
}



int main(int argc, char **argv, char **envp)
{
  FloatImage img, dx, dy, dxx, dyy, dxy, ridge;
  int x, y, w, h;



  if (cl_init(argc, argv, envp, clinit, depend, USAGE, CL_NORESTRICT))
    return 0;

  img = imLoad(IMAGE_FLOAT, NULL);
  if (img == (FloatImage) NULL) {
    return -1;
  }

  w = imGetWidth(img);
  h = imGetHeight(img);

  dx    = imNew(IMAGE_FLOAT, w, h);
  dy    = imNew(IMAGE_FLOAT, w, h);
  dxx   = imNew(IMAGE_FLOAT, w, h);
  dyy   = imNew(IMAGE_FLOAT, w, h);
  dxy   = imNew(IMAGE_FLOAT, w, h);
  ridge = imNew(IMAGE_FLOAT, w, h);

  if (dx == NULL  ||  dy == NULL  ||  dxx == NULL  ||  dyy == NULL  ||
      dxy == NULL ||  ridge == NULL) {
    return -1;
  }
  
  for (y = 0; y < h - 1; y++) {
    for (x = 0; x < w - 1; x++) {
      float a, b, c, d;

      a = imRef(img, x, y);
      b = imRef(img, x+1, y);
      c = imRef(img, x, y+1);
      d = imRef(img, x+1, y+1);
      
      imRef(dx, x, y) = 0.5 * (b - a + d - c);
      imRef(dy, x, y) = 0.5 * (c - a + d - b);
    }
  }

  for (y = 0; y < h - 2; y++) {
    for (x = 0; x < w - 2; x++) {
      float a, b, c, d;

      a = imRef(dx, x, y);
      b = imRef(dx, x+1, y);
      c = imRef(dx, x, y+1);
      d = imRef(dx, x+1, y+1);

      imRef(dxx, x, y) = 0.5 * (b - a + d - c);
      imRef(dxy, x, y) = 0.5 * (c - a + d - b);

      a = imRef(dy, x, y);
      b = imRef(dy, x+1, y);
      c = imRef(dy, x, y+1);
      d = imRef(dy, x+1, y+1);

      imRef(dyy, x, y) = 0.5 * (c - a + d - b);
    }
  }

  for (y = 0; y < h - 2; y++) {
    for (x = 0; x < w - 2; x++) {
      float exx, eyy, exy;

      exx = imRef(dxx, x, y);
      eyy = imRef(dyy, x, y);
      exy = imRef(dxy, x, y);

      if (exx + eyy < 0.0) {
	float exx_m_eyy = exx - eyy;
	float cd = sqrt(square(exx_m_eyy) + 4.0*square(exy));
	float dpcx = sqrt(cd - exx_m_eyy);
	float dpcy = sqrt(cd + exx_m_eyy);
	boolean s00, s01, s10, s11;

	if (exy > 0.0)
	  dpcy = -dpcy;

	s00 = imRef(dx, x, y)*dpcx     + imRef(dy, x, y)*dpcy > 0.0;
	s01 = imRef(dx, x, y+1)*dpcx   + imRef(dy, x, y+1)*dpcy > 0.0;
	s10 = imRef(dx, x+1, y)*dpcx   + imRef(dy, x+1, y)*dpcy > 0.0;
	s11 = imRef(dx, x+1, y+1)*dpcx + imRef(dy, x+1, y+1)*dpcy > 0.0;

	if ((s00 || s01 || s10 || s11) && !(s00 && s01 && s10 && s11))
	  imRef(ridge, x+1, y+1) = cd;   /* imRef(img, x, y); */   /* a: kbs  b: sandy */
	else
	  imRef(ridge, x+1, y+1) = 0.0;
      }
      else
	imRef(ridge, x+1, y+1) = 0.0;

    }
  }

  imSave(ridge, NULL);

  return 0;
}
    

  
