 /*
  * Khoros: $Id: dunloadvect.c,v 1.1 1991/05/10 15:41:35 khoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: dunloadvect.c,v 1.1 1991/05/10 15:41:35 khoros Exp $";
#endif

 /*
  * $Log: dunloadvect.c,v $
 * Revision 1.1  1991/05/10  15:41:35  khoros
 * Initial revision
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1990, University of New Mexico.  All rights reserved.

 * Permission to copy and modify this software and its documen-
 * tation only for internal use in your organization is hereby
 * granted, provided that this notice is retained thereon and
 * on all copies.  UNM makes no representations as too the sui-
 * tability and operability of this software for any purpose.
 * It is provided "as is" without express or implied warranty.
 * 
 * UNM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
 * NESS.  IN NO EVENT SHALL UNM BE LIABLE FOR ANY SPECIAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY OTHER DAMAGES WHAT-
 * SOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PER-
 * FORMANCE OF THIS SOFTWARE.
 * 
 * No other rights, including for example, the right to redis-
 * tribute this software and its documentation or the right to
 * prepare derivative works, are granted unless specifically
 * provided in a separate license agreement.
 *---------------------------------------------------------------------
 */

/*
#
# FILE NAME:	dunloadvector.c
# 
# AUTHORS: 	Donna Koechner
#
# 
# DATE:		2/9/90
# 
# DESCRIPTION:	Utility for unloading a vector array back into image format.
#	
# MODIFICATIONS: Mon Feb 25 1991 - added double and double complex
#                capabilities - Donna Koechner
#		 Tue Mar 13 1991 - added explicit error checking
#		 for cases when row_size and col_size in image are bogus.
#		 - Jeremy Worley
#			
*/

#include "unmcopyright.h"	 
#include "vinclude.h"	 	

/**************************************************************
*
* MODULE NAME:	dunload_vector
*
*     PURPOSE: 	Dsp1 utility that takes a 2-D array of vectorized data 
*              	and rearanges the data so that the data is stored in 
*		an image format.
*
*		dunload_vector should be called at the end of any dsp1 
*		routine that calls dload_vector.  This routine loads 
*		the vector array back into (multiband) image format.  
*		Again, dunload_vector arranges the output data according to 
*		the process_dir variable (DSP_VECTOR or DSP_BAND) passed in.
*
*               dunload_vector does the following:
*               1.  Loads the data into image format (done differently
*                   for vector vs. band processing directions)
*                   You pass in a pointer to the xvimage structure
*                   and dunload_vector assigns the data to a 1-d
*		    data array, and then assigns this array to 
*		    image->imagedata.
*		2.  If process direction = DSP_VECTOR, resets 
*		    image->num_data_bands to dimension, and calls
*		    unload_vector.
*		3.  If process direction is DSP_BAND, resets image->col_size
*		    and/or image->row_size if dimension of data has been
*		    altered.  (ie. dimension != rows*cols).  New row and
*		    col sizes are set according to the following rules.
*		    (dim already divided by 2 if data is complex.)
*			if      num_rows = 1, num_cols = dim/num_rows
*			else if num_cols = 1, num_rows = dim/num_cols
*			else if dimension divisible by num_rows, 
*		    			      num_cols = dim/num_rows
*			else if dimension divisible by num_cols, 
*		    			      num_rows = dim/num_cols
*			else	num_cols =1, num_rows = dimension.
*
*		4.  Sets image->data_storage_type to type passed in.
*
*		DSP_VECTOR Process Direction:
*      	        If the parameter process_dir = DSP_VECTOR (0), each 
*		vector represents a pixel and the dimension of the
*      	        vector represents the number of data bands for the image.
*      	        So the mth element of vector t represents pixel t in
*      	        the mth data band.  Therefore, the image is built by 
*      	        filling row by row from the linear vector data.
*
*		DSP_BAND Process Direction:
*		If the parameter process_dir = DSP_BAND (1), each vector
*		represents a band and the dimension of the vectors
*		is given by rows*cols.  In this case, the image is
*		built by assigning each vector to a band in the 
*		output image.
*
*       INPUT:  char **input_vectors - a pointer to the 2-D vectorized data
*
*       	struct xvimage *image - a pointer to the image to which the
*                                       unvectorized data is assigned.
*               
*               type - image data storage type
*
*               num_vects - total number of vectors
*
*               dimension - vector dimension
*
*		process_dir (int) - a flag set to 0 the data is 
*				    vectorized down the bands, and
*				    set to 1 if each vector is a band 
*
*      OUTPUT: 	struct xvimage *image - a pointer to the image to which the
*                                       unvectorized data is assigned.
*
* CALLED FROM:
*
* ROUTINES CALLED: unload_vector
*
**************************************************************/


