/*===========================================================================
  Copyright (C) 1995-2011 European Southern Observatory (ESO)
 
  This program is free software; you can redistribute it and/or 
  modify it under the terms of the GNU General Public License as 
  published by the Free Software Foundation; either version 2 of 
  the License, or (at your option) any later version.
 
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
 
  You should have received a copy of the GNU General Public 
  License along with this program; if not, write to the Free 
  Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, 
  MA 02139, USA.
 
  Correspondence concerning ESO-MIDAS should be addressed as follows:
	Internet e-mail: midas@eso.org
	Postal address: European Southern Observatory
			Data Management Division 
			Karl-Schwarzschild-Strasse 2
			D 85748 Garching bei Muenchen 
			GERMANY
===========================================================================*/

/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.IDENT        genxy1.c
.LANGUAGE     C
.AUTHOR       K. Banse   ESO/IPG
.KEYWORDS     Bulk data frames, Images
.PURPOSE      a) copy images
	      b) rearrange planes of a cube
	      c) convert descr sequences to a table (e.g. VIMOS data)

.VERSION      1.00  950921:   Creation 

 111123		last modif
---------------------------------------------------------------------*/

#define MAXSUBS  15

#include <stdlib.h>
#include <stdio.h>


#include   <midas_def.h>

/*

*/

void convert(infile,outfile)
char    *infile, *outfile;

