#ifndef ROUTINES_H
#define ROUTINES_H

#include "solaris.h"
#include "image.h"
#include "cannyEdge.h"


/* BOX_SPIRAL(x,y)
 *  
 *  given an x and y coordinate, it modifies x and y to be the next 
 *  location on the rectangular counter-clockwise spiral beginning at 
 *  (0,0),(1,0),(1,1), and continuing.  To spiral out through an nxn
 *  box one should stop when x > n, since the x always increments 
 *  before the y diameter.
 * 
 *  How it works: (four sides, four cases)
 *  x > 0 and x > abs(y), y++
 *  x < 0 and -x > abs(y) or -x = y, y--
 *  y > 0 and y > -x, x--
 *  y < 0 and -y >= x, x++, or x = y = 0 x++, note that order of 
 *  evaluation is important.
 */
#define BOX_SPIRAL(x,y)({if((x)>0&&(x)>(y)&&(x)>-(y))(y)++;else if((x)<0&&(x)<(y)&&-(x)>=(y))(y)--;else if((y)>0)(x)--;else (x)++;})
#define BOX_SPIRAL_INIT(x,y,d)({(x)=0;y=0;})
#define BOX_SPIRAL_STOP(x,y,d)((x) > (d))
/* RECT_SPIRAL(x,y,d)
 *
 * same as the box_spiral but designed to fill a size (a,b) box, where d =
 * a-b;  d must be >0;  To make a vertical one, simply interchange the x 
 * and y coordinates and use -d.  Note that the x coordinate should start 
 * at x = 1-d
 */
#define RECT_SPIRAL(x,y,d)({if((x)>0&&(x)>(y)+(d)-1&&(x)>-(y)+(d)-1)(y)=(y)+1;else if((x)<0&&((-(x)>(y)+(d)-1&&-(x)>-(y)+(d)-1)||((-(x)==(y)+(d)-1)&&(y)>0)))(y)=(y)-1;else if((y)>0)(x)=(x)-1;else (x)=(x)+1;})
#define RECT_SPIRAL_STOP(x,y,d)((x) > (d))
#define RECT_SPIRAL_INIT(x,y,a,b,d)({(d)=(a)-(b);(x)=1-d;y=0;assert(d >=0);})
/* RECT_TRAVERSE(x,y,a,b)
 *
 * The rectangle from -aa to a , -b to b
 */
#define RECT_TRAVERSE(x,y,a,b)({if(x > a){y++;x=-a;}else x++;})
#define RECT_TRAVERSE_STOP(x,y,a,b)((y) > (b))
#define RECT_TRAVERSE_INIT(x,y,a,b)({x=-a;y=-b;})

#define sumsqr_lookup(i,a,b,x,y)(imRef(i,x,y)+imRef(i,a,b)-imRef(i,a,y)-imRef(i,x,b))
#define sumsqr_pbm(b,g)(sumsqr_uchar(&(imRef(b,0,0)),&(imRef(g,0,0)),imGetWidth(b),imGetHeight(g)))

#define uchar_zero(i)(bzero(&(imRef((i),0,0)),(int)(imGetWidth(i)*imGetHeight(i))))


/*void *imMAX(void *im1, void *im2);
void *imMIN(void *im1, void *im2);*/
void box_spiral(int *x, int *y);
GrayImage gim_crop(GrayImage inim, int minx, int miny, 
		   int maxx, int maxy);
void gim_subpix_shift(GrayImage image, float shiftX, float shiftY);
void gim_weighted_avg(GrayImage start, GrayImage end, 
		      GrayImage output, float weight);
void gim_weighted_add(GrayImage start, GrayImage end, 
		      GrayImage output, float weightS, float weightE);
void min_max(FloatImage image, float *outmin, float*outmax);
float pbm_percentOn(BinaryImage inim);
void pbm_areahist(BinaryImage inim, int xdivs, int ydivs, int *arr);
void sumsqr_uchar(unsigned char *i, unsigned int *o, 
		  int w, int h);
Quad laplacianEdge(FloatImage inimage);
void pgm_shift_sub(GrayImage a, GrayImage b, int xDisp, int yDisp, 
		   GrayImage out);
/*
GrayImage pfm_to_pgm(FloatImage image, float min, float max);
*/

#endif
