
/**************************************************************************
 *                                                                        *
 * Copyright (c) 1996 Michael Richmond and Richard Treffers               *
 *                                                                        *
 *                    This software may be copied and distributed for     *
 *                    educational, research and not for profit services   *
 *                    provided that this copyright and statement are      *
 *                    included in all such copies.                        *
 *                                                                        *
 **************************************************************************/


/*	
	rotates an image 
	
		ROTATE file [PA=] [LEFT] [RIGHT] [BOX=] [SINC] [LAGRANGE]
	Stolen from the vista routines.

	The words rotate left and right are derived from 
	viewing the image like a sheet of paper with row 0 and column 0
	at the upper left corner, then rotating it ccw, and cw respectively.
	This may or may not be the VISTA convention. 

	3/3/96   - enabled use of "sinc" and "lagrange" options,
	              although I suspect the "sinc" option will take
	              a long, long time.  MWR
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "pcvista.h"
#include "fits.h"
#include "interp.h"

#ifndef M_PI
#define M_PI 3.14159265359
#endif


#ifdef PROTO
int main(int, char **);
static void rot_left(int16 **a, int nrow, int ncol, FITS_HANDLE fout);
static void rot_right(int16 **a, int nrow, int ncol, FITS_HANDLE fout);
static void rot_ud(int16 **a, int nrow, int ncol, FITS_HANDLE fout);
static void rotate_it(int16 **a, int nrow, int ncol, FITS_HANDLE fout,
                      double pa, PFI16 interp, int16 fill);
static void show_options(FILE *fp);
#else
int main();
static void rot_left();
static void rot_right();
static void rot_ud();
static void rotate_it();
static void show_options();
#endif


#define MODE_LEFT	1
#define MODE_RIGHT	2
#define MODE_UD		4
#define MODE_PA		8

#define PF (M_PI/180.)		/* degree to radian conversion factor */

int
main(argc,argv)
int argc;
char *argv[];
{
	int i;
	int boxno=-1;			/* -1 specifies the whole image */
	int rot_mode=0;
	double pa = 0.0;
	char *gotit;
	char infile[NBUF],outfile[NBUF];
	PFI16 interp;
	int16 **data;
	int16 fill=0;
	int nrow,ncol,newrow,newcol,nr,nc;
	FITS_HANDLE fin, fout;

	if (argc == 1) {
		show_options(stderr);
		exit(-1);
	}
	else if (strcmp(argv[1], "help") == 0) {
		show_options(stdout);
		exit(0);
	}

	strcpy(infile,argv[1]); 
	strcpy(outfile,argv[1]); /* default output filename is write over*/

	/* default interpolation function*/
	interp = (PFI16) bilinear;		

	fin = fits_open(argv[1], "r", &nrow, &ncol);

	for(i = 2; i < argc; i++) {
		if (keyword("help", argv[i])) {
			show_options(stdout);
			exit(0);
		}
		if ((gotit = find("pa", argv[i])) != NULL) {
			pa = evaluate(gotit);
			if(rot_mode)
				error(1,"you already have specified a rotation mode");
			rot_mode=MODE_PA;
			continue;
		}
		if ((gotit = find("fill", argv[i])) != NULL) {
			fill = (int16)floor(evaluate(gotit)+0.5);
			continue;
		}
		if (keyword("sinc",argv[i])){
			interp = (PFI16) sinc;
			continue;
		}
		if(keyword("left",argv[i])){
			if(rot_mode)
				error(1,"you already have specified a rotation mode");
			rot_mode=MODE_LEFT;
			continue;
		}
		if(keyword("right",argv[i])){
			if(rot_mode)
				error(1,"you already have specified a rotation mode");
			rot_mode=MODE_RIGHT;
			continue;
		}
		if(keyword("ud",argv[i])){
			if(rot_mode)
				error(1,"you already have specified a rotation mode");
			rot_mode=MODE_UD;
			continue;
		}
		if(keyword("lagrange",argv[i])){
			interp = (PFI16) lagrange;
			continue;
		}
		if ((gotit = find("outfile", argv[i])) != NULL) {
			strcpy(outfile,gotit);
			continue;
		}
		fprintf(stderr,"unknown option'%s'\n",argv[i]);
		exit(1);
	}

	/*	do some option consistency checking */ 
	if(rot_mode & (MODE_LEFT | MODE_RIGHT | MODE_UD)){
		if(boxno!=-1)
			error(1,"you can't use box with left or right or ud");
	}

	/* read in the image data */

	if ((data = boxdata(fin, boxno, (int) nrow, (int) ncol, &nr, &nc)) == NULL)
		error(-1,"couldn't read data in box from file");

	/*	create an new image into which to place the rotated data */ 

	if(rot_mode & (MODE_LEFT | MODE_RIGHT) ){
		newrow=ncol;
		newcol=nrow;
	}else{
		newrow=nrow;
		newcol=ncol;
	}
	if(strcmp(infile,outfile) == 0)
		fout = fits_open(outfile, "r+", &newrow, &newcol);
	else
		fout = fits_open(outfile, "w", &newrow, &newcol);

	/*	now perform the rotion depending on the mode selected */
	switch(rot_mode ){
		case MODE_LEFT:
			rot_left( data, newrow,newcol,fout);
			break;
		case MODE_RIGHT:
			rot_right( data, newrow,newcol,fout);
			break;
		case MODE_UD:
			rot_ud( data, newrow,newcol,fout);
			break;
		case MODE_PA:
			rotate_it(data,newrow,newcol,fout,pa,interp,fill);
			break;
		default:
			error(1,"no rotation specified");
	}

	fits_close(fout);

	exit(0);
}