int dunload_vector(input_vectors, image, type, num_vects, 
		   dimension, process_dir)
char 		**input_vectors;
struct xvimage 	*image;
int 		num_vects, dimension, process_dir;
unsigned long   type;

{
  int		border,			/* image border (set to 0) */
		nbands,			/* number of data bands */
		*idata,			/* integer data array */
		**i_vects,
		i,j,indx;

  float		*fdata,			/* float data array */
		**f_vects;

  double	*ddata,			/* float data array */
		**d_vects;

  short		**s_vects,
		*sdata;			/* short int data array */

  char		*cdata,			/* byte data array */
		*unload_vector(),
  		*prog = "dunload_vector: ";


 /* 
  * If the process direction is vectors, set up the number of data bands 
  * to be dimension.  Otherwise, (case of band processing 
  * direction or only one band of data in the original file) set number 
  * of bands equal to the num_vects.
  */

  if ( (process_dir == DSP_VECTOR) && (image->num_data_bands != 1) )
  {
    nbands = dimension;
  }
  else		/* band processing or only one band of data */
  {
    nbands = num_vects;
  }

  if (nbands < 1)
  {
    (void)fprintf(stderr,"dunload_vector: invalid dimension -> %d\n",dimension);
    return(0);
  }

  if(image->row_size < 1 || image->col_size < 1){
     (void)fprintf(stderr,"dunload_vector: invalid image dimension (%d,%d)\n",
           image->row_size,image->col_size);
     return(0);
  }


 /*
  * If process direction is vectors, call unload_vector.
  */
  if ( (process_dir == DSP_VECTOR) && (image->num_data_bands != 1) )
  {
    if ( (image->row_size * image->col_size) != num_vects)
    {
      (void)fprintf(stderr,"%s: number of rows and columns ", prog);
      (void)fprintf(stderr,"(%d, %d) ",image->col_size, image->row_size);
      (void)fprintf(stderr,"does not agree with num_vects (%d)\n",num_vects);
      return(0);
    }

    free ((char*)image->imagedata);
    border = 0;
    if ( (image->imagedata = unload_vector( (char **)input_vectors, border, 
	  type, num_vects, dimension, image->col_size, image->row_size))  
	  == NULL) 
    {
      (void) fprintf(stderr,"dunload_vector: unload_vector failed\n");
      return(0);
    }
    image->num_data_bands = nbands;
  }

  else		/* DSP_BAND process direction or only on band of data */
  {

   /*
    * If working on bands instead of vectors, may have to rearrange the
    * output data if dimension of data has changed.
    */

    if ( (image->row_size * image->col_size) != dimension )
    {

      /* If input single row, output single row */
      if (image->col_size == 1)	
      {
          image->row_size = dimension;
      }
  
      /* If input single column, then output single column */
      else if (image->row_size == 1)	
      {					 
        image->col_size = dimension;
      }

      /* if divisible by number of rows, increase col size */
      else if ((dimension % (image->col_size)) == 0)	
      {						
        image->row_size = dimension/image->col_size;
      }

      /* if divisible by number of columns, increase row size */
      else if ((dimension % image->row_size) == 0)	
      { 					
        image->col_size = dimension/image->row_size;
      }
  
      /* last resort, if nothing else works, output single row */
      else	
      {
        image->col_size = dimension;
        image->row_size = 1;
      }
    }

    switch(type)
    {
      case VFF_TYP_BIT:
           (void)fprintf(stderr,"%sCannot work on BIT data type\n",prog);
           return(0);

      case VFF_TYP_1_BYTE:
          /* Allocate new array. */
           if( (cdata = (malloc((unsigned int) dimension * nbands *
			           sizeof(char) ))) == NULL)
           {
             (void)fprintf(stderr,"%s char memory allocation failed\n",prog);
             return(0);
           }

           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<dimension; j++)
             {
               cdata[indx] = input_vectors[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = cdata;
           break;

      case VFF_TYP_2_BYTE:
          /* Allocate new array. */
           if( (sdata = (short *) (malloc((unsigned int) dimension * nbands *
			           sizeof(short) ))) == NULL)
           {
             (void)fprintf(stderr,"%s short memory allocation failed\n",prog);
             return(0);
           }
       
	   s_vects = (short **) input_vectors;
           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<dimension; j++)
             {
               sdata[indx] = s_vects[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = (char *)sdata;
           break;

      case VFF_TYP_4_BYTE:
          /* Allocate new array. */
           if( (idata = (int *) (malloc((unsigned int) dimension * nbands *
			           sizeof(int) ))) == NULL)
           {
             (void)fprintf(stderr,"%s int memory allocation failed\n",prog);
             return(0);
           }
       
	   i_vects = (int **) input_vectors;
           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<dimension; j++)
             {
               idata[indx] = i_vects[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = (char *)idata;
           break;

      case VFF_TYP_FLOAT:
          /* Allocate new array. */
           if( (fdata = (float *) (malloc((unsigned int) dimension * nbands *
			           sizeof(float) ))) == NULL)
           {
             (void)fprintf(stderr,"%s float memory allocation failed\n",prog);
             return(0);
           }

	   f_vects = (float **) input_vectors;
           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<dimension; j++)
             {
               fdata[indx] = f_vects[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = (char *)fdata;
           break;

      case VFF_TYP_COMPLEX:
          /* Allocate new array. */
           if( (fdata = (float *) (malloc((unsigned int) dimension * nbands *
			           2 * sizeof(float) ))) == NULL)
           {
             (void)fprintf(stderr,"%s complex allocation failed\n",prog);
             return(0);
           }
       
	   f_vects = (float **) input_vectors;
           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<(dimension*2); j++)
             {
               fdata[indx] = f_vects[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = (char *)fdata;
           break;

      case VFF_TYP_DOUBLE:
          /* Allocate new array. */
           if( (ddata = (double *) (malloc((unsigned int) dimension * nbands *
			           sizeof(double) ))) == NULL)
           {
             (void)fprintf(stderr,"%s double memory allocation failed\n",prog);
             return(0);
           }

	   d_vects = (double **) input_vectors;
           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<dimension; j++)
             {
               ddata[indx] = d_vects[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = (char *)ddata;
           break;

      case VFF_TYP_DCOMPLEX:
          /* Allocate new array. */
           if( (ddata = (double *) (malloc((unsigned int) dimension * nbands *
			           2 * sizeof(double) ))) == NULL)
           {
             (void)fprintf(stderr,"%s dcomplex allocation failed\n",prog);
             return(0);
           }
       
	   d_vects = (double **) input_vectors;
           indx = 0;
           for (i=0; i<nbands; i++)
           {
             for (j=0; j<(dimension*2); j++)
             {
               ddata[indx] = d_vects[i][j];
	       indx ++;
             }
           }
	   free((char*)image->imagedata);
           image->imagedata = (char *)ddata;
           break;

      default:
           (void)fprintf(stderr,"%sInvalid image data storage type\n",prog);
           (void)fprintf(stderr,"Can only convert type BYTE, SHORT, INTEGER,");
           (void)fprintf(stderr,"Float\nand Complex\n");
           return(0);

    }  /* end of case statement */
  }

  image->data_storage_type = type;
  return(1);
} 
