/* @(#)ccopyf.c	19.2 (ESO-DMD) 05/20/03 09:42:23 */
/*===========================================================================
  Copyright (C) 1995 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
===========================================================================*/

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.COPYRIGHT:  Copyright (c) 1994 European Southern Observatory,
                                         all rights reserved
.IDENTIFIER  module CCOPYF
.LANGUAGE    C
.AUTHOR      K. Banse			IPG-ESO Garching
.KEYWORDS    
.COMMENTS    holds: Copywnd, Copyf, Copyf1, Copyf2, Copyi, Copyfx, Fillima
.ENVIRONment MIDAS
 #include <midas_def.h>   Prototypes for MIDAS interfaces
 
.VERSIONS    
 030520		last modif

------------------------------------------------------------*/

/* Define _POSIX_SOURCE to indicate that this is a POSIX program */

#define  _POSIX_SOURCE 1



#include <stdlib.h>
#include <midas_def.h>

/*

*/

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy parts of frame A to artifical 1dim frame B
.INPUT/OUTPUT
  call as    Fillima(flag,imno,npix,auxstr,insize,retimno)

  input:
          int   flag		0 = create art. image
				1 = fill image
				2 = expand image
				3 = get exact size of art. image
          int   imno		file id of input frame
          int   *npix		NPIX of input frame
	  char  *auxstr		aux. string with subarea info
  in/output:
	  int   *insize		IN: no. of pixels for art. image (flag = 0)
				OUT: current nopix of art. image (flag = 3)
  output:
	  int   *retimno	file id of artificial 1dim image

.RETURNS     = 0, if o.k.
	       < 0, if problems

------------------------------*/

int Fillima(flag,imno,npix,auxstr,insize,retimno)
int  flag, imno, *npix, *insize, *retimno;
char *auxstr;

{
int  first, stat, kk, iav, size, endx, endy, sublo[3], subhi[3];
register int nr, ny;
static int felem, totsize;

register float  *apntr, *bpntr, *xpntr;

char  *impntr;
static char  *mypntr, namend;



/*
printf("Fillima: flag = %d, totsize = %d, felem = %d\n",
       flag,totsize,felem);
*/


if (flag == 0)			/* create artificial image (allocate memory) */
   {
   if (*insize < 1) return (-2);
   totsize = *insize;			/* save nopix of 1-dim result image */
   namend = 'y';
   felem = 0;
   for (nr=0; nr<3; nr++)
      {
      sublo[nr] = subhi[nr] = 0;
      }

   stat = SCFCRE("middumm#y",D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,totsize,retimno);
   if (stat == ERR_NORMAL)
      stat = SCFMAP(*retimno,F_X_MODE,1,totsize,&iav,&mypntr);

   if (stat != ERR_NORMAL) return (-1);
   }

else if (flag == 1)			/* fill artificial image */
   {
   stat = Convcoo(1,imno,auxstr,3,&iav,sublo,subhi);
   if (stat != ERR_NORMAL) return (-3);
   
   endx = subhi[0] - sublo[0] + 1;
   endy = subhi[1] - sublo[1] + 1;
   size = endy * npix[0];			/* full strip */
   first = (sublo[1] * npix[0]) + 1;		/* 1st elem in input frame */
   kk = (endx*endy);				/* no. of pixels to copy */
 
   if ((felem+kk) > totsize) return (-4); 	/* check for overflow */
						/* get strip of input frame */
   stat = SCFMAP(imno,F_I_MODE,first,size,&iav,&impntr);

   apntr = (float *) impntr;
   apntr += sublo[0];
   bpntr = (float *) mypntr;
   bpntr += felem;

   for (ny=0; ny<endy; ny++)
      {
      xpntr = apntr;
      for (nr=0; nr<endx; nr++) *bpntr++ = *xpntr++;
      apntr += npix[0];
      }

   felem += kk;			/* update offset */
   (void) SCFUNM(imno);
   }

else if (flag == 2)			/* expand artificial image */
   {
   int  myimno;
 
   if (*insize < 1) return (-2);
   totsize = *insize;			/* save new size */

   if (namend == 'y')			/* switch between ...#z and ...#y */
      {
      stat = SCFCRE("middumm#z",D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,
                    totsize,&myimno);
      namend = 'z';
      }
   else
      {
      stat = SCFCRE("middumm#y",D_R4_FORMAT,F_X_MODE,F_IMA_TYPE,
                    totsize,&myimno);
      namend = 'y';
      }
   if (stat == ERR_NORMAL)
      stat = SCFMAP(myimno,F_X_MODE,1,totsize,&iav,&impntr);

   if (stat != ERR_NORMAL) return (-1);

   apntr = (float *) mypntr;
   bpntr = (float *) impntr;
   for (nr=0; nr<felem; nr++) *bpntr++ = *apntr++;
   stat = SCFCLO(*retimno);

   mypntr = impntr;			/* save new pointer + imno */
   *retimno = myimno;			/* felem remains as it is */
   }

else
   {
   *insize = felem;			/* just get current size */
   }

return (0);
}