{
char    cbuf[124], instring[124], tmpstr[124], *ptra;
char    dscroot[48], fulldscroot[124], *dscsub[MAXSUBS], *helpsub[MAXSUBS];
char    sfmt[8];

int  imnoa, tid;
int  dtype[MAXSUBS], colno[MAXSUBS], csize[MAXSUBS], hlen[MAXSUBS];
int  mn, mm, maxsubs, nval, null, unit;
int  n, convdir, bytelm, status;
int  ec, el, ed, ln1, ln0, delflag;
int  nrow, nrowmax, dlim[2], single;
int  ival;

float rval;

double dval;


/*

Midas command: 
CONVERT/DESCR_MATRIX image  table  direction 
              dscroot[,first[,last]]  dscsub1,dscsub2,...  del_flag
 
*/

status = 0;
single = 0;			/* set, if 1-dim array instead of matrix */
(void) strcpy(sfmt,"%s%d.");

(void) SCKGETC("P3",1,4,&nval,cbuf);	/* which way to go? */
CGN_LOWSTR(cbuf);
mm = strcmp(cbuf,"t-ds");
if (mm != 0)				/* descriptors -> table */
   {
   convdir = 1;
   (void) SCKRDI("INPUTI",1,1,&nval,&delflag,&unit,&null);  /* delete flag */
   }
else					/* table -> descriptors */
   {
   convdir = 2;
   delflag = 0;
   (void) TCTOPN(outfile,F_I_MODE,&tid);
   (void) TCIGET(tid,&maxsubs,&nrowmax,&mn,&mn,&mn);
   (void) SCDRDI(tid,"DESCR_MATRIX",1,1,&nval,&single,&unit,&null);
   }



/* look for root part of descr and optional index limits */

if (single == 1) 			/* that implies convdir = 2 ! */
   {
   (void) strcpy(sfmt,"%s%d");
   (void) SCDGETC(tid,"DESCR_ROOT",1,120,&nval,fulldscroot);
   }
else
   {
   (void) SCKGETC("P4",1,120,&nval,fulldscroot);
   if ((fulldscroot[0] == '+') || (fulldscroot[0] == '?'))
      {						/* nothing entered */
      if (convdir == 1)
         SCETER(67,"missing root of descr...");
					/* get info from table descr. */
      (void) SCDGETC(tid,"DESCR_ROOT",1,120,&nval,fulldscroot);
      }
   }


/* and process	root[,first[,last]] */

(void) strcpy(instring,fulldscroot);
mm = CGN_INDEXC(instring,',');
if (mm > 0)
   {
   instring[mm] = '\0';
   (void) strcpy(dscroot,instring);		/* copy first string */
   (void) strcpy(tmpstr,&instring[mm+1]); // source and destination cannot
   (void) strcpy(instring,tmpstr); // overlap in strcpy() 
   mm = CGN_INDEXC(instring,',');
   if (mm > 0)
      mm = 2;
   else
      {
      mm = 1;
      dlim[1] = -1;
      }
   n =  CGN_CNVT(instring,1,mm,dlim,&rval,&dval);
   if (n != mm) SCETER(64,"invalid start, end indices...");

   if (dlim[0] < 1) dlim[0] = 1;
   if ((mm == 2) && (dlim[1] < dlim[0]))
      SCETER(65,"invalid start, end indices...");
   }
else
   {
   (void) strcpy(dscroot,instring);
   dlim[0] = 1;				/* index of first descr. */
   dlim[1] = -1;			/* index of last descr. */
   }


/* allocate virtual space for subDSCs and their help 
   max 46 chars per subDSC and 72 chars per help string */

mm = 48 + 74;			/* use multiples of 4 for nicer handling */

dscsub[0] = (char *) malloc((size_t) (MAXSUBS * mm));
if (dscsub[0] == (char *) 0)
   SCETER(66,"could not allocate virtual memory...");
helpsub[0] = dscsub[0] + (MAXSUBS * 48);	/* skip to help string part */

for (n=1; n<MAXSUBS; n++)
   {
   dscsub[n] = dscsub[n-1] + 48;
   helpsub[n] = helpsub[n-1] + 74;
   }


/* open the image for access to FITS/descr. header */

(void) SCFOPN(infile,D_OLD_FORMAT,0,F_IMA_TYPE,&imnoa);
(void) SCECNT("GET",&ec,&el,&ed);
ln1 = 1; ln0 = 0;


/* ........................................

   Descriptors -> Table

   ......................................... */


if (convdir == 1)
   {
   maxsubs = 1;			 /* parse individual descr fields (subDCS) */
   (void) SCKGETC("P5",1,120,&nval,instring);
   if ((instring[0] == '?') || (instring[0] == '+'))
      {
      single = 1;
      (void) strcpy(dscsub[0],"");		/* points to Nirwana... */
      (void) strcpy(sfmt,"%s%d");
      }
   else
      {
      ptra = instring;

      for (n=0; n<MAXSUBS; n++)
         {
         mm = CGN_INDEXC(ptra,',');
         if (mm > 0)			
            {
            *(ptra+mm) = '\0';
            (void) strcpy(dscsub[n],ptra);
            ptra += (mm+1);
            maxsubs ++;
            }
         else
            {
            (void) strcpy(dscsub[n],ptra);
            break;
            }
         }
      }


   /* move descriptors to binary table */

   if (single == 0)
      (void) 
      printf("use as descr_root:   %s###\nand as descr_fields: ",dscroot);
   else
      (void) 
      printf("use as descr_root:   %s### and no descr_fields ",dscroot);

   (void) sprintf(instring,sfmt,dscroot,dlim[0]);	/* for first descr. */
   mm = (int) strlen(instring);

   for (n=0; n<maxsubs; n++)
      {
      (void) strcpy(&instring[mm],dscsub[n]);
      (void) SCDFND(imnoa,instring,cbuf,&nval,&bytelm);
      if (cbuf[0] == ' ')
         SCETER(62,"could not get descr_field type...");

      csize[n] = 1;
      if (cbuf[0] == 'I')
         dtype[n] = 1;
      else if (cbuf[0] == 'R')
         dtype[n] = 2;
      else if (cbuf[0] == 'D')
         dtype[n] = 4;
      else				/* only C (character) left */
         {
         dtype[n] = 3;
         csize[n] = nval * bytelm;		/* size of char. column */
         }
   
      (void) printf("%s, ",dscsub[n]);

      (void) SCDRDH(imnoa,instring,1,72,&nval,cbuf,&mn);
      if (mn < 1) 
         *helpsub[n] = '\0';
      else
         {
         cbuf[nval] = '\0';
         (void) strcpy(helpsub[n],cbuf);
         }
      }

   if (single == 0)
      (void) printf("\n=> table will be created with %d columns\n",maxsubs);
   else
      {
      (void) printf("\n=> table will be created with %d column\n",maxsubs);
      (void) strcpy(dscsub[0],dscroot);
      }


   /* create the table with `maxsubs' cols * 200 rows */

   (void) TCTINI(outfile,F_TRANS,F_O_MODE,maxsubs,200,&tid);

   for (n=0; n<maxsubs; n++)
      {
      if (dtype[n] == 1)
         status = TCCINI(tid,D_I4_FORMAT,1,"I8"," ",dscsub[n],&colno[n]);
      else if (dtype[n] == 2)
         status = TCCINI(tid,D_R4_FORMAT,1,"G12.6"," ",dscsub[n],&colno[n]);
      else if (dtype[n] == 4)
         status = TCCINI(tid,D_R8_FORMAT,1,"G12.6"," ",dscsub[n],&colno[n]);
      else 
         {
         mn = (int) strlen(dscsub[n]);
         nval = ((mn - 1)%8 + 1) * 8;		/* => chunks of 8 chars */
         (void) sprintf(cbuf,"a%d",nval);
         status = TCCINI(tid,D_C_FORMAT,csize[n],cbuf," ",dscsub[n],&colno[n]);
         }

      if (status != ERR_NORMAL)
         SCETER(63,"could not create table columns...");
      }

   (void) SCDWRC(tid,"DESCR_ROOT",1,fulldscroot,1,120,&unit);
   (void) SCDWRI(tid,"DESCR_MATRIX",&single,1,1,&unit);
   for (n=0; n<maxsubs; n++)
      {
      (void) sprintf(instring,"DESCR_%4.4d",n);
      (void) SCDWRC(tid,instring,1,dscsub[n],1,(int)strlen(dscsub[n]),&unit);
      if (*helpsub[n] != '\0')
         {
         hlen[n] = (int) strlen(helpsub[n]);
         (void) SCDWRH(tid,instring,helpsub[n],1,hlen[n]);
         }
      }

   if (single == 1) (void) strcpy(dscsub[0],"");


   /* loop through header of file */
   
   (void) SCECNT("PUT",&ln1,&ln0,&ln0);		/* now, ignore errors */

   if (dlim[1] == -1) dlim[1] = 200000;
   nrow = 1;

   for (mn=dlim[0]; mn<dlim[1]+1 ; mn++)
      {
      (void) sprintf(instring,sfmt,dscroot,mn);	/* build DSC name */
      mm = (int) strlen(instring);

      for (n=0; n<maxsubs; n++)
         {
         (void) strcpy(&instring[mm],dscsub[n]);
         if (dtype[n] == 1)
            {
            status = SCDRDI(imnoa,instring,1,1,&nval,&ival,&unit,&null);
            if (status == ERR_NORMAL)
               {
               (void) TCEWRI(tid,nrow,colno[n],&ival);
               if (delflag == 1) (void) SCDDEL(imnoa,instring);
               }
            }
         else if (dtype[n] == 2)
            {
            status = SCDRDR(imnoa,instring,1,1,&nval,&rval,&unit,&null);
            if (status == ERR_NORMAL)
               {
               (void) TCEWRR(tid,nrow,colno[n],&rval);
               if (delflag == 1) (void) SCDDEL(imnoa,instring);
               }
            }
         else if (dtype[n] == 4)
            {
            status = SCDRDD(imnoa,instring,1,1,&nval,&dval,&unit,&null);
            if (status == ERR_NORMAL)
               {
               (void) TCEWRD(tid,nrow,colno[n],&dval);
               if (delflag == 1) (void) SCDDEL(imnoa,instring);
               }
            }
         else 				/* only char string left */
            {
            status = SCDRDC(imnoa,instring,1,1,80,&nval,cbuf,&unit,&null);
            if (status == ERR_NORMAL)
               {
               cbuf[nval] = '\0';
               (void) TCEWRC(tid,nrow,colno[n],cbuf);
               if (delflag == 1) (void) SCDDEL(imnoa,instring);
               }
            }

         }

      if (status == ERR_DSCNPR)
         {
         nrow --;			/* adjust no. of rows written */
         (void) sprintf(instring,"%d rows created",nrow);
         SCTPUT(instring);
         break;
         }

      nrow ++;
      }
   }


/* ........................................

   Table -> Descriptors

   ......................................... */
 
else
   {
   for (n=0; n<maxsubs; n++)		/* find all columns to process */
      {
      (void) sprintf(cbuf,"#%d",n+1);
      (void) TCCSER(tid,cbuf,&colno[n]);
      if (colno[n] == -1) 
         SCETER(68,"input column bad...");

      (void) TCFGET(tid,colno[n],cbuf,&mn,&nval);
      csize[n] = 1;
      if (nval == D_C_FORMAT)
         {
         dtype[n] = 3;
         csize[n] = mn;
         }
      else if (nval == D_R8_FORMAT)
         dtype[n] = 4;
      else if (nval == D_R4_FORMAT)
         dtype[n] = 2;
      else 
         dtype[n] = 1;			/* all other => integer */

      (void) sprintf(instring,"DESCR_%4.4d",n);
      (void) SCDHRC(tid,instring,1,1,46,&nval,dscsub[n],cbuf,72,&unit,&null);
      *(dscsub[n] + nval) = '\0';	/* strings from descr. have no '\0' */
      (void) strcpy(helpsub[n],cbuf);
      hlen[n] = (int) strlen(cbuf);

/*
      printf("dscsub[%d] = >%s<, type = %d, size = %d\n",
             n,dscsub[n],dtype[n],csize[n]);
      printf("helpsub[%d] = >%s<, hlen = %d\n\n",
             n,helpsub[n],hlen[n]);
*/
      }

   if (single == 1) (void) strcpy(dscsub[0],"");


   /* move binary table to descriptors */

   (void) SCECNT("PUT",&ln1,&ln0,&ln0);		/* now, ignore errors */

   mn = dlim[0];
   if (dlim[1] == -1) dlim[1] = nrowmax;
   nrow = 1;

  table_loop:
   (void) sprintf(instring,sfmt,dscroot,mn);	/* build DSC name */
   mm = (int) strlen(instring);

   for (n=0; n<maxsubs; n++)
      {
      (void) strcpy(&instring[mm],dscsub[n]);

      if (dtype[n] == 1)
         {
         status = TCERDI(tid,nrow,colno[n],&ival,&null);
         if (status == ERR_NORMAL)
            (void) xSCDWRI(imnoa,instring,&ival,1,1,&unit);
         }
      else if (dtype[n] == 2)
         {
         status = TCERDR(tid,nrow,colno[n],&rval,&null);
         if (status == ERR_NORMAL)
            (void) xSCDWRR(imnoa,instring,&rval,1,1,&unit);
         }
      else if (dtype[n] == 4)
         {
         status = TCERDD(tid,nrow,colno[n],&dval,&null);
         if (status == ERR_NORMAL)
            (void) xSCDWRD(imnoa,instring,&dval,1,1,&unit);
         }
      else 				/* only character left */
         {
         status = TCERDC(tid,nrow,colno[n],cbuf,&null);
         if (status == ERR_NORMAL)
            (void) xSCDWRC(imnoa,instring,1,cbuf,1,csize[n],&unit);
         }

      if (*helpsub[n] != '\0')
         (void) xSCDWRH(imnoa,instring,helpsub[n],1,hlen[n]);
      }

   mn ++; nrow ++;
   if ((mn > dlim[1]) || (nrow > nrowmax)) 
      {
      nrow --;			/* adjust no. of rows written */
      (void) sprintf(instring,"%d rows processed",nrow);
      SCTPUT(instring);
      }
   else
      goto table_loop;
   }


(void) SCECNT("PUT",&ec,&el,&ed);		/* reset error flags */

(void) SCKWRI("OUTPUTI",&nrow,9,1,&unit);      /* save in OUTPUTI(9) */

(void) TCTCLO(tid);
(void) SCFCLO(imnoa);

}
/*

*/

