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

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

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

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1991, 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.
 *---------------------------------------------------------------------
 */

#include "unmcopyright.h"        /* Copyright 1991 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: lvmapxfer.c
 >>>>
 >>>>      Program Name: vmapxfer
 >>>>
 >>>> Date Last Updated: Tue Mar  5 22:38:02 1991 
 >>>>
 >>>>          Routines: lvmapxfer - the library call for vmapxfer
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


/* -library_includes */
/* -library_includes_end */


/****************************************************************
*
* Routine Name: lvmapxfer - library call for vmapxfer
*
* Purpose:
*    
*    Transfers the Map from one image to another
*    
*    
* Input:
*    
*    *rec_img       The image that will receive the new map.
*    
*    *ext_img       The image that will have its map extracted.
*    
*    
* Output:
*    
*    *rec_img       The image that will contain a new map.
*    
*    
*
* Written By: Tom Sauer, Scott Wilson
*    
*    2/1/91    added support for BIT images. C.Gage
*    
*    
****************************************************************/


/* -library_def */
int
lvmapxfer(rec_img, ext_img)

struct xvimage *rec_img, *ext_img;
/* -library_def_end */

/* -library_code */
{
    char *program = "lvmapxfer";
    int dsize, dcount, msize, mcount, lsize, lcount;
    char *new_map;

    /*  Input image must be of type BIT, BYTE, SHORT, or LONG
     */
    if (  (! propertype(program, rec_img, VFF_TYP_BIT, FALSE))  &&
          (! propertype(program, rec_img, VFF_TYP_1_BYTE, FALSE))  &&
          (! propertype(program, rec_img, VFF_TYP_2_BYTE, FALSE))  &&
          (! propertype(program, rec_img, VFF_TYP_4_BYTE, FALSE)) )
     { 
        (void) fprintf(stderr,"%s: Receiving input image must be of\n", program);
        (void) fprintf(stderr,"Data Storage Type BIT, BYTE, SHORT or LONG\n");
        return(0);
     }

      /* only VFF_MS_ONEPERBAND and VFF_MS_SHARED map schemes are supported */

    if ( (! proper_map_scheme(program, ext_img, VFF_MS_ONEPERBAND, FALSE)) &&
         (! proper_map_scheme(program, ext_img, VFF_MS_SHARED, FALSE)))
    {
       (void) fprintf(stderr,"%s:  Extracting input image must", program);
       (void) fprintf(stderr,"have a Map Scheme of One-Per-Band or Shared\n");
       return(0);
    }

     /* if the extracting image has a map_scheme of ONE_PER_BAND then
      * the receiving image must have the same number of data bands
      * as the extracting image, unless the receiving image has a map_scheme
      * of NONE and the extracting image has only 1 band.
      */

    if ( (ext_img->map_scheme == VFF_MS_ONEPERBAND) && (rec_img->map_scheme != VFF_MS_NONE) ) 
    {
       if ( (! match_num_bands(program, ext_img, rec_img, FALSE)))
       {
           (void) fprintf(stderr,
                    "%s:  Extracting input image and Receiving input\n", program);
           (void) fprintf(stderr,
                    "image must have the same number of data bands,\n");
           (void) fprintf(stderr,
                    "since the map scheme of the Extracting input image is\n");
           (void) fprintf(stderr,
                    "One_Per_Band.\n");
           (void) fprintf(stderr,
                    "Number of bands for Extracting Input Image = %d\n",
                    ext_img->num_data_bands);
           (void) fprintf(stderr,
                    "Number of bands for Receiving Input Image = %d\n",
                    rec_img->num_data_bands);
           return(0);
       }
    }

        /* calculate the image, map size so that we can use bcopy to 
         * to copy the map to the receiving image.
         */

    if (! (imagesize(ext_img,&dsize,&dcount,&msize,&mcount,&lsize,&lcount)))
    {
        (void) fprintf(stderr,
           "%s: ERROR imagesize failed\n", program);
          return(0);
    }

        /* For BIT, BYTE, SHORT, and INT images,
         * make sure that the receiving image can map into
         * the new map. Check for overflow and underflow.
         */
    if (! (check_size(rec_img, ext_img, program)))
           return(0);

        /* get space for the new map */
    new_map = (char *) malloc(msize);
    if ( new_map == NULL ) 
    {
       (void) fprintf(stderr,
            "%s: ERROR insufficient  memory avaliable\n", program);
       return(0);
    }

        /* adjust the header accordingly */
    switch ( ext_img->map_scheme)
    {
       case VFF_MS_ONEPERBAND:

         /* NOTE:  if the extracting image is only one band with a
          *  map_scheme of ONE PER BAND, and the receiving image has
          *  a map_scheme of NONE, then set the receiving image to
          *  a map_scheme of SHARED.  Note that the receiving image
          *  MUST be multiband, otherwise the receiving image is
          *  set to ONE PER BAND.
          */

         if ( (ext_img->num_data_bands == 1) && (rec_img->num_data_bands > 1) && (rec_img->map_scheme == VFF_MS_NONE) )
         {
            bcopy(ext_img->maps, new_map, msize);
            rec_img->map_scheme = VFF_MS_SHARED;
            rec_img->map_row_size = ext_img->map_row_size;
            rec_img->map_col_size = ext_img->map_col_size;
            rec_img->map_storage_type = ext_img->map_storage_type;
            rec_img->map_subrow_size = ext_img->map_subrow_size;
            rec_img->color_space_model = ext_img->color_space_model;
         }
         else
         {
            bcopy(ext_img->maps, new_map, msize);
            rec_img->map_scheme = VFF_MS_ONEPERBAND;
            rec_img->map_row_size = ext_img->map_row_size;
            rec_img->map_col_size = ext_img->map_col_size;
            rec_img->map_storage_type = ext_img->map_storage_type;
            rec_img->map_subrow_size = ext_img->map_subrow_size;
            rec_img->color_space_model = ext_img->color_space_model;
         }
         break;
       case VFF_MS_SHARED:
         bcopy(ext_img->maps, new_map,  msize);

            /* note if the receiving image is only one band
             * and the map type of the extracting image is
             * SHARED, then set the map scheme of the receiving
             * image to ONE_PER_BAND since that is really what it is.
             */

         if (rec_img->num_data_bands == 1 ) 
           rec_img->map_scheme = VFF_MS_ONEPERBAND;
         else
           rec_img->map_scheme = VFF_MS_SHARED;
         rec_img->map_row_size = ext_img->map_row_size;
         rec_img->map_col_size = ext_img->map_col_size;
         rec_img->map_storage_type = ext_img->map_storage_type;
         rec_img->map_subrow_size = ext_img->map_subrow_size;
         rec_img->color_space_model = ext_img->color_space_model;
         break;
       default:
         (void)fprintf(stderr,"%s:  Extracting input image must", program);
         (void)fprintf(stderr,"have a Map Scheme of One-Per-Band or Shared\n");
         return(0);
         break;
    }

    if ( rec_img->maps != NULL) free(rec_img->maps);
    rec_img->maps = (char *)new_map;

    return(1);
}