/*	function to rotate an image to an arbitrary position angle

	At the position of each pixel in the rotated system,
	interpolate in the original system.

*/

static void rotate_it(a,nrow,ncol,fout, pa, interp,fill)
int16 **a,fill;
double pa;
FITS_HANDLE fout;
int nrow,ncol;
PFI16 interp;
{
	int i,row;
	double cpa,spa;
	double row_cen,col_cen,dr,dc,x,y;
	int16 buf[NMAX];

	spa=sin(pa *PF);
	cpa=cos(pa *PF);

	/* define the center of rotation */
	row_cen=nrow/2.;
	col_cen=ncol/2.;

	for(row=0; row<nrow ; row++){
		dr= row-row_cen;
		for(i=0; i<ncol; i++) {
			dc= i - col_cen;
			x= -spa * dr + cpa *dc + col_cen;
			y=  cpa * dr + spa *dc + row_cen;
			if (interp == (PFI16) sinc) {
				initsinc(x, y);
			}
			buf[i]=(*interp)(x,y,a,nrow,ncol,fill);
		}
		fits_put_data(fout,row,0,buf,ncol);
	}
}

/*	now do the trivial cases by re-binning 
		The words 'left', 'right' and 'updown' are hopefully
		similar to vista
*/

static void rot_left( a, nrow,ncol,fout)
int16 **a;
int nrow,ncol;
FITS_HANDLE fout;
{
	int i,row,old_col;
	int16 buf[NMAX];

	for(row=0,old_col=nrow; row< nrow; row++){
		old_col --;
		for(i=0 ; i<ncol; i++)
			buf[i] = a[i][old_col]; 
		fits_put_data(fout,row,0,buf,ncol);
	}
}


static void rot_right( a, nrow,ncol,fout)
int16 **a;
int nrow,ncol;
FITS_HANDLE fout;
{
	int i,row,old_row;
	int16 buf[NMAX];

	for(row=0; row< nrow; row++){
		for(i=0,old_row=ncol; i<ncol; i++){
			old_row--;
			buf[i] = a[old_row][row]; 
		}
		fits_put_data(fout,row,0,buf,ncol);
	}
}

static void rot_ud( a, nrow,ncol,fout)
int16 **a;
int nrow,ncol;
FITS_HANDLE fout;
{
	int i,row,old_row,old_col;
	int16 buf[NMAX],*p;

	for(row=0,old_row=nrow; row< nrow; row++){
		old_row --;
		p=a[old_row];
		for(i=0,old_col=ncol; i<ncol; i++){
			old_col--;
			buf[i] = p[old_col]; 
		}
		fits_put_data(fout,row,0,buf,ncol);
	}
}




static void 
show_options(fp)
FILE *fp;
{
	fprintf(fp,
		"usage: rotate image_file [left] [right] [ud] [pa=] [outfile=] ");
	fprintf(fp, "[fill=] [help]\n");
}