/*

*/

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy (part of) frame A to frame B, start pixels don't have to be
             the same
.ALGORITHM   Note, that all arrays are foreseen for 3-D frames
.INPUT/OUTPUT
  call as    Ccopwnd( pntrA, npixA, pntrB, npixB, bgnA, bgnB, endA )

  input:
          float *pntrA		input frame A
          int   npixA[3]	NPIX of A
          float *pntrB		output frame B
          int   npixB[3]	NPIX of B
          int   bgnA[3]		start pixel of window in A
          int   bgnB[3]		start pixel of window in B
          int   endA[3]         end pixel of window in A

.RETURNS     nothing
------------------------------*/

void Ccopwnd( pntrA, npixA, pntrB, npixB, bgnA, bgnB, endA )
int   *npixA, *npixB, *bgnA, *bgnB, *endA;
float *pntrA, *pntrB;

{
register int ix, iy, iz, xyz;

int offsA, offsB, dimwA[3], dimwB[3];


/*  Make sure, son frame fits into father frame */

for (xyz=0; xyz<3; xyz++)
   {
   dimwA[xyz] = endA[xyz] - bgnA[xyz] + 1;
   dimwB[xyz] = npixB[xyz] - bgnB[xyz] + 1;
   if ( dimwA[xyz] > dimwB[xyz] ) dimwA[xyz] = dimwB[xyz];
   } 

offsA = npixA[0] - dimwA[0];
offsB = npixB[0] - dimwA[0];


/* Move the pointers to start positions */

pntrA += bgnA[0] - 1 + npixA[0]*((bgnA[1] - 1) + npixA[1] * (bgnA[2] -1));
pntrB += bgnB[0] - 1 + npixB[0]*((bgnB[1] - 1) + npixB[1] * (bgnB[2] -1));

/* Copy frame A to frame B */

for (iz=0; iz<dimwA[2]; iz++)
   {
   for (iy=0; iy<dimwA[1]; iy++)
      {
      for (ix=0; ix<dimwA[0]; ix++) *pntrB++ = *pntrA++;
      pntrA += offsA;
      pntrB += offsB;
      }
   }
}

/*

*/

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy (part of) frame A to frame B, start pixels don't have to be
             the same
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    Ccopyf1( pntrA, npixA, bgnA, dimwA, pntrB, npixB, bgnB )

  input:
          float *pntrA		input frame A
          int   npixA[2]	NPIX of A
          int   bgnA[2]         start pixel of window in A
          int   dimwA[2]        dimension of window in A
          float *pntrB		output frame B
          int   npixB[2]	NPIX of B
          int   bgnB[2]		start pixel of window in B

.RETURNS     nothing
------------------------------*/

