/* @(#)packer.c	19.1 (ESO-DMD) 02/25/03 14:00:00 */
/*===========================================================================
  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
===========================================================================*/

/* +++++++++++++++++++++++++  packer.c  +++++++++++++++++++++++++++++++++++++
.COPYRIGHT   (c) 1994 European Southern Observatory
.IDENTIFIER  Module PACKER
.LANGUAGE    C
.AUTHOR      K. Banse                           ESO - Garching
.KEYWORDS    Image display, Byte packing
.COMMENTS    holds I1PACK, K1PACK, I1UNPA, F1UNPA,
.ENVIRONment MIDAS
             #include <midas_def.h>      Prototypes for MIDAS interfaces

.VERSION   [1.00]  880126:  adapted from PACKER.FOR (RvH)

 011005		last modif

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

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

#define  _POSIX_SOURCE 1

#include <midas_def.h>

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTIFIER  I1PACK_C
.PURPOSE     pack a real array (from an image) into 1 byte for
             the image display device 
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    I1PACK_C( pntr, aux, faux, cdata, outaux )

  input:
         char  *cpntr		image data given with a character pointer
         int   *aux		auxiliary info array:
                                  [0] data type flag (as D_xx_FORMAT)
                                  [1] offset in input data
			          [2] size of above
			          [3] scaling factor
			          [4] scaling_flag, = 0 (no), = 1 (yes scale)
			          [5] spare
         float *faux		auxiliary real info array:
			          factor to map into [0,outmax]
			          artificial minimum and maximum of image data
         int   *outaux		max. output value (<= 255)
                                offset in pixel array
  output:
         unsigned char *cdata	scaled line with pixel in byte

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

void I1PACK_C(pntr,aux,faux,cdata,outaux)
char  *pntr;
unsigned char *cdata;
int   *aux, *outaux;
float *faux;

{	
register float myfact, turbo;

int    mscal, ndim;
register int nr;

unsigned char cmax;



ndim   = aux[2];			/* init */
mscal  = aux[3];
cmax   = (unsigned char) outaux[0];
cdata += outaux[1];
myfact = faux[0];
turbo = 0.5 - (myfact * faux[1]);		/* faux[1] = cuts[0] */


/* branch according to data type */

switch( aux[0] )
   { 
   case D_R4_FORMAT:
      {
      register float  flow, fhi, *rbuff, rval;

      rbuff = (float *) pntr;
      flow  = faux[1];
      fhi   = faux[2];

      rbuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         rval = *rbuff;
         if (rval <= flow)
            *cdata++ = 0;
         else if (rval >= fhi)
            *cdata++ = cmax;
         else
            *cdata++ = (unsigned char) ((rval * myfact) + turbo);
         rbuff += mscal;
         }
      }
      break;

   case D_I4_FORMAT:
      {
      register int   ilow, ihi, *ibuff, ival;

      ibuff = (int *) pntr;
      ilow  = (int) faux[1];
      ihi   = (int) faux[2];

      ibuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         ival = *ibuff;
         if (ival <= ilow)
            *cdata++ = 0;
         else if (ival >= ihi)
            *cdata++ = cmax;
         else
            *cdata++ = (unsigned char) ((ival * myfact) + turbo);
         ibuff += mscal;
         }
      }
      break;

   case D_I2_FORMAT:
      {
      short int  jlow, jhi, *jbuff, jval;
	
      jbuff = (short int *) pntr;
      jlow  = (short int) faux[1];
      jhi   = (short int) faux[2];

      jbuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         jval = *jbuff;
         if (jval <= jlow)
            *cdata++ = 0;
         else if (jval >= jhi)
            *cdata++ = cmax;
         else
            *cdata++ = (unsigned char) ((jval * myfact) + turbo);
         jbuff += mscal;
         }
      }
      break;

   case D_I1_FORMAT:
      {
      unsigned char  clow, chi, *cbuff, cval;
	
      cbuff = (unsigned char *) pntr;
      cbuff += aux[1];
          
      if ( aux[4] == 0 )  			/* just copy data  */
         {
         for (nr=0; nr<ndim; nr++)
            {
            *cdata++ = *cbuff;
            cbuff += mscal;
            }
         }
      else					/* really scale the stuff  */
         {
         clow  = (unsigned char) faux[1];
         chi   = (unsigned char) faux[2];

         for (nr=0; nr<ndim; nr++)
            {
            cval = *cbuff;
            if (cval <= clow)
               *cdata++ = 0;
            else if (cval >= chi)
               *cdata++ = cmax;
            else
               *cdata++ = (unsigned char) ((cval * myfact) + turbo);
            cbuff += mscal;
            }
         }
      }    
      break;

   case D_UI2_FORMAT:
      {
      unsigned short int  julow, juhi, *jubuff, juval;
	
      jubuff = (unsigned short int *) pntr;
      julow  = (unsigned short int) faux[1];
      juhi   = (unsigned short int) faux[2];

      jubuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         juval = *jubuff;
         if (juval <= julow)
            *cdata++ = 0;
         else if (juval >= juhi)
            *cdata++ = cmax;
         else
            *cdata++ = (unsigned char) ((juval * myfact) + turbo);
         jubuff += mscal;
         }
      }
      break;

   default:
      SCETER( 1, "FATAL error in I1PACK: unknown data type" );
   }
}

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTIFIER  K1PACK_C
.ALGORITHM   straight forward
.PURPOSE     pack a real array (from an image) into 1 byte for
             the image display device and zoom up (replicate the pixels)
