 /*
  * Khoros: $Id: lvmos2band.c,v 1.2 1992/03/20 23:06:50 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: lvmos2band.c,v 1.2 1992/03/20 23:06:50 dkhoros Exp $";
#endif

 /*
  * $Log: lvmos2band.c,v $
 * Revision 1.2  1992/03/20  23:06:50  dkhoros
 * VirtualPatch5
 *
  */

/*
 *----------------------------------------------------------------------
 *
 * Copyright 1992, 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 to 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 1992 by UNM */

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>  <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 >>>>
 >>>>         File Name: lvmos2band.c
 >>>>
 >>>>      Program Name: vmos2band
 >>>>
 >>>> Date Last Updated: Tue Mar 17 09:02:14 1992 
 >>>>
 >>>>          Routines: lvmos2band - the library call for vmos2band
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


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


/****************************************************************
*
* Routine Name: lvmos2band - library call for vmos2band
*
* Purpose:
*    
*    Converts a mosaic input image to an output  image  in  which
*    each  subimage of the input mosaic constitutes a band of the
*    output image.
*    
*    

* Input:
*    
*    image          pointer to input xvimage structure
*    
*    sub_rows       num rows per subimage (including borders)
*    
*    sub_cols       num cols per subimage (including borders)
*    
*    sub_border     subimage border (inner border) size in pixels
*    
*    sub_x_off      col index through subimages (1 img per index)
*    
*    sub_y_off      row index through subimages (1 img per index)
*    
*    sub_skip       skip value between subimages to be banded
*    
*    num_flag       if set, user specifies num subimages banded
*    
*    num_subs       number of subimages that will be banded
*    
*    

* Output:
*    
*    img1           output banded image
*    
*    

*
* Written By: Donna Koechner
*    
*    

****************************************************************/


/* -library_def */
int
lvmos2band(image, img1, sub_rows, sub_cols, sub_border, img_border, sub_x_off, sub_y_off, sub_skip, num_flag, num_subs)

struct xvimage  *image,     /* imput mosaic image */
                **img1;     /*  multiband output image */

int             sub_rows,   /* num rows per subimage (including borders) */
                sub_cols,   /* num cols per subimage (including borders) */
                sub_border, /* subimage border (inner border) size in pixels */
                img_border, /* overall image border (outer) size in pixels */
                sub_x_off,  /* col index through subimages (1 img per index) */
                sub_y_off,  /* row index through subimages (1 img per index) */
                sub_skip,   /* skip value between subimages to be banded */
                num_flag,   /* if set, user specifies num subimages banded */
                num_subs;   /* number of subimages that will be banded */
/* -library_def_end */