void Ccopyf1( pntrA, npixA, bgnA, dimwA, pntrB, npixB, bgnB )
int   *npixA, *npixB, *bgnA, *bgnB, *dimwA;
float *pntrA, *pntrB;
{
register int ix, iy;

int offsA = npixA[0] - dimwA[0],
    offsB = npixB[0] - dimwA[0];
      
/*
 * Move the pointers to start positions
 */
pntrA += bgnA[0] - 1 + npixA[0] * (bgnA[1] - 1);
pntrB += bgnB[0] - 1 + npixB[0] * (bgnB[1] - 1);

/*
 * Copy frame A to frame B
 */
for ( iy = 0; iy < dimwA[1]; iy++ )
    { for ( ix = 0; ix < dimwA[0]; ix++ ) *pntrB++ = *pntrA++;
      pntrA += offsA;
      pntrB += offsB;
    }
}

/*

*/

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy a constant value to (part of) frame B
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    Ccopyf2( value, pntrB, npixB, bgnB, dimwB )

  input:
          float value		constant value
          float *pntrB		output frame B
          int   npixB[2]	NPIX of B
          int   bgnB[2]		start pixel of window in B
          int   dimwB[2]        dimension of window in B

.RETURNS     nothing
------------------------------*/

#ifdef __STDC__
void Ccopyf2( float value, float *pntrB, int *npixB, int *bgnB, int *dimwB )
#else
void Ccopyf2( value, pntrB, npixB, bgnB, dimwB )
int   *npixB, *bgnB, *dimwB;
float value, *pntrB;
#endif
{
register int ix, iy; 

int offsB = npixB[0] - dimwB[0];
      
/*
 * Move the pointers to start positions
 */
pntrB += bgnB[0] - 1 + npixB[0] * (bgnB[1] - 1);

/*
 * Copy value to frame B
 */
for ( iy = 0; iy < dimwB[1]; iy++ )
    { for ( ix = 0; ix < dimwB[0]; ix++ ) *pntrB++ = value;
      pntrB += offsB;
    }
}

/*

*/

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy (part of) floating point frame A to frame B
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    Ccopyf( pntrA, pntrB, dim )

  input:
          float *pntrA		input frame A
          float *pntrB		output frame B
          int   dim		number of items to be copied

.RETURNS     nothing
------------------------------*/

void Ccopyf( pntrA, pntrB, dim )
int   dim;
float *pntrA, *pntrB;
{
register int ii;      

for ( ii = 0; ii < dim; ii++ ) *pntrB++ = *pntrA++;
}

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy (part of) integer frame A to frame B
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    Ccopyi( pntrA, pntrB, dim )

  input:
          int *pntrA		input frame A
          int *pntrB		output frame B
          int dim		number of items to be copied

.RETURNS     nothing
------------------------------*/

void Ccopyi( pntrA, pntrB, dim )
int *pntrA, *pntrB, dim;
{
register int ii;      

for ( ii = 0; ii < dim; ii++ ) *pntrB++ = *pntrA++;
}
/*

*/

/*++++++++++++++++++++++++++++++
.PURPOSE     Copy a "big" file in pieces
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    Ccopyfx(pntrA,imni,imno,npix,istrip)

  input:
          float *pntrA		working buffer, size = *npix * istrip
          int   imni		file no. of input data frame
          int   imno		file no. of output data frame
          int   npix		NPIX
          int   strip		no. of lines to be copied

.RETURNS     nothing
------------------------------*/

#ifdef __STDC__
 void Ccopyfx(float *pntrA,int imni,int imno,int *npix,int strip)
#else
 void Ccopyfx(pntrA,imni,imno,npix,strip)
 int   imni, imno, strip, *npix;
 float *pntrA;
#endif

{
int   actvals, felem, ksize, looplm;
register int   nr;

char *cpntrA;


cpntrA = (char *) pntrA;
looplm = npix[1] / strip;
if ((npix[1] - (looplm*strip)) > 0) looplm ++;

felem = 1;
ksize = npix[0] * strip;

for (nr=0; nr<looplm; nr++)
   {						/* actvals <- real size */
   (void) SCFGET(imni,felem,ksize,&actvals,cpntrA);
   (void) SCFPUT(imno,felem,actvals,cpntrA);
   felem += actvals;				/* update I/O pointer */
   }

}