void mappi(in,map,out,nval,aux,msize,flag,oo)
float  *in;	/* IN: input buffer */
float  *map;	/* IN: the map buffer */
float  *out;	/* OUT: result buffer */
int    nval;	/* IN: no. of pixels */
float  *aux;	/* IN: aux[0] = fact, aux[1] = xlo, aux[2] = xhi */
int    msize;	/* IN: highest index of map */
int    flag;	/* IN: = 0, do scaling - = 1, take value directly as index */
float  *oo;	/* OUT: min, max value */

{
register int   nr, indx, mindx;

float   fact, xlo, xhi, mapmax;
register float  rin, rout, turbo;



mindx = msize - 1;
fact = aux[0]; xlo = aux[1]; xhi = aux[2];
turbo = 0.5 - fact*xlo;
mapmax = *(map+mindx);

if (flag == 0)
   {

   /* indx = 1 + NINT((r - xlo)*fact); but  first pixel of map has indx = 0
   => indx = NINT(r*fact - xlo*fact) or (int) (r*fact - xlo*fact + 0.5) */

   for (nr=0; nr<nval; nr++)
      {
      rin = *in++;
      if (rin <= xlo)
         rout = *map;
      else if (rin >= xhi)
         rout = mapmax;
      else
         {
         indx = (int) (rin*fact + turbo);	
         rout = *(map+indx);
         }
      if (rout < oo[0])
         oo[0] = rout;
      else if (rout > oo[1])
         oo[1] = rout;
      *out++ = rout;
      }
   }
else
   {

   /* indx = NINT(r) */

   for (nr=0; nr<nval; nr++)
      {
      indx = (int) (turbo + (*in++));	
      if (indx <= 0)
         rout = *map;
      else if (indx >= mindx)
         rout = mapmax;
      else
         rout = *(map+indx);
      if (rout < oo[0])
         oo[0] = rout;
      else if (rout > oo[1])
         oo[1] = rout;
      *out++ = rout;
      }
   }

}
/*

*/

