 /*
  * Khoros: $Id: lviff2pbm.c,v 1.4 1992/03/20 23:36:01 dkhoros Exp $
  */

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

 /*
  * $Log: lviff2pbm.c,v $
 * Revision 1.4  1992/03/20  23:36:01  dkhoros
 * VirtualPatch5
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * 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: lviff2pbm.c
 >>>>
 >>>>      Program Name: viff2pbm
 >>>>
 >>>> Date Last Updated: Sat Mar  2 14:43:45 1991 
 >>>>
 >>>>          Routines: lviff2pbm - the library call for viff2pbm
 >>>>
 >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>   <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/


#include "vinclude.h"


/* -library_includes */
#include "file_formats/pbm.h"
#include "vrev.h"
/* -library_includes_end */


/****************************************************************
*
* Routine Name: lviff2pbm - library call for viff2pbm
*
* Purpose:
*    
*    Converts a VIFF image to a PBM image.
*    
*    
* Input:
*    
*         struct xvimage *viff:  VIFF input image
*    
*         int raw:  flag specifying ascii or raw output
*    
*    
* Output:
*    
*         struct pbm  **pbm:  PBM output image
*    
*    
*
* Written By: Charlie Gage and Mark Young
****************************************************************/


/* -library_def */
int lviff2pbm(viff, pbm, raw)

struct xvimage *viff;
struct pbm     **pbm;
int    raw;
/* -library_def_end */

/* -library_code */
{
        struct pbm *temp;
        int  num_bytes;
        int  num_pixels, msize, mcount, lsize, lcount;
        int max_viff_value();
        char *program = "lviff2pbm";


        /*-----------------  ERROR checking ------------------------- */
        if (viff == NULL)
           return(FALSE);

        if ( (viff->num_data_bands != 1) && (viff->num_data_bands != 3) )
        {
          (void) fprintf(stderr,"%s: input image must be a single band\n",program);
          (void) fprintf(stderr,"or 3-band image for conversion to pbm format.");
          return(FALSE);
        }

          if ( (viff->map_scheme != VFF_MS_SHARED) && (viff->map_scheme != VFF_MS_ONEPERBAND) && (viff->map_scheme != VFF_MS_NONE) )
          {
            (void) fprintf(stderr,"%s: input image must have a map scheme\n",program);
            (void) fprintf(stderr,"of none, shared or oneperband.\n");
            return(FALSE);
          }

        if ( (viff->data_storage_type != VFF_TYP_BIT) && (viff->data_storage_type != VFF_TYP_1_BYTE) && (viff->data_storage_type != VFF_TYP_2_BYTE) && (viff->data_storage_type != VFF_TYP_4_BYTE) )
        {
          (void) fprintf(stderr,"%s: Input image must be of data type,\n",program);
          (void) fprintf(stderr,"BIT, BYTE, SHORT or INTEGER\n");
          return(FALSE);
        }

        /*
         *  Malloc space for the pbm structure.
         */
        if (!(temp = (struct pbm *) calloc(1, sizeof(struct pbm))))
        {
           (void) fprintf(stderr,"%s: Unable to allocate memory for \
pbm image structure.\n",program);
           return(FALSE);
        }

        /*-----------------------------------------------------------------
         * Do some preprocessing of the input image to determine
         *  if any data conversion (upcasting) should be performed
         *  and what target PBM image type is appropriate based
         *  on the input image.
         *----------------------------------------------------------------*/
        if (viff->data_storage_type == VFF_TYP_BIT)
        {
          temp->raw = raw;
          temp->type = PBM;        /* output class is PBM image */
        }
        else if ( (viff->map_scheme == VFF_MS_NONE) && (viff->num_data_bands == 1) )
        {
          if ( (viff->data_storage_type == VFF_TYP_2_BYTE) || (viff->data_storage_type == VFF_TYP_4_BYTE) || (!raw) )
          {
            temp->raw = 0;    /* force output to ascii in this case */
            if ( (viff->data_storage_type == VFF_TYP_2_BYTE) || (viff->data_storage_type == VFF_TYP_1_BYTE) )
            {
              if (lvconvert(viff, VFF_TYP_4_BYTE, 0, 1, 0.0, 1.0, 1) == 0)
              {
                (void) fprintf(stderr,"%s: unable to convert SHORT image\n",program);
                return(FALSE);
              }
            }
          }
          else
             temp->raw = raw;     /* set desired output type */
          temp->type = PGM;       /* output class is PGM image */
        }
        else
        {
          if ( (viff->map_scheme == VFF_MS_ONEPERBAND) || (viff->map_scheme == VFF_MS_SHARED) )
          {
            if (lvmapdata(viff) == 0)
            {
              (void) fprintf(stderr,"%s: Unable to map the data\n", program);
              return(FALSE);
            }
          }
          if ( (viff->data_storage_type == VFF_TYP_2_BYTE) || (viff->data_storage_type == VFF_TYP_4_BYTE) )
          {
            temp->raw = 0;        /* force output type to ASCII */
            if (viff->data_storage_type == VFF_TYP_2_BYTE)
            {
              if (lvconvert(viff, VFF_TYP_4_BYTE, 0, 1, 0.0, 1.0, 1) == 0)
              {
                (void) fprintf(stderr,"%s: unable to convert SHORT image\n",program);
                return(FALSE);
              }
            }
          }
          else if ( (viff->data_storage_type == VFF_TYP_1_BYTE) && (!raw) )
          {
            if (lvconvert(viff, VFF_TYP_4_BYTE, 0, 1, 0.0, 1.0, 1) == 0)
            {
              (void) fprintf(stderr,"%s: unable to convert SHORT image\n",program);
              return(FALSE);
            }
            temp->raw = 0;           /* force output type to ASCII */
          }
          else
            temp->raw = raw;         /* set desired output type */
          temp->type = PPM;          /* set class of output image */
        }

         /* Determine image size of input viff image */
        if (imagesize(viff, &num_bytes, &num_pixels, &msize, &mcount,&lsize,&lcount) == 0)
        {
          (void) fprintf(stderr,"%s: Unable to determine image size.\n",program);
          return(FALSE);
        }

         /* Set header parameters of PBM image */
        temp->maxval = max_viff_value(viff);
        temp->width = viff->row_size;
        temp->height = viff->col_size;

         /* Malloc space for pbm data according to num_bytes of viff image */
        if (!(temp->data = (char *) calloc(1, num_bytes)))
        {
           (void) fprintf(stderr,"%s: Unable to allocate memory for PBM image data.\n",program);
           free(temp);
           return(FALSE);
        }

        /*-----------------------------------------------------------
         * Process viff image according to appropriate class
         *  and type of PBM image.
         *-----------------------------------------------------------*/

        if (temp->type == PPM)       /* output type is PPM */
        {
                                        /* raw format selected */
           if ( (temp->raw) && (viff->data_storage_type == VFF_TYP_1_BYTE) ) 
           {
              int      i, j, size;
              unsigned char *src, *dest;

              size = temp->width * temp->height;
              src = (unsigned char *) viff->imagedata;
              dest = (unsigned char *) temp->data;

              for (i = 0, j = 0; i < size; i++)
              {
                 dest[j++] = src[i];
                 dest[j++] = src[i+size];
                 dest[j++] = src[i+size*2];
              }
           }
           else                   /* ascii format selected */
           {
              int i, j, size;
              int *src, *dest;

              size = temp->width * temp->height;
              src = (int *) viff->imagedata;
              dest = (int *) temp->data;

              for (i = 0, j = 0; i < size; i++)
              {
                 dest[j++] = src[i];
                 dest[j++] = src[i+size];
                 dest[j++] = src[i+size*2];
              }
           }
        }
        else if (temp->type == PGM)    /* Output image will be PGM  */
        {
           if ( (temp->raw) && (viff->data_storage_type == VFF_TYP_1_BYTE) )
           {
             unsigned char *src, *dest;
             src = (unsigned char *) viff->imagedata;
             dest = (unsigned char *) temp->data;

             bcopy(src, dest, num_bytes);
           }
           else              /* ascii format selected */
           {
             int i, size;
             int *src, *dest;

             size = temp->width * temp->height;
             src = (int *) viff->imagedata;
             dest = (int *) temp->data;

             for (i = 0; i < size; i++)
                 dest[i] = src[i];
           }
        }
        else   /*----  VIFF image is BIT, Output image will be PBM  ----*/
        {
             int      i;
             unsigned char *src, *dest;

             src = (unsigned char *) viff->imagedata;
             dest = (unsigned char *) temp->data;

             for (i = 0; i < num_bytes; i++)
             {
               if (temp->raw)
                   dest[i] = ~rev[src[i]];
               else                           /* ascii format selected */
                   dest[i] = ~src[i];
             }
        }

        *pbm = temp;

        return(TRUE);
}   /*** End of MAIN ***/

int max_viff_value(viff)

struct xvimage *viff;
{
  int i, max_value, tmp;
  int img_size = viff->row_size * viff->col_size;
  unsigned char  *src_byte_img;
  int  *src_int_img;

  max_value = 0;

  switch (viff->data_storage_type)
  {
   case VFF_TYP_BIT:
     max_value = 1;
     break;
   case VFF_TYP_1_BYTE:
     src_byte_img = (unsigned char *)viff->imagedata;
     for (i=0; i < img_size; i++)
     {
       tmp = src_byte_img[i];
       if (tmp > max_value)
          max_value = tmp;
     }
     break;
   case VFF_TYP_4_BYTE:
     src_int_img = (int *) viff->imagedata;
     for (i=0; i < img_size; i++)
     {
       tmp = src_int_img[i];
       if (tmp > max_value)
          max_value = tmp;
     }
     break;
   default:
     {
       (void)fprintf(stderr,"lviff2pbm: ERROR, incorrect data type.\n");
       return(0);
     }
  }
  return(max_value);
}
/* -library_code_end */