/**************************************************************
*
* MODULE NAME:  check_size
*
*     PURPOSE:  Make sure the receiving image's  data min and max values 
*               are within the size of the map(s) from the extracting image.
*
*               This routine will prescan the data to get the min 
*               and max for each data band and make sure that the min 
*               and max can map into the map(s). If the min and max cannot 
*               map into the map the routine will give an error message 
*               and return.
*
*               Must check BYTE, SHORT or LONG.
*
*       INPUT: struct xvimage *rec_img -- the image that will receive the map
*              struct xvimage *ext_img -- the image that will extract the map
*
*      OUTPUT: Returns a 1 upon sucess and a 0 upon failure.
*               success implies that the receiving image's  data is within
*               bounds of the  extracting image's map size.
*
* CALLED FROM: lvmapxfer
*
* ROUTINES CALLED: None
*
**************************************************************/

int check_size(rec_img, ext_img, program)
    struct xvimage *rec_img;
    struct xvimage *ext_img;
    char *program;

{

    long min, max, i, j;
    unsigned char *cptr;
    short *sptr;
    long *lptr;


    switch ( rec_img->data_storage_type )
    {
       case VFF_TYP_BIT:
           if ( ext_img->map_col_size > 2 )
           {
              (void) fprintf(stderr,
                "%s: Extracting Image has too many entries in the\n",
                 program);
              (void) fprintf(stderr,
                "color map for the receiving image color map.\n");
              (void) fprintf(stderr,
                "Receiving image is BIT; can only have 2 entries in map\n");
           }
           break;
       case VFF_TYP_1_BYTE:
           cptr = (unsigned char *) rec_img->imagedata;
           for ( i = 0; i < rec_img->num_data_bands; i++)
           {
              min = max =  *cptr; 
              cptr++;
              for (j = 1 ; j < rec_img->row_size*rec_img->col_size; j++)
              {
                 if ( *cptr > max ) max = *cptr;
                 else 
                   if ( *cptr < min ) min = *cptr;
                 cptr++;
              }
              if ( max > ext_img->map_col_size)
              {
                 (void) fprintf(stderr,
                    "%s: Receiving Image data has data values too large\n",
                    program);
                 (void) fprintf(stderr,
                    "for Extracting Image's Map for band number %d\n",i);
                 (void) fprintf(stderr,
                    "Receiving Image maximun data value = %d\n",max);
                 (void) fprintf(stderr,
                    "Extracting Image maximum map value = %d\n",
                     ext_img->map_col_size);
                 return(0);
              }
              if ( min < 0 )
              {
                 (void) fprintf(stderr,
                    "%s: Receiving Image data has data values too small\n",
                    program);
                 (void) fprintf(stderr,
                    "for Extracting Images Map for band number %d\n",i);
                 (void) fprintf(stderr,
                    "Receiving Image minimum data value = %d\n",min);
                 (void) fprintf(stderr,
                    "Extracting Image maximun map value = 0\n");
                 return(0);
              }
           }
           break;
       case VFF_TYP_2_BYTE:
           sptr = (short *)rec_img->imagedata;
           for ( i = 0; i < rec_img->num_data_bands; i++)
           {
              max = min = *sptr;
              sptr++;
              for (j = 1 ; j < rec_img->row_size*rec_img->col_size; j++)
              {
                 if ( *sptr > max ) max = *sptr;
                 else
                    if ( *sptr < min ) min = *sptr;
                 sptr++;
              }
              if ( max > ext_img->map_col_size)
              {
                 (void) fprintf(stderr,
                    "%s: Receiving Image data has data values too large\n",
                    program);
                 (void) fprintf(stderr,
                    "for Extracting Images Map for band number %d\n",i);
                 (void) fprintf(stderr,
                    "Receiving Image maximum data value = %d\n",max);
                 (void) fprintf(stderr,
                    "Extracting Image maximum map value = %d\n",
                     ext_img->map_col_size);
                 return(0);
              }
              if ( min < 0 )
              {
                 (void) fprintf(stderr,
                    "%s: Receiving Image data has data values too small\n",
                    program);
                 (void) fprintf(stderr,
                    "for Extracting Images Map for band number %d\n",i);
                 (void) fprintf(stderr,
                    "Receiving Image minimum data value = %d\n",min);
                 (void) fprintf(stderr,
                    "Extracting Image maximum map value = 0\n");
                 return(0);
              }
           }
          break;
       case VFF_TYP_4_BYTE:
           lptr = (long *)rec_img->imagedata;
           for ( i = 0; i < rec_img->num_data_bands; i++)
           {
              max = min = *lptr;
              lptr++;
              for (j = 1 ; j < rec_img->row_size*rec_img->col_size; j++)
              {
                 if ( *lptr > max ) max = *lptr;
                 else
                   if ( *lptr < min ) min = *lptr;
                 lptr++;
              }
              if ( max > ext_img->map_col_size)
              {
                 (void) fprintf(stderr,
                    "%s: Receiving Image data has data values too large\n",
                    program);
                 (void) fprintf(stderr,
                    "for Extracting Images Map for band number %d\n",i);
                 (void) fprintf(stderr,
                    "Receiving Image maximum data value = %d\n",max);
                 (void) fprintf(stderr,
                    "Extracting Image maximum map value = %d\n",
                     ext_img->map_col_size);
                 return(0);
              }
              if ( min < 0 )
              {
                 (void) fprintf(stderr,
                    "%s: Receiving Image data has data values too small\n",
                    program);
                 (void) fprintf(stderr,
                    "for Extracting Images Map for band number %d\n",i);
                 (void) fprintf(stderr,
                    "Receiving Image minimum data value = %d\n",min);
                 (void) fprintf(stderr,
                    "Extracting Image maximum map value = 0\n");
                 return(0);
              }
           }
          break;
       default:
          (void) fprintf(stderr,
                    "%s: Invalid image data storage type. Image type must\n",
                    program);
          (void) fprintf(stderr, "be BYTE, SHORT or LONG\n");
          return(0);

          break;
   }
   return(1);
            
}
/* -library_code_end */
