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

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

 /*
  * $Log: lvtranslat.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: lvtranslat.c
 >>>>
 >>>>      Program Name: vtranslat
 >>>>
 >>>> Date Last Updated: Sun Mar 31 13:56:28 1991 
 >>>>
 >>>>          Routines: lvtranslat - the library call for vtranslat
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


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


/****************************************************************
*
* Routine Name: lvtranslat - library call for vtranslat
*
* Purpose:
*    
*    Translates an xvimage structure
*    
*    
* Input:
*    
*         img  - an xvimage structure (input image).
*         vi   - integer: Translation along i axis
*         vj   - integer: Translation along j axis
*         wflg - integer: flag set to one if wrapping selected or zero
*         if padding with padding value
*         pad  - float: padding value used to set the  pixels  of  the
*         result  image  that  have  not received any value during the
*         translation process.
*    
*    
* Output:
*    
*    img  - Holds the result of the translation.
*    
*    
*
* Written By: Pascal ADAM
*    
*    Ghosted by Pascal ADAM  Mon Jun  4 12:13:28 MDT 1990
*    
*    
****************************************************************/


/* -library_def */
int
lvtranslat(img,vj,vi,wflg,pad)
struct xvimage *img;
int   wflg;
int   vi,vj;
float pad;
/* -library_def_end */