/* -library_code */
{

  int           sub_col_cnt,    /* num subimages in horizontal direction */
                sub_row_cnt,    /* num of subimages in vertical direction */
                total_num_subs, /* total number subimages in mosaic */
                first_sub_loc,  /* 1st subimage position - from -x, -y */
                num_subs_left,  /* total - first subimage */
                num_subs_avail, /* number of subimage available after x,y,s */
                skip,           /* sub_skip + 1  -- used as an index */
                skew,           /* skew at beginning of rows due to skipping */
                band_cnt,
                *i1, *i2,
                i,j,m,n;

  short         *s1, *s2;
  unsigned char *c1, *c2;
  float         *f1, *f2;

  struct xvimage *img2, *createimage();

  unsigned long height,         /* subimage height (minus subimage border) */
                width,          /* subimage width (minus subimage border) */
                x_off,          /* column offset into mosaic image */
                y_off;          /* row offset into mosaic image */
 /*
  * Verify that given sub border sizes are within bounds
  */
  if (2*sub_border >= sub_cols || 2*sub_border >= sub_rows)
  {
    (void)fprintf(stderr,"lvmos2band: sub image border size too large:\n");
    (void)fprintf(stderr,"sub image border size = %d\n",sub_border);
    return(0);
  }


 /*
  * Verify that given border sizes and subimage sizes agree with input 
  * mosaic image size.
  */
  if (((image->row_size - 2*img_border)%sub_cols) != 0 )
  {
    (void)fprintf(stderr,"lvmos2band: Incorrect horizontal dimensions:\n");
    (void)fprintf(stderr,"number of cols in image = %d\n",image->row_size);
    (void)fprintf(stderr,"cols per subimage = %d\n",sub_cols);
    (void)fprintf(stderr,"image border size = %d\n\n",img_border);
   return(0);
  }
  sub_col_cnt = (image->row_size - 2*img_border)/sub_cols;

  if (((image->col_size - 2*img_border)%sub_rows) != 0 )
  {
    (void)fprintf(stderr,"lvmos2band: Incorrect vertical dimensions:\n");
    (void)fprintf(stderr,"number of rows in image = %d\n",image->col_size);
    (void)fprintf(stderr,"rows per subimage = %d\n",sub_rows);
    (void)fprintf(stderr,"image border size = %d\n\n",img_border);
    return(0);
  }
  sub_row_cnt = (image->col_size - 2*img_border)/sub_rows;


 /*
  * Verify that horizontal and vertical subimage offset values are valid.
  */
  if ( (sub_x_off < 0) || (sub_x_off >= sub_col_cnt) )
  {
    (void)fprintf(stderr,"lvmos2band: invalid horizontal subimage offset:\n");
    (void)fprintf(stderr,"offset = %d, number subimages in ", sub_x_off);
    (void)fprintf(stderr,"horizontal direction = %d\n", sub_col_cnt);
    (void)fprintf(stderr,"Max offset is number subimages - 1\n\n");
    return(0);
  }
 
  if ( (sub_y_off < 0) || (sub_y_off >= sub_row_cnt) )
  {
    (void)fprintf(stderr,"lvmos2band: invalid vertical subimage offset:\n");
    (void)fprintf(stderr,"offset = %d, number subimages in ", sub_y_off);
    (void)fprintf(stderr,"vertical direction = %d\n", sub_row_cnt);
    (void)fprintf(stderr,"Max offset is number subimages - 1\n\n");
    return(0);
  }


 /*
  * Calculate the number of subimages available to be put into bands.
  * If number of subimages flag is set, get the value passed in.  
  */
  total_num_subs = sub_row_cnt * sub_col_cnt;
  first_sub_loc = (sub_col_cnt * sub_y_off) + sub_x_off;
  num_subs_left = total_num_subs - first_sub_loc;
  num_subs_avail = ( (num_subs_left - 1)/(sub_skip +1) ) + 1;
  if (!num_flag)
  {
    num_subs = num_subs_avail;
  }
  

 /* 
  * If more subimages were specified to be banded than are available, 
  * return.
  */
  if (num_subs > num_subs_avail)
  {
    (void)fprintf(stderr,
                  "lvmos2band: Number subimages to band option too large.\n");
    return(0);
  }

  if ((width = sub_cols - 2*sub_border) < 1)
  {
    (void)fprintf(stderr,
                  "lvmos2band: subimage borders larger than subimage cols\n");
    return(0);
  }

  if ((height = sub_rows - 2*sub_border) < 1)
  {
    (void)fprintf(stderr,
                  "lvmos2band: subimage borders larger than subimage rows\n");
    return(0);
  }

 /*
  * Create the resulting image
  */
  img2 = createimage(height,                    /* number rows per subimage */
                     width,                     /* number cols per subimage */
                     image->data_storage_type,
                     1,                         /* number of images */
                     num_subs,                  /* number of data bands */
                     "created by vmos2band",    /* comment */
                     image->map_row_size,
                     image->map_col_size,
                     image->map_scheme,
                     image->map_storage_type,
                     VFF_LOC_IMPLICIT,
                     0);                        /* location dimension */

                                
  if (img2 == NULL)
  {
    (void)fprintf(stderr,"lvmos2vect: createimage failed\n");
    return(0);
  }

  if (img2->imagedata == NULL)
  {
    (void)fprintf(stderr,"lvmos2band: Pointer to img2->imagedata invalid.\n");
    return(0);
  }

 /* 
  * Change necessary fields in output image.
  * Startx and starty, which specify location of subimage in original
  * image, is set to the first subimage extracted.
  */
  img2->startx = img_border + (sub_x_off * sub_cols) + sub_border;
  img2->starty = img_border + (sub_y_off * sub_rows) + sub_border;
  img2->pixsizx = image->pixsizx;
  img2->pixsizy = image->pixsizy;
  img2->data_encode_scheme = image->data_encode_scheme;
  img2->map_enable = image->map_enable;
  img2->color_space_model = image->color_space_model;


 /* 
  * Copy map data from image to img2 
  */
  if ( ! copymapdata(image, &img2, FALSE) ) 
  {
    (void) fprintf(stderr,"lvmos2band: Could not copy map data!\n");
    return(0);
  }


 /*
  * Initialize common loop variable.
  */
  skew = 0;
  skip = sub_skip + 1;
  band_cnt = 0;
  

 /*
  * Copy specified subimages from input image to bands in output image.
  */
  switch (image->data_storage_type)
  {
    case VFF_TYP_BIT:
         (void)fprintf(stderr,"lvmos2band: No BIT images allowed!\n");
         return(0);
         break;

    case VFF_TYP_1_BYTE:
         
         c1 = (unsigned char *)(image->imagedata);
         c2 = (unsigned char *)(img2->imagedata);

        /*
         * First extract subimages in the partial(?) row defined by 
         * sub_x_off and sub_y_off
         */
         for ( j=sub_x_off ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip )
         {
           x_off = img_border + ( j * sub_cols ) + sub_border;
           y_off = img_border + ( sub_y_off * sub_rows ) + sub_border;
  
           for (m=0; m<height; m++)
           {
             for (n=0; n<width; n++)
             {
               c2[(band_cnt * height * width ) + m * width + n] 
                        = c1[(y_off+m)*image->row_size+(x_off+n)];
             }
           }
  
           band_cnt ++;
    
           if ( (sub_col_cnt - j) <= skip )
           {
             skew = skip - (sub_col_cnt - j);
           }
         } 
  
        /* 
         * Extract the rest of the (complete) rows.
         */
  
         for ( i=(sub_y_off+1) ; (i<sub_row_cnt) && (band_cnt<num_subs) ; i++ )
         {
           for ( j=skew ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip ) 
           {
             x_off = img_border + ( j * sub_cols ) + sub_border;
             y_off = img_border + ( i * sub_rows ) + sub_border;
  
             for (m=0; m<height; m++)
             {
               for (n=0; n<width; n++)
               {
                 c2[(band_cnt * height * width ) + m * width + n] 
                          = c1[(y_off+m)*image->row_size+(x_off+n)];
               }
             }
  
             band_cnt ++;
      
             if ( (sub_col_cnt - j) <= skip )
             {
               skew = skip - (sub_col_cnt - j);
             }
           }  /* end of loop through subimage columns */
         }  /* end of loop through subimage rows */
         break; /* end case VFF_TYP_1_BYTE */


    case VFF_TYP_2_BYTE:
         
         s1 = (short *)(image->imagedata);
         s2 = (short *)(img2->imagedata);

        /*
         * First extract subimages in the partial(?) row defined by 
         * sub_x_off and sub_y_off
         */
         for ( j=sub_x_off ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip )
         {
           x_off = img_border + ( j * sub_cols ) + sub_border;
           y_off = img_border + ( sub_y_off * sub_rows ) + sub_border;
  
           for (m=0; m<height; m++)
           {
             for (n=0; n<width; n++)
             {
               s2[(band_cnt * height * width ) + m * width + n] 
                        = s1[(y_off+m)*image->row_size+(x_off+n)];
             }
           }
  
           band_cnt ++;
    
           if ( (sub_col_cnt - j) <= skip )
           {
             skew = skip - (sub_col_cnt - j);
           }
         } 
  
        /* 
         * Extract the rest of the (complete) rows.
         */
  
         for ( i=(sub_y_off+1) ; (i<sub_row_cnt) && (band_cnt<num_subs) ; i++ )
         {
           for ( j=skew ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip ) 
           {
             x_off = img_border + ( j * sub_cols ) + sub_border;
             y_off = img_border + ( i * sub_rows ) + sub_border;
  
             for (m=0; m<height; m++)
             {
               for (n=0; n<width; n++)
               {
                 s2[(band_cnt * height * width ) + m * width + n] 
                          = s1[(y_off+m)*image->row_size+(x_off+n)];
               }
             }
  
             band_cnt ++;
      
             if ( (sub_col_cnt - j) <= skip )
             {
               skew = skip - (sub_col_cnt - j);
             }
           }  /* end of loop through subimage columns */
         }  /* end of loop through subimage rows */
         break; /* end case VFF_TYP_2_BYTE */



    case VFF_TYP_4_BYTE:

         i1 = (int *)(image->imagedata);
         i2 = (int *)(img2->imagedata);

        /*
         * First extract subimages in the partial(?) row defined by 
         * sub_x_off and sub_y_off
         */
         for ( j=sub_x_off ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip )
         {
           x_off = img_border + ( j * sub_cols ) + sub_border;
           y_off = img_border + ( sub_y_off * sub_rows ) + sub_border;
  
           for (m=0; m<height; m++)
           {
             for (n=0; n<width; n++)
             {
               i2[(band_cnt * height * width ) + m * width + n] 
                        = i1[(y_off+m)*image->row_size+(x_off+n)];
             }
           }
  
           band_cnt ++;
    
           if ( (sub_col_cnt - j) <= skip )
           {
             skew = skip - (sub_col_cnt - j);
           }
         } 
  
        /* 
         * Extract the rest of the (complete) rows.
         */
  
         for ( i=(sub_y_off+1) ; (i<sub_row_cnt) && (band_cnt<num_subs) ; i++ )
         {
           for ( j=skew ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip ) 
           {
             x_off = img_border + ( j * sub_cols ) + sub_border;
             y_off = img_border + ( i * sub_rows ) + sub_border;
  
             for (m=0; m<height; m++)
             {
               for (n=0; n<width; n++)
               {
                 i2[(band_cnt * height * width ) + m * width + n] 
                          = i1[(y_off+m)*image->row_size+(x_off+n)];
               }
             }
  
             band_cnt ++;
      
             if ( (sub_col_cnt - j) <= skip )
             {
               skew = skip - (sub_col_cnt - j);
             }
           }  /* end of loop through subimage columns */
         }  /* end of loop through subimage rows */
         break; /* end case VFF_TYP_4_BYTE */
         

    case VFF_TYP_FLOAT:

         f1 = (float *)(image->imagedata);
         f2 = (float *)(img2->imagedata);

        /*
         * First extract subimages in the partial(?) row defined by 
         * sub_x_off and sub_y_off
         */
         for ( j=sub_x_off ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip )
         {
           x_off = img_border + ( j * sub_cols ) + sub_border;
           y_off = img_border + ( sub_y_off * sub_rows ) + sub_border;
  
           for (m=0; m<height; m++)
           {
             for (n=0; n<width; n++)
             {
               f2[(band_cnt * height * width ) + m * width + n] 
                        = f1[(y_off+m)*image->row_size+(x_off+n)];
             }
           }
  
           band_cnt ++;
    
           if ( (sub_col_cnt - j) <= skip )
           {
             skew = skip - (sub_col_cnt - j);
           }
         } 
  
        /* 
         * Extract the rest of the (complete) rows.
         */
  
         for ( i=(sub_y_off+1) ; (i<sub_row_cnt) && (band_cnt<num_subs) ; i++ )
         {
           for ( j=skew ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip ) 
           {
             x_off = img_border + ( j * sub_cols ) + sub_border;
             y_off = img_border + ( i * sub_rows ) + sub_border;
  
             for (m=0; m<height; m++)
             {
               for (n=0; n<width; n++)
               {
                 f2[(band_cnt * height * width ) + m * width + n] 
                          = f1[(y_off+m)*image->row_size+(x_off+n)];
               }
             }
  
             band_cnt ++;
      
             if ( (sub_col_cnt - j) <= skip )
             {
               skew = skip - (sub_col_cnt - j);
             }
           }  /* end of loop through subimage columns */
         }  /* end of loop through subimage rows */
         break; /* end case VFF_TYP_FLOAT */


    case VFF_TYP_COMPLEX:

         f1 = (float *)(image->imagedata);
         f2 = (float *)(img2->imagedata);

        /*
         * First extract subimages in the partial(?) row defined by 
         * sub_x_off and sub_y_off
         */
         for ( j=sub_x_off ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip )
         {
           x_off = img_border + ( j * sub_cols ) + sub_border;
           y_off = img_border + ( sub_y_off * sub_rows ) + sub_border;

           for (m=0; m<height; m++)
           {
             for (n=0; n<width*2; n++)
             {
               f2[(band_cnt * height * width * 2) + m * width * 2 + n] 
                        = f1[(y_off+m)*2*image->row_size+(x_off*2+n)];
             }
           }
  
           band_cnt ++;
    
           if ( (sub_col_cnt - j) <= skip )
           {
             skew = skip - (sub_col_cnt - j);
           }
         } 
  
        /* 
         * Extract the rest of the (complete) rows.
         */
  
         for ( i=(sub_y_off+1) ; (i<sub_row_cnt) && (band_cnt<num_subs) ; i++ )
         {
           for ( j=skew ; (j<sub_col_cnt) && (band_cnt<num_subs) ; j+=skip ) 
           {
             x_off = img_border + ( j * sub_cols ) + sub_border;
             y_off = img_border + ( i * sub_rows ) + sub_border;
  
             for (m=0; m<height; m++)
             {
               for (n=0; n<width*2; n++)
               {
                  f2[(band_cnt * height * width * 2) + m * width * 2 + n] 
                          = f1[(y_off+m)*2*image->row_size+(x_off*2+n)];
               }
             }
  
             band_cnt ++;
      
             if ( (sub_col_cnt - j) <= skip )
             {
               skew = skip - (sub_col_cnt - j);
             }
           }  /* end of loop through subimage columns */
         }  /* end of loop through subimage rows */
         break; /* end case VFF_TYP_COMPLEX */

    default:
         (void) fprintf(stderr,"lvmos2band: Unknown data storage type, %d\n",
                                img2->data_storage_type);
          return(0);
          break;
  } /* end type case statement */

  *img1 = img2;
  return(1);

}
/* -library_code_end */