int check_fmt(cbuf)
char  *cbuf;

{
int  ibra;

ibra = *cbuf;
cbuf ++;

switch (ibra)
   {
   case 'I':
   case 'i':

   if (*cbuf == '1')
      return (D_I1_FORMAT);
   else if (*cbuf == '2')
      return (D_I2_FORMAT);
   else if (*cbuf == '4')
      return (D_I4_FORMAT);
   else
      break;


   case 'U':
   case 'u':

   if ((*cbuf == 'I') || (*cbuf == 'i'))
      {
      if (*(++cbuf) == '2')
         return (D_UI2_FORMAT);
      }


   case 'R':
   case 'r':

   if (*cbuf == '8')
      return (D_R8_FORMAT);
   else
      return (D_R4_FORMAT);
   

   case 'D':
   case 'd':

   return (D_R8_FORMAT);


   default:
      break;
   }

return (-1);			/* wrong format  */
}
/*

*/

void mapima(infile,mapfile,outfile)
char    *infile, *mapfile, *outfile;

{
char    *pntra, *pntrb, *pntrc, cbuf[4];

int  naxis, npix[6], imnoa, imnob, imnoc, imnow1, imnow2;
int  felm, mapsize, sizze, msize, clony;
int  n, null, nval, unit, scflag;

float   cuts[4], fact, oldoo[2], oo[2], faux[3];



(void) SCKRDI("MONITPAR",20,1,&nval,&n,&unit,&null);  /* get storage size */
mapsize = n * n;

(void) SCKGETC("P5",1,2,&nval,cbuf);
if ((cbuf[0] == 's') || (cbuf[0] == 'S'))
   scflag = 0;
else
   scflag = 1;			/* use pixel value directly as index for map */

imnoa = -1;
(void) SCFOPN(infile,D_R4_FORMAT,0,F_IMA_TYPE,&imnoa);
(void) SCDRDI(imnoa,"NAXIS",1,1,&nval,&naxis,&unit,&null);
if (naxis > 6) SCETER(3,"More than 6 dimensions...");

(void) SCDRDI(imnoa,"NPIX",1,naxis,&nval,npix,&unit,&null);

sizze = 1;					/*  get total size of frame  */
for (n=0; n< naxis; n++) sizze *= npix[n];

(void) SCKRDR("INPUTR",1,2,&nval,cuts,&unit,&null);  /* get mapping interval */
if (cuts[1] <= cuts[0])
   {
   (void) SCDRDR(imnoa,"LHCUTS",3,2,&nval,cuts,&unit,&null);
   if (cuts[1] <= cuts[0])
      SCETER(23,"Invalid Map-limits (bad descr. LHCUTS)...");
   }


/* create new image and try to clone all descriptors */

(void) CGN_IBUILD(imnoa,outfile,D_R4_FORMAT,sizze,&imnoc,&clony);


/* get the complete image "map" */

imnob = -1;
(void) SCFOPN(mapfile,D_R4_FORMAT,0,F_IMA_TYPE,&imnob);
(void) SCDRDI(imnob,"NAXIS",1,1,&nval,&naxis,&unit,&null);
if (naxis > 6) SCETER(3,"More than 6 dimensions...");

(void) SCDRDI(imnob,"NPIX",1,naxis,&nval,npix,&unit,&null);

msize = 1;					/*  get total size of map  */
for (n=0; n< naxis; n++) msize *= npix[n];

(void) SCFMAP(imnob,F_I_MODE,1,msize,&nval,&pntrb);


/* compute aux-variables: 

   (pix - pxlo)/(pxhi - pxlo) = (x - cuts[0])/(cuts[1] - cuts[0])
   pix = pxlo + (x - cuts[0])*fact
   with fact = (pxhi - pxlo)/(cuts[1] - cuts[0])   */


/* allocate virtual memory for in/out frame buffers with right data types */

if (sizze <= mapsize) mapsize = sizze;
(void) SCFCRE("work1",D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,mapsize,&imnow1);
(void) SCFMAP(imnow1,F_X_MODE,1,mapsize,&nval,&pntra);
(void) SCFCRE("work2",D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,mapsize,&imnow2);
(void) SCFMAP(imnow2,F_X_MODE,1,mapsize,&nval,&pntrc);


fact = (msize-1) / (cuts[1] - cuts[0]);
faux[0] = fact; faux[1] = cuts[0]; faux[2] = cuts[1];

printf("index-range = [1,%d], map-range = [%f,%f], \n",
       msize,cuts[0],cuts[1]);

(void) SCDRDR(imnob,"LHCUTS",3,2,&nval,oldoo,&unit,&null);
if (oldoo[1] <= oldoo[0]) SCETER(24,"Invalid LHCUTS of mapfile...");

oo[0] = oldoo[1]; oo[1] = oldoo[0];	/* should be pixels in that interval */
oldoo[0] = oo[0]; oldoo[1] = oo[1];


/*  now we do the mapping   */

felm = 0;
while (felm < sizze)
   {
   n = felm + 1;
   (void) SCFGET(imnoa,n,mapsize,&nval,pntra);
   mappi(pntra,pntrb,pntrc,nval,faux,msize,scflag,oo);
   (void) SCFPUT(imnoc,n,nval,pntrc);
   felm += nval;
   if (oo[0] < oldoo[0]) oldoo[0] = oo[0];
   if (oo[1] > oldoo[1]) oldoo[1] = oo[1];
   }

if (clony == 0)
   (void) SCDCOP(imnoa,imnoc,1," ");   /* copy all descriptors */

cuts[0] = cuts[1] = 0.0;
cuts[2] = oldoo[0]; cuts[3] = oldoo[1];
(void) SCDWRR(imnoc,"LHCUTS",cuts,1,4,&unit);
}

