#ifndef MOSS_HAS_BEEN_INCLUDED
#define MOSS_HAS_BEEN_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>
#include <math.h>

#include <air.h>
#include <biff.h>
#include <nrrd.h>

#define MOSS "moss"

#define MOSS_MAXPAIRS 32  /* hack: limit the number of corresp points 
			     per image pair */

#define MOSS_TINYVAL 0.005  /* smallest value allowed to be inverted */

/*
******** mossCorresp struct
**
** struct for holding correspondence information
** holds both the correspondence points, as well as the conversion
** matrices computed from them.  There may be no correspondence point
** data, only the matrices, if this is an intermediate correspondence
** computed from other mossCorresps.
*/
typedef struct {
  int num,           /* number of corresp. points for which we have info */
    maxNum;          /* number of corresp. points allocated for in arrays */
  float *x0, *y0,    /* (x0[i],y0[i]) is correspondence point in image 0 */
    *x1, *y1;        /* (x1[i],y1[i]) is correspondence point in image 1 */
  float m01[3][3],   /* projective transform mapping from image 0 to 1 */
    m10[3][3];       /* projective transform mapping from image 1 to 0 */
} mossCorresp;

/*
******** mossMatrix struct
**
** struct to hold two-dimensional array of mossCorresp structs
** each element in the array tells how to map between two images
** 
** pair[i][j] contains information for going between image i and j,
** where image i is image "0" and image j is "1"
*/
typedef struct {
  int size;            /* length of pair[] array and of each pair[][] array */
  mossCorresp ***pair; /* array of arrays of mossCorresp pointers */
} mossMatrix;

/* methods.c */
extern mossCorresp *mossNewCorresp(int maxNum);
extern void mossNukeCorresp(mossCorresp *);
extern mossMatrix *mossNewMatrix(int size);
extern void mossNukeMatrix(mossMatrix *matx);

/* svdcmp.c */
extern int mossSVD(float *U, float *W, float *V, float *matx, int M, int N);
extern int mossPseudoInverse(float *inv, float *matx, int M, int N);

/* image.c */
extern void mossProjTran(float *xOutP, float *yOutP,
			 float m[3][3],
			 float xIn, float yIn);
extern void mossImageSize(int *sizeXP, int *sizeYP, Nrrd *img);
extern int mossLearnBounds(float *minXP, float *maxXP, 
			   float *minYP, float *maxYP, 
			   mossMatrix *matx, Nrrd **imgs, 
			   int numImgs, int which);
extern int mossInterp(float *wght, float *val, Nrrd *img, float xs, float ys);
extern void mossSetVal(Nrrd *img, int x, int y, float v0, float v1, float v2);
extern int mossFillImage(Nrrd *out, mossMatrix *matx, 
			 Nrrd **imgs, int numImgs, int which);

/* corresp.c */
extern int mossSetMatrix(mossMatrix *matx, Nrrd *points);

/* mosiac.c */
extern int mossValidPNM(Nrrd *img);
extern int mossValidPoints(Nrrd *points, int numImgs);
extern int mossValidArgs(Nrrd **imgs, int numImgs, int which, Nrrd *points);
extern Nrrd *mossDoit(Nrrd **imgs, int numImgs, int which, Nrrd *points);


/* extern C */
#ifdef __cplusplus
}
#endif

#endif /* MOSS_HAS_BEEN_INCLUDED */