/* -library_code */
{
#define X(i,j,l)  (i*nc + j + l*k)    
#define xi      (i+vi)
#define ximod   ((((i+vi)%nr)+nr)%nr)
#define xj      (j+vj)
#define xjmod   ((((j+vj)%nc)+nc)%nc)

/* 
**   ATTENTION: Following to a XVGROUP consensus, the translation
**   on the X axis is a horizontal translation. The original
**   version was based on a OX,OY coordinate system that was
**   inverted.
** 
**   So now, the axis x is horizontal, and the y Axis is vertical.
**   That way, we have the axis i or x which is horizontal
**   and j or y which is vertical.    --------> X or I
**                                    |
**   I personnaly do not agree with   |
**   this convention, because of the  |
**   non direct system (mathematical  |
**   problem could be inducted )      V
**                                        Y or J 
**
**   cf: A direct system is a system in which one passes from 
**       the X axis to the Y axis by rotating X in the positive
**       direction. 
**
**   Nevertheless I respect the CHORUS majority and note
**   that the axis modification has been made by inverting the
**   arguments vi and vj in the function definition.
**
*/    
     int    i, j, k, l, nc, nr, absvi, absvj;
     int int_pad;
     int band;
  
     unsigned char *c1;
     short  *s1;
     int    *i1;
     float  *f1;

     unsigned char  *result1;  /* pointer to resulting image byte  */
     short          *result2;  /* pointer to resulting image short */
     int            *result3;  /* pointer to resulting image int   */
     float          *result4;  /* pointer to resulting image float */

     nc   = img->row_size; 
     nr   = img->col_size;
     band = img->num_data_bands;
     k    = nc * nr; 

     absvi = (vi<0) ? (-1*vi) : vi;
     absvj = (vj<0) ? (-1*vj) : vj;

     if ((nr < absvi || nc < absvj) && (wflg == 1)) /* translation too far */ 
     {                                              /* result out of image */ 
        fprintf(stderr,
        "lvtranslat: translation vector too long\n");
        return(0);
     }
     switch (img->data_storage_type)
     {
        case VFF_TYP_BIT :
          (void)fprintf(stderr,
          "lvtranslat: Don't know how to translate BIT images\n");
          return(0);
          break;

        case VFF_TYP_1_BYTE :

          /* Allocate space for resulting image */
          result1 = (unsigned char *)malloc(band*k*sizeof(char));
          if(result1 == NULL) 
          {
            (void) fprintf(stderr,"lvtranslat: insufficient memory available\n");
            return(0);
          }

          /* check if pad has a compatible value for byte image */   
          if ((pad > 255) || (pad < 0))
          { 
             (void) fprintf(stderr,"lvtranslat: uncorrect pad value for a byte image\n");
             return(0);
          } 
          int_pad = (unsigned char)pad;

          /* pointer on image data */
          c1 = (unsigned char *)(img->imagedata);
     
          /* loop for translation computation */    
          for (i=0; i<nr; i++)
          { 
              for (j=0; j<nc; j++)
              {
                  for (l=0; l<band; l++)
                  {
                      if (((xi != ximod)||(xj != xjmod))&&(wflg == 0))
                         /* padding case  */
                         *(result1+X(ximod,xjmod,l)) = int_pad;
                         /* wrapping case */
                      else  *(result1+X(ximod,xjmod,l)) = *(c1+X(i,j,l)); 
                  }
              }
          }
  
          c1 = (unsigned char *)(img->imagedata);
          for (i=0;i<k*band;i++) *(c1+i) = *(result1+i);

          break;
        case VFF_TYP_2_BYTE :

          /* Allocate space for resulting image */
          result2 = (short *)malloc(band*k*sizeof(short));
          if(result2 == NULL) 
          {
            (void) fprintf(stderr,"lvtranslat: insufficient memory available\n");
            return(0);
          }

          /* check if pad has a compatible value for byte image */   
          if ((pad > 65535) || (pad < 0))
          { 
             (void) fprintf(stderr,"lvtranslat: uncorrect pad value for a byte image\n");
             return(0);
          } 
          int_pad = (short) pad;

          /* pointer on image data */
          s1 = (short *)(img->imagedata);
     
          /* loop for translation computation */    
          for (i=0; i<nr; i++)
          { 
              for (j=0; j<nc; j++)
              {
                  for (l=0; l<band; l++)
                  {
                      if (((xi != ximod) || (xj != xjmod)) &&  (wflg == 0))
                         /* padding case  */
                         *(result2+X(ximod,xjmod,l)) = int_pad;      
                         /* wrapping case */
                      else  *(result2+X(ximod,xjmod,l)) = *(s1+X(i,j,l)); 
                  }
              }
          }
  
          s1 = (short *)(img->imagedata);
          for (i=0;i<k*band;i++) *(s1+i) = *(result2+i);

          break;
        case VFF_TYP_4_BYTE :
        
          /* Allocate space for resulting image */
          result3 = (int *)malloc(band*k*sizeof(int));
          if(result3 == NULL) 
          {
            (void) fprintf(stderr,"lvtranslat: insufficient memory available\n");
            return(0);
          }

          /* check if pad has a compatible value for byte image */   
          int_pad = (int) pad;
          if ( ((int_pad-pad) > 1) || ((int_pad-pad) < -1))
          { 
             (void) fprintf(stderr,"lvtranslat: uncorrect pad value for a 4_byte image\n");
             return(0);
          } 

          /* pointer on image data */
          i1 = (int *)(img->imagedata);
     
          /* loop for translation computation */    
          for (i=0; i<nr; i++)
          { 
              for (j=0; j<nc; j++)
              {
                  for (l=0; l<band; l++) 
                  {
                      if (((xi != ximod) || (xj != xjmod)) &&  (wflg == 0))
                      /* padding case  */
                         *(result3+X(ximod,xjmod,l)) = int_pad;      
                      /* wrapping case */
                      else  *(result3+X(ximod,xjmod,l)) = *(i1+X(i,j,l)); 
                  }
              }
          }
  
          i1 = (int *)(img->imagedata);
          for (i=0;i<k*band;i++) *(i1+i) = *(result3+i);

          break;

        case VFF_TYP_FLOAT :

          /* Allocate space for resulting image */
          result4 = (float *)malloc(band*k*sizeof(float));
          if(result4 == NULL) 
          {
            (void) fprintf(stderr,"lvtranslat: insufficient memory available\n");
            return(0);
          }

          /* pointer on image data */
          f1 = (float *)(img->imagedata);
     
          /* loop for translation computation */    
          for (i=0; i<nr; i++)
          { 
              for (j=0; j<nc; j++)
              {
                  for (l=0; l<band; l++)
                  {

                      if (((xi != ximod) || (xj != xjmod)) &&  (wflg == 0))
                      /* padding case  */
                         *(result4+X(ximod,xjmod,l)) = pad;          
                      /* wrapping case */
                       else  *(result4+X(ximod,xjmod,l)) = *(f1+X(i,j,l)); 
                  }
              }
          }
  
          f1 = (float *)(img->imagedata);
          for (i=0;i<k*band;i++) *(f1+i) = *(result4+i);

          break;

 
        case VFF_TYP_COMPLEX :
          /* Allocate space for resulting image */
          result4 = (float *)malloc(band*k*2*sizeof(float));
          if(result4 == NULL)
          {
            (void) fprintf(stderr,"lvtranslat: insufficient memory available\n");
            return(0);
          }


         /* pointer on image data */
          f1 = (float *)(img->imagedata);
          for (i=0;i<nc;i++)  {
              for (j=0;j<nr;j++)  {
                  for (l=0;l<band;l++)  {
                      if (((xi != ximod)||(xj != xjmod))&&(wflg == 0)) {
                         /* padding case  */
                         *(result4+2*X(ximod,xjmod,l))   = pad; 
                         *(result4+2*X(ximod,xjmod,l)+1) = pad; 
                         }
                      else  {  
                         /* wrapping case */
                         *(result4+2*X(ximod,xjmod,l))= *(f1+2*X(i,j,l));
                         *(result4+2*X(ximod,xjmod,l)+1)= *(f1+2*X(i,j,l)+1);
                         }
                      }
                  }
              }

          f1 = (float *)(img->imagedata);
          for (i=0;i<2*k*band;i++) *(f1+i) = *(result4+i);

	  free(img->imagedata);
          img->imagedata = (char *)f1;
          img->data_storage_type =  VFF_TYP_COMPLEX;
          break;
                   
        default:
          fprintf(stderr,
          "lvtranslat: Unknown data storage type, %d\n",
          img->data_storage_type);

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