/*===========================================================================
  Copyright (C) 1995-2009 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  DCLOAD
.LANGUAGE    C
.AUTHOR      K. Banse			IPG-ESO Garching
.KEYWORDS    ImageDisplay
.PURPOSE     load an image into image display
.ALGORITHM   
             
.INPUT/OUTPUT
  call as    DCLOAD(imno,name,dattyp,icent,cuts,scale,chan_flag)

  input:
         int   imno      : image no. of input image
         char  *name     : name of the image
         int   dattyp    : data type (as D_xx_FORMAT)
         int   icen[4]   : fixpoint: screen pixels + frame pixels
         float cuts[2]   : low + high cut in z-dir.
         int   scale[3]  : scaling factors for image in x,y
                           [0,1]  if > 1: make image smaller
                                  if < 1: make image larger
                           [2]    flag for using max (= 3), using min (= 2),
				       for averaging (= 1) or not (= 0)

         int   chan_flag : = 0, load into QIMCH
                           = 1, load into QIMCH and following channels
                                only applicable to 3dim image loading


.RETURNS     nothing
.COMMENT     uses MIDAS keywords: MID$DISP, MID$SPEC & SIZIN
.ENVIRONment MIDAS
             #include <midas_def.h>   Prototypes for MIDAS interfaces
             #include <idinumd.h>     Global variables for DISPLAY interfaces
 
.VERSIONS    1.00       940413  from LODIMA.FOR    RvH

 090706		last modif
------------------------------------------------------------*/

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

#define  _POSIX_SOURCE 1

#include <midas_def.h>
#include <idinumd.h>
#include <proto_II.h>

#include <stdio.h>
#include <string.h>
 

#ifndef TRUE
#define TRUE            1
#define FALSE           0
#endif

#define DEFMEMSIZE	512

#define MYMIN(a,b)	((a) > (b) ? (b) : (a))
#define MYMAX(a,b)	((b) > (a) ? (b) : (a))

/*

*/

void DCLOAD(imno,name,dattyp,icent,cuts,scale,chan_flag)
char  *name;
int   imno, dattyp, *icent, *scale, chan_flag;
float *cuts;

{
register int nr, mr; 

int  naxis;
int  actvals, dsplfl, flag, idum, kcount;
int  knul, offs, size, splmod, unit, dazhld[11], khelp[15], mapsiz[2];
int  stat, qsize[2], npix[3], splcx[4][5], splcy[4][5];

int  idiserver;			/* = 1, do it in the IDIserver directly;
				   = 0, send data via IDI interfaces */

double ddum, step[3], start[3];

char  outfra[120], cbuff[24], ourname[120];

void out_error();




kcount = 0;
for (nr=0; nr<15; nr++) khelp[nr] = 0;

nr = CGN_INDEXC(name,']');         /* look for name[...] first */
if (nr > 0)
   {
   if (name[nr+1] == ',')
      idum = nr + 1;
   else
      idum = 0;
   }
else
   idum = CGN_INDEXC(name,',');		/* look for name,f_plane,l_plane */

(void) SCDRDI(imno,"NAXIS",1,1,&actvals,&naxis,&unit,&knul);
if (naxis > 3) naxis = 3;                       /* limit to 3-dims */

if (idum > 0)
   {
   (void) strncpy(ourname,name,idum);		/* copy only name */
   ourname[idum] = '\0';

   if (naxis < 3)
      SCTPUT("2-dim image, no plane_specs should be given...");
   else
      {
      (void) strcpy(outfra,&name[idum+1]);
      if ((outfra[0] == 'a') || (outfra[0] == 'A'))
         {
         khelp[11] = 1;
         khelp[12] = -1;
         nr = CGN_INDEXC(outfra,',');		/* image,all,delay_time */
         if (nr > 0)
            {
            nr ++;
            stat = CGN_CNVT(&outfra[nr],1,1,&khelp[13],cuts,&ddum);
            }
         }
      else
         {
         nr = CGN_INDEXS(outfra,"..");
         if (nr > 0)
            {
            outfra[nr++] = ',';
            outfra[nr] = ' ';
            }
         stat = CGN_CNVT(outfra,1,3,&khelp[11],cuts,&ddum);
         if (stat < 1)
            {
            (void) sprintf(outfra,
                           "invalid plane no.s (= %s) ...",&name[idum+1]);
            SCETER(5,outfra);
            }
         else if (stat == 1)
            khelp[12] = khelp[11];			/* single plane */
         }
      }
   }
else
   {
   (void) strcpy(ourname,name);
   if (naxis > 2)
      {
      khelp[11] = 1;
      khelp[12] = 1;
      SCTPUT ("1. plane of image cube will be loaded...");
      }
   }


/* get descriptors of input frame */

for (nr=0; nr<3; nr++)
   {
   npix[nr] = 1;
   start[nr] = 0.0;
   step[nr] = 1.0;
   }

(void) SCDRDI(imno,"NPIX",1,naxis,&actvals,npix,&unit,&knul);
(void) SCDRDD(imno,"START",1,naxis,&actvals,start,&unit,&knul);
(void) SCDRDD(imno,"STEP",1,naxis,&actvals,step,&unit,&knul);
size = *npix * npix[1];

if (naxis > 2)
   {
   if ( (khelp[11] == -1) || (khelp[11] > npix[2]) )
      khelp[11] = npix[2];
   else if (khelp[11] < 1)
      khelp[11] = 1;
   if ( (khelp[12] == -1) || (khelp[12] > npix[2]) )
      khelp[12] = npix[2];
   else if (khelp[12] < 1)
      khelp[12] = 1;

   if (chan_flag == 0)
      khelp[10] = 1;
   else				/* only allow as many planes as channels */
      {				/* from QIMCH on exist */
      khelp[10] = 2;

      kcount = QLSTCH - QIMCH;	/* no of available channels */
      nr = kcount + (khelp[11] - 1);	/* last possible plane to load */
      if (khelp[12] > nr) khelp[12] = nr;
      }
   }


/*  test, if we should load into a frame */

(void) SCKGETC("MID$DISP",1,22,&actvals,cbuff);
if ((*cbuff != 'I') && (*cbuff != 'i'))
   {
   (void) strcpy(outfra,cbuff+2);
   if ((*cbuff != 'F') && (*cbuff != 'f'))
      {
      dsplfl = -1;
      (void) SCKGETC("MID$SESS",11,2,&actvals,cbuff);
      (void) strcpy(&cbuff[2],".ima");
      (void) strcat(outfra,cbuff);
      (void) SCKWRC("IN_B",1,outfra,1,30,&unit);        /* save name... */
      (void) SCKRDI("IDIDEV",49,2,&actvals,qsize,&unit,&knul);
      if (qsize[0] <= 0) qsize[0] = DEFMEMSIZE;
      if (qsize[1] <= 0) qsize[1] = DEFMEMSIZE;
      }
   else
      {
      if (scale[0] < -1)
         qsize[0] = npix[0] * (-scale[0]);
      else if (scale[0] > 1)
         qsize[0] = npix[0] / scale[0];
      else
         qsize[0] = npix[0];
      if (scale[1] < -1)
         qsize[1] = npix[1] * (-scale[1]);
      else if (scale[1] > 1)
         qsize[1] = npix[1] / scale[1];
      else
         qsize[1] = npix[1];
      dsplfl = 0;
      }
   }
else
   dsplfl = 1;


/* determine map buffer space, and start to fill array KHELP */

khelp[0] = dattyp;
(void) SCKRDI("SIZIN",1,2,&actvals,mapsiz,&unit,&knul);
if (*mapsiz < *npix)		/* for image with long lines... */
   {
   *mapsiz = *npix;
   khelp[1] = *npix;
   }
else
   khelp[1] = MYMIN( *mapsiz, size );
khelp[2] = mapsiz[1];


/* no. of lines needed to average (work on) */

if (scale[2] != 0)
   khelp[1] = MYMAX( khelp[1],*npix * scale[1]);


/* determine size of "display_frame" + load the image into it */

if (dsplfl < 1)
   {
   int    outno, kcen[2], mpix[2];
   double end[2];
   float  ocuts[4];
   char   cunit[120];


   kcen[0] = icent[0];		/* determine size of output frame */
   if (icent[2] == -1) 
      kcen[1] = qsize[0]/2;
   else
      kcen[1] = icent[2];
   SIZER_C(qsize[0],npix[0],scale[0],scale[2],kcen,
           dazhld,dazhld+1,dazhld+2,dazhld+3);
   kcen[0] = icent[1];
   if (icent[3] == -1) 
      kcen[1] = qsize[1]/2;
   else
      kcen[1] = icent[3];
   SIZER_C(qsize[1],npix[1],scale[1],scale[2],kcen,
           dazhld+5,dazhld+6,dazhld+7,dazhld+8);

   mpix[0] = dazhld[0];
   mpix[1] = dazhld[5];
   size = mpix[0] * mpix[1];

   (void) SCFCRE(outfra,D_I1_FORMAT,F_O_MODE,F_IMA_TYPE,size,&outno);

   idum = 2;					/* will be 2-dim frame */
   (void) SCDWRI(outno,"NAXIS",&idum,1,1,&unit);
   (void) SCDWRI(outno,"NPIX",mpix,1,idum,&unit);
   (void) SCDWRD(outno,"STEP",step,1,idum,&unit);


   /* get original identifier */

   memset((void *)cunit,32,(size_t)72);
   (void) strncpy(cunit,"hardcopy of frame ",18);
   (void) SCDWRC(outno,"IDENT",1,cunit,1,72,&unit);
   (void) strcpy(cunit,"screen pixels   ");
   (void) strcpy(cunit+16, "screen pixels   ");
   (void) strcpy(cunit+32, "screen intens.  ");
   (void) SCDWRC(outno,"CUNIT",1,cunit,1,48, &unit);
   (void) SCDWRC(outno,"ROOT_FRAME",1,ourname,1,60,&unit);
   (void) SCDWRR(outno,"ROOT_CUTS",cuts,1,2,&unit);


   /* Write a 2-dimensional image into a frame serving as Virtual Display */

   WIMGB_C(imno,khelp,npix,cuts,scale,outno,dazhld);

   ocuts[0] = ocuts[2] = 0.;
   ocuts[1] = ocuts[3] = 255.;                         /* try highest value */
   (void) SCDWRR(outno,"LHCUTS",ocuts,1,4,&unit);


   /* new start & end values for the X-axis */

   *start += (dazhld[3]-1) * (*step);                     /* start values */
   if ( *scale < 0 )
      offs = *mpix / (- (*scale)) - 1;
   else
      { 
      if ( scale[2] == 0 )                              /* no averaging */
         offs = (*mpix-1) * (*scale);
      else
         offs = ((*mpix) * (*scale)) - 1;
      }
   *end = (*start) + (offs * (*step));			/* end value */


   /* new start + end values for the Y-axis */

   start[1] += (dazhld[8] - 1) * step[1];
   if ( scale[1] < 0 )
      offs = mpix[1]/ (- scale[1]) - 1;
   else
      {
      if ( scale[2] == 0 )                              /* no averaging */
         offs = (mpix[1] - 1) * scale[1];
      else
         offs = mpix[1] * scale[1] - 1;
      }
   end[1] = (start[1] + offs) * step[1];                     /* end value */

   (void) SCDWRD(outno,"START",start,1,2,&unit);
   (void) SCDWRD(outno,"END",end,1,2,&unit);
   }						/* The job is done!! */
else


/*
   We are really going to load into a display.
   Get split mode + addresses + memories per pixel as well as "active" channel
*/

   {
   int  kdum[2];
   char  *namepntr;

   (void) SCKRDI("DAZHOLD",1,11,&actvals,dazhld,&unit,&knul);

   if (icent[2] == -1) icent[2] = QMSZX/2;
   if (icent[3] == -1) icent[3] = QMSZY/2;
   
   if ( IDINUM < 11 ) 
      SPLCNT_C( splcx, splcy );               /* calculate split addresses */
   else
      {
      for (nr=0; nr<4; nr++)
         {
         for (mr=0; mr<5; mr++)
            {
            splcx[nr][mr] = 0;
            splcy[nr][mr] = 0;
            }
         }
      if (QIMCH == QOVCH) 
         SCETER(6,"DCLOAD: no image loading into overlay possible in X11");
      }

   khelp[9] = SOURCE;

   if (IDINUM == 11)
      {					/* check for compressed files */
      kdum[0] = 0;
      namepntr = ourname;
      idiserver = 1;
      idum = (int) strlen(ourname) - 1;
      if ((ourname[idum] == 'Z') && (ourname[idum-1] == '.'))
         {
         idum --;
         (void) strncpy(outfra,ourname,idum);
         outfra[idum] = '\0';
         namepntr = outfra;
         }
      else if ((ourname[idum] == 'z') && (ourname[idum-1] == 'g')
                                      && (ourname[idum-2] == '.'))
         {
         idum -=2;
         (void) strncpy(outfra,ourname,idum);
         outfra[idum] = '\0';
         namepntr = outfra;
         }
      else
         (void) SCFINF(ourname,5,kdum);

      if (kdum[0] > 0)			/* we have an extracted frame... */
         {
         (void) SCFNAME(imno,outfra,100);	/* get name of son */
         kdum[0] = 0;
         (void) SCPSET(F_DEL_PARM,kdum);	/* don't delete son */
         (void) SCFCLO(imno);			/* close father + son */
         namepntr = outfra;			/* point to name of son */
         }
      }
   else
      idiserver = 0;

   if (idiserver == 1)
      {
      khelp[2] = MYMAX(mapsiz[0],mapsiz[1]);         /* we can allocate! */
      stat = IIXWIM_C(QDSPNO,QIMCH,namepntr,khelp,LOADDR,
                      npix,icent,cuts,scale);
      if (stat != 0)				/* we had problems... */
         out_error(stat,ourname);
      (void) IIEGDB_C(QDSPNO,1,QIMCH,dzmemc,dzmemi,dzmemr);
      }
   else
      {
      WIMGA_C(QDSPNO,QIMCH,imno,khelp,LOADDR,npix,icent,cuts,scale);
      ZOOMX = ZOOMY = 1;			/* update IDIMEM data */
      SCALX = scale[0];
      SCALY = scale[1];
      }


   flag = FALSE;
   splmod = dazhld[2];
   if (splmod == 0)      
      {
      if (QMSZX > QDSZX)		/* take care of larger channels */
         {
         SCROLX = QMSZX/2 - QDSZX/2;
         flag = TRUE;
         } 
      else
         SCROLX = 0;

      if (QMSZY > QDSZY)      
         {
         SCROLY = QMSZY/2 + QDSZY/2;
         flag = TRUE;
         }
      else
         SCROLY = QMSZY - 1;
      }
   else
      {
      flag = TRUE;
      *npix = SSPX + NSX/2;
      SCROLX = *npix - splcx[QIMCH][splmod];
      npix[1] = SSPY + NSY/2;
      SCROLY = QMSZY - 1 + npix[1] - splcy[QIMCH][splmod];
      }
      
   if ( flag ) (void) Cdazscr(QDSPNO,QIMCH,&SCROLX,&SCROLY);


   /* update refscale only for image channels...  */

   if (QIMCH != QOVCH) Cdazvis(QDSPNO,QIMCH,1,dazhld[7]);


   /* store xsta,ysta,xend,yend,locut,hicut,min,max 
      in global variable dzmemr */

   if (khelp[9] != 2)		/* only if not OVERWRITE */
      {
      dzmemr[0] = (float) (*start + (SFPX-1) * *step);
      dzmemr[1] = (float) (start[1] + (SFPY-1) * step[1]);
      if ( *scale < 0)     
         offs = NSX / (- *scale) - 1;
      else
         { 
         if ( scale[2] == 0 )                    /* no averaging */
            offs = (NSX-1) * (*scale);
         else
            offs = NSX * (*scale) - 1;
         }
      dzmemr[2] = (float) (*start + (SFPX + offs - 1) * *step);

      if ( scale[1] < 0 )     
         offs = NSY / (- scale[1]) - 1;
      else
         { 
         if ( scale[2] == 0 )                    /* no averaging */
            offs = (NSY - 1) * scale[1];
         else
            offs = NSY * scale[1] - 1;
         }

      dzmemr[3] = (float) (start[1] + (SFPY + offs - 1) * step[1]);
      dzmemr[4] = cuts[0];
      dzmemr[5] = cuts[1];
      dzmemr[6] = cuts[2];
      dzmemr[7] = cuts[3];

      if (khelp[10] == 2)		/* update channel info */
         {
         int  chanl;

         chanl = QIMCH;
         for (nr=0; nr<kcount; nr++)
            {
            ZPLANE = khelp[11];
            DCPICH(chanl);
            Alphamem(chanl);
            chanl ++;
            khelp[11] ++;
            }
         }
      else
         {
         DCPICH(QIMCH);
         Alphamem(QIMCH);
         }
      }
   }
}

/*

*/

void out_error(stat,name)
int  stat;
char  *name;

{
char   otto[88];


if (stat == 41)
   {
   sprintf(otto,"XWIMG: overflow in output buffer...");
   SCETER(41,otto);
   }
else if (stat == 12)
   {
   sprintf(otto,"XWIMG: averaging only supported for real data!");
   SCETER(12,otto);
   }
else
   {
   sprintf(otto,"XWIMG: frame %s could not be accessed...",name);
   SCETER(11,otto);
   }
}