.INPUT/OUTPUT
  call as    void K1PACK_C( pntr, aux, faux, cdata, outaux )

  input:
         char  *cpntr           image data given with a character pointer
         int   *aux             auxiliary info array:
                                  data type flag (as D_xx_FORMAT)
                                  offset in input data
                                  size of above
                                  scaling factor
                                  scaling_flag, = 0 (no), = 1 (yes scale)
				  spare
         float *faux            auxiliary real info array:
                                  factor to map into [0,outmax]
                                  artificial minimum and maximum of image data
         int   *outaux          max. output value (<= 255)
                                offset in pixel array
  output:
         unsigned char *cdata   scaled line with pixel in byte

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

void K1PACK_C( cpntr, aux, faux, cdata, outaux )
char  *cpntr;
unsigned char *cdata;
int   *aux, *outaux;
float *faux;

{	
int    mscal, ndim;
register int  nr, kk;

unsigned char cmax;
register unsigned char value;

register float   myfact, turbo;



ndim   = aux[2];			/* init */
mscal  = aux[3];
cmax   = (unsigned char) outaux[0];
cdata += outaux[1];
myfact = faux[0];
turbo = 0.5 - (myfact * faux[1]);		/* faux[1] = cuts[0] */


/* branch according to data type */

switch( aux[0] )
   {
   case D_R4_FORMAT:
      {
      float   flow, fhi, *rbuff, rval;
   
      rbuff = (float *) cpntr;
      flow = faux[1];
      fhi  = faux[2];

      rbuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         rval = *rbuff;
         if (rval <= flow)
            value = 0;
         else if (rval >= fhi)
            value = cmax;
         else
            value = (unsigned char) ((rval*myfact) + turbo);

         for (kk=0; kk<mscal; kk++) *cdata++ = value; 
         rbuff++;
         }
      break;
      }

   case D_I4_FORMAT:
      {
      int   ilow, ihi, *ibuff, ival;

      ibuff = (int *) cpntr;
      ilow  = (int) faux[1];
      ihi   = (int) faux[2];

      ibuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         ival = *ibuff;
         if (ival <= ilow) 
            value = 0;
         else if (ival >= ihi) 
            value = cmax;
         else
            value = (unsigned char) ((ival*myfact) + turbo);

         for (kk=0; kk<mscal; kk++) *cdata++ = value; 
         ibuff++;
         }
      }   
      break;

   case D_I2_FORMAT:
      {
      short int  jlow, jhi, *jbuff, jval;

      jbuff = (short int *) cpntr;
      jlow  = (short int) faux[1];
      jhi   = (short int) faux[2];

      jbuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         jval = *jbuff;
         if (jval <= jlow) 
            value = 0;
         else if (jval >= jhi) 
            value = cmax;
         else
            value = (unsigned char) ((jval*myfact) + turbo);

         for (kk=0; kk<mscal; kk++) *cdata++ = value; 
         jbuff++;
         }
      }
      break;

   case D_I1_FORMAT:
      {
      unsigned char clow, chi, cval, *cbuff;

      cbuff = (unsigned char *) cpntr;
      cbuff += aux[1];

      if (aux[4] == 0)  			/* just copy data  */
         {
         for (nr=0; nr<ndim; nr++)
            { 
            cval = *cbuff;
            for (kk=0; kk<mscal; kk++) *cdata++ = cval;
            cbuff ++;
            }
         }
      else					/* really scale the stuff  */
         {
         clow  = (unsigned char) faux[1];
         chi   = (unsigned char) faux[2];

         for (nr=0; nr<ndim; nr++)
            { 
            cval = *cbuff;
            if (cval >= chi) 
               value = cmax;
            else if (cval <= clow)
               value = 0;
            else
               value = (unsigned char) ((cval*myfact) + turbo);
   
            for (kk=0; kk<mscal; kk++) *cdata++ = value; 
            cbuff++;
            }
         }
      }
      break;

   case D_UI2_FORMAT:
      {
      unsigned short int  julow, juhi, *jubuff, juval;

      jubuff = (unsigned short int *) cpntr;
      julow  = (unsigned short int) faux[1];
      juhi   = (unsigned short int) faux[2];

      jubuff += aux[1];
      for (nr=0; nr<ndim; nr++)
         {
         juval = *jubuff;
         if (juval <= julow)
            value = 0;
         else if (juval >= juhi)
            value = cmax;
         else
            value = (unsigned char) ((juval*myfact) + turbo);

         for (kk=0; kk<mscal; kk++) *cdata++ = value; 
         jubuff++;
         }
      }
      break;

   default:
      SCETER( 1, "FATAL error in K1PACK: unknown data type" );
   }
}

/*

*/

/*++++++++++++++++++++++++++++++
.IDENTIFIER  I1UNPA_C
.PURPOSE     unpack a byte array (from the image display) and
             store in integer  array
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    I1UNPA( cdata, ndim, ibuf )

  input:
         unsigned char *cdata;  pixel array in bytes
         int  ndim              size of above
  output:
         int  *ibuf             integer image data

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

void I1UNPA_C( cdata, ndim, ibuf )
unsigned char *cdata;
int  ndim, *ibuf;

{
register int ii = 0;

while (ii++ < ndim) *ibuf++ = (int) *cdata++;
}




/*++++++++++++++++++++++++++++++
.IDENTIFIER  F1UNPA_C
.PURPOSE     unpack a byte array (from the image display) and
             store in real array
.ALGORITHM   straight forward
.INPUT/OUTPUT
  call as    F1UNPA_C( cdata, ndim, buf )

  input:
         unsigned char *cdata;  pixel array in bytes
         int   ndim             size of above
  output:
         float *fbuf            real image data

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

void F1UNPA_C( cdata, ndim, fbuf )
unsigned char *cdata;
int   ndim;
float *fbuf;

{
register int ii = 0;

while (ii++ < ndim) *fbuf++ = (float) *cdata++;
}