/*

*/

void copyii(infile,outfile)
char    *infile, *outfile;

{
char    cbuf[12], dely[8];
char    *pntra, *pntrb;

int  naxis, npix[6], imnoa, imnob, imnow1, imnow2;
int  felm, mapsize, sizze, clony;
int  info[5], null, nval, unit;
int  n, fmtin, fmtout, uflow, oflow;

float   cuts[4];


(void) SCKGETC("P3",1,10,&nval,cbuf); 			/* get output format */
(void) SCKGETC("P4",1,7,&nval,dely);  			/* get delete flag   */

(void) SCKRDI("MONITPAR",20,1,&nval,&n,&unit,&null);  /* get mapping size */
mapsize = n * n;

(void) SCFINF(infile,2,info);			/* get source format  */
fmtin =  info[1];
fmtout = check_fmt(cbuf);
if (fmtout < 0) SCETER(2,"invalid data format...");

imnoa = -1;
(void) SCFOPN(infile,info[1],0,F_IMA_TYPE,&imnoa);
(void) SCDRDI(imnoa,"NAXIS",1,1,&nval,&naxis,&unit,&null);
if (naxis > 6) SCETER(3,"More than 6 dimensions...");

(void) SCDRDI(imnoa,"NPIX",1,naxis,&nval,npix,&unit,&null);
(void) SCDRDR(imnoa,"LHCUTS",1,4,&nval,cuts,&unit,&null);

uflow = 0; oflow = 0;
sizze = 1;					/*  get total size of frame  */
for (n=0; n< naxis; n++)
   sizze *= npix[n];

/* (void) SCFCRE(outfile,fmtout,F_O_MODE,F_IMA_TYPE,size,&imnob); */
(void) CGN_IBUILD(imnoa,outfile,fmtout,sizze,&imnob,&clony);


/* allocate virtual memory for in/out frame buffers with right data types */

if (sizze <= mapsize) mapsize = sizze;
(void) SCFCRE("work1",fmtin,F_X_MODE,F_IMA_TYPE,mapsize,&imnow1);
(void) SCFMAP(imnow1,F_X_MODE,1,mapsize,&nval,&pntra);

if (fmtin != fmtout)
   {
   (void) SCFCRE("work2",fmtout,F_X_MODE,F_IMA_TYPE,mapsize,&imnow2);
   (void) SCFMAP(imnow2,F_X_MODE,1,mapsize,&nval,&pntrb);
   }
else
   pntrb = pntra;


/*  now we do the conversion   */

felm = 0;
while (felm < sizze)
   {
   n = felm + 1;
   (void) SCFGET(imnoa,n,mapsize,&nval,pntra);
   if (fmtin != fmtout) 
      conv_pix(pntrb,pntra,fmtout,fmtin,nval);
   (void) SCFPUT(imnob,n,nval,pntrb);
   felm += nval;
   }


/*  handle over, underflow  */

if (fmtout == D_I1_FORMAT)
   {
   if (cuts[2] < 0) uflow = 1;
   if (cuts[3] > 255) oflow = 1;
   }
else if (fmtout == D_I2_FORMAT)
   {
   if (cuts[2] < -32768) uflow = 1;
   if (cuts[3] > 32767) oflow = 1;
   }
else if (fmtout == D_UI2_FORMAT)
   {
   if (cuts[2] < 0) uflow = 1;
   if (cuts[3] > 65534) oflow = 1;
   }
if (uflow == 1)
   SCTPUT("Warning: Format conversion results in underflow...");
if (oflow == 1)
   SCTPUT("Warning: Format conversion results in overflow...");


if (clony == 0)
   (void) SCDCOP(imnoa,imnob,1,cbuf);	/* copy all descriptors */

n = CGN_INDEXC(dely,',');		/* test history_update_flag */
if (n > 0)
   dely[1] = dely[n+1];
else
   dely[1] = 'u';

if ((dely[1] == 'U') || (dely[1] == 'u')) 
   (void) CGN_DSCUPD(imnob,imnob," ");		/* update history */



/* if delete flag set, delete the input frame  */

if ((dely[0] == 'D') || (dely[0] == 'd')) (void) SCFDEL(infile);
}

/*

*/

void transcube(infile,outfile)
char  *infile, *outfile;

{
char   cbuf[12], temp[128];
char   *pntra;

static char workfile[] = "middummxyz.bdf";

int  nobytes, mapsize, unit, null, fmtin;
int  naxis, npix[3], newpix[3], imnoa, imnob, imnow, size;
int  info[5], planedir, nval, mm[3];
register int  nr, mr;

double  start[3], step[3], nstart[3], nstep[3];


(void) SCFINF(infile,2,info);			/* get source format  */
nobytes = info[0];				/* bytes per pixel */
fmtin =  info[1];
planedir = 0;

(void) SCFOPN(infile,fmtin,0,F_IMA_TYPE,&imnoa);
(void) SCDRDI(imnoa,"NAXIS",1,1,&nval,&naxis,&unit,&null);
if (naxis != 3)
   SCETER(3,"Input image has not 3 dimensions...");
(void) SCDRDI(imnoa,"NPIX",1,naxis,&nval,npix,&unit,&null);
(void) SCDRDD(imnoa,"START",1,naxis,&nval,start,&unit,&null);
(void) SCDRDD(imnoa,"STEP",1,naxis,&nval,step,&unit,&null);


/* create working frame (may be renamed to output frame) */

size = npix[0] * npix[1] * npix[2];		/*  get total size of frame */
(void) SCFCRE(workfile,fmtin,F_O_MODE,F_IMA_TYPE,size,&imnob);


(void) SCKGETC("P3",1,4,&nval,cbuf); 			/* get plane specs */
CGN_UPSTR(cbuf);

if ( (strncmp(cbuf,"ZY",2) == 0) || (strncmp(cbuf,"YZ",2) == 0) )
   {
   mm[0] = 2;
   mm[1] = 1;
   mm[2] = 0;
   planedir = Z_Y_PLANE;
   if (cbuf[0] == 'Y')
      {
      SCTPUT(
"Warning: YZ-plane is handled as ZY-plane, i.e. rows are in z-direction...");
      }
   }
else if ( (strncmp(cbuf,"ZX",2) == 0) || (strncmp(cbuf,"XZ",2) == 0) )
   {
   mm[0] = 0;
   mm[1] = 2;
   mm[2] = 1;
   planedir = X_Z_PLANE;
   if (cbuf[0] == 'Z')
      {
      SCTPUT(
"Warning: ZX-plane is handled as XZ-plane, i.e. rows are in x-direction...");
      }
   }
else
   SCETER(3,"Invalid plane specification...");

for (nr=0; nr<3; nr++)
   {
   newpix[nr] = npix[mm[nr]];
   nstart[nr] = start[mm[nr]];
   nstep[nr] = step[mm[nr]];
   }

(void) SCDCOP(imnoa,imnob,1,cbuf); 		/* copy all descriptors */
(void) SCDWRI(imnob,"NPIX",newpix,1,naxis,&unit);	/* update NPIX */
(void) SCDWRD(imnob,"START",nstart,1,naxis,&unit);	/* update START */
(void) SCDWRD(imnob,"STEP",nstep,1,naxis,&unit);	/* update STEP */


/* allocate virtual memory for buffer with right data types */

mapsize = newpix[0] * newpix[1];
(void) SCFCRE("work1",fmtin,F_X_MODE,F_IMA_TYPE,mapsize,&imnow);
(void) SCFMAP(imnow,F_X_MODE,1,mapsize,&nval,&pntra);


/* loop through YZ- or XZ_planes and store them as XY_plane into
   workframe                                                     */

for (nr=0; nr<newpix[2]; nr++)
   {
   mr = nr + 1;
   (void) SCPGET(imnoa,planedir,mr,pntra);
   (void) SCPPUT(imnob,X_Y_PLANE,mr,pntra);
   }

CGN_DSCUPD(imnoa,imnob," ");		/* update history */


/* now test if result should replace input frame or go to a new frame */

if (outfile[0] == '+')
   CGN_CLEANF(infile,0,temp,120,&nval,&null);
else
   CGN_CLEANF(outfile,0,temp,120,&nval,&null);
(void) SCFRNM(workfile,temp);

}

/*

*/

int main()

{
char   infile[124], outfile[124], mapfile[124], cbuf[12];

int    nval;


(void) SCSPRO("genxy1");            

(void) SCKGETC("IN_A",1,120,&nval,infile);  		/* get input frame   */
(void) SCKGETC("OUT_A",1,120,&nval,outfile);  		/* get output frame  */

(void) SCKGETC("ACTION",1,3,&nval,cbuf);		/* get action flag */

if (strcmp(cbuf,"TRA") == 0) 
   transcube(infile,outfile);

else if (strcmp(cbuf,"COP") == 0) 
   copyii(infile,outfile);

else if (strcmp(cbuf,"CON") == 0) 
   convert(infile,outfile);

else if (strcmp(cbuf,"MAP") == 0) 
   {
   (void) SCKGETC("IN_B",1,120,&nval,mapfile);
   mapima(infile,mapfile,outfile);
   }

(void) SCSEPI();
return(0);

}
