 /*
  * Khoros: $Id: readimage.c,v 1.4 1991/12/18 09:57:38 dkhoros Exp $
  */

#if !defined(lint) && !defined(SABER)
static char rcsid[] = "Khoros: $Id: readimage.c,v 1.4 1991/12/18 09:57:38 dkhoros Exp $";
#endif

 /*
  * $Log: readimage.c,v $
 * Revision 1.4  1991/12/18  09:57:38  dkhoros
 * HellPatch3
 *
  */ 

/*
 *----------------------------------------------------------------------
 *
 * 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.
 *---------------------------------------------------------------------
 */

/*
 *
 *   READIMAGE - Read an KHOROS image from the specified file. Special
 *              filenames are "-" which is STDIN and "#" which is
 *              STDERR.
 *
 *              Machine dependencies are
 *              taken care of by converting the incoming data into
 *              the data format of the host.
 *
 *  NOTE:       THIS CODE IS MACHINE DEPENDENT!
 *
 *  Written:  Scott Wilson
 *  Date:     24-Feb-87
 *
 *  Changes:  
 *      Mark Young  6/17/88
 *            Changed all wait reads (added by Ron) to use block_read().
 *            Also changed error response conditions to use freeimage()
 *            in order to free failed image, and also changed all exit(1)
 *            to return(NULL).
 *      Scott Wilson and Tom Sauer 11/23/88
 *            Added support for color map models - must scale image data
 *            size by number of color axes.
 *      Scott Wilson 18-Feb-89 
 *            Updated to XV 3.0
 *      Scott Wilson 31-May-89 
 *            Updated to XV 3.1
 *      Scott Wilson  2-Feb-90 
 *            Added image cache support
 *      Scott Wilson 21-Jun-90 
 *            Modified for filenames instead of fd's
 *      Scott Wilson 22-Jun-90 
 *            Changed cache support
 *      Scott Wilson 6-Aug-90 
 *            Catch malloc of zero bytes (SYS V bug)
 *      Scott Wilson 11-Dec-90 
 *            Added normal file locking
 *      Scott Wilson 29-May-91 
 *            Fix "-" as input filename
 *      Mark Young 14-Sep-91   
 *            Fix "-" to not perform flock() and not get closed.  
 *      Jeremy Worley Mon Oct 14 08:59:18 MDT 1991
 *            Modifications to large portions of this routine and others 
 *            it calls to support architectures with word sizes other than
 *            32 bit.  Cache support code was deleted.
 *             
 */

#include "unmcopyright.h"	 /* Copyright 1990 by UNM */
#include "vinclude.h"

struct xvimage *readimage(filename)
char *filename;
{
    char           buf[512];
    long           machtype(),getmachorder();
    long           src_order,dest_order;
    unsigned long  src_machine,dest_machine,dimension,getmachsize();
    int            imgsize,mapsize,locsize,imgcnt,mapcnt,loccnt,storage_type;
    struct xvimage *image, *readheader();
    int            block_read();
    int            read_compressed(),elem_size;
    int            file;
    int            cast_data(),i;

    /* 
    ** if file cannot be found, return NULL indicating failure.
    */    
    if (!vfullpath(filename,NULL,buf)) return(NULL);

     if((file = kopen(buf,O_RDONLY)) < 0){
        (void)fprintf(stderr,"\nreadimage: unable to access file %s\n",
                      filename);
        return(NULL);
     }

    /* 
     * lock the file for reading...
     */
    kflock(file,LOCK_SH);
    
    /* 
     * Read the image header 
     */
    if((image = readheader(file)) == NULL){
       krclose(file);
       return(NULL);
    }

    /* 
     * Get size of image components in bytes 
     */
    if(!imagesize(image,&imgsize,&imgcnt,&mapsize,&mapcnt,&locsize,&loccnt)){
       free((void *)image);
       krclose(file);
       return(NULL);
    }

/*
 * this is where things start to get hairy.
 */

    src_machine = (unsigned long)image->machine_dep;
    dest_machine = machtype(NULL);
    
    src_order = getmachorder((long int)src_machine);
    dest_order = getmachorder((long int)dest_machine);

    /* 
     * Read  maps 
     */
    if(mapsize!=0){
       if((image->maps =(char*)malloc((unsigned)mapsize*sizeof(char)))==NULL){
          fprintf(stderr,"\nreadimage:  Memory allocation failure\n");
          freeimage(image);
          krclose(file);
          return(NULL);
       }

       if(image->data_encode_scheme == VFF_DES_RAW) {
           if (block_read(file,(char *)image->maps, mapsize) != mapsize) {
               fprintf(stderr,"\nreadimage: ");
    	       fprintf(stderr,"Incorrect byte count reading maps!\n");
               freeimage(image);
               krclose(file);
               return(NULL);
           }
       }else{
          if(read_compressed(file,image->maps,mapsize,image) != mapsize) {
              fprintf(stderr,"\nreadimage: ");
              fprintf(stderr,"Unable to interpret compressed maps!\n");
              freeimage(image);
              krclose(file);
              return(NULL);
          }
       } /* fi */

       /*
        * this obnoxious if statement handles the fact that double has
        * a different value for maps and data in viff.h!
        */
       if (image->map_storage_type == VFF_MAPTYP_DOUBLE)
          storage_type = VFF_TYP_DOUBLE;
       else
          storage_type = image->map_storage_type;

       elem_size = getmachsize(src_machine,(unsigned long)storage_type);
       dimension = mapsize/elem_size;
       if(storage_type!=VFF_MAPTYP_NONE){
          i = cast_data((unsigned char **)&(image->maps),
                         (unsigned int)dimension,
                         (unsigned int)storage_type,
                         (unsigned int)src_machine,
                         (unsigned int)dest_machine);
          if(!i){
            fprintf(stderr,"\nData format conversion failed in readimage().\n");
            fprintf(stderr,"Error occured while reading map data.\n");
            return(0);
          }
       } /* end if storage_type */
    } /* end if maptype!=0 */

    /* 
     * Read  locations 
     */
    if(locsize!=0){
       if((image->location = (float *)malloc(locsize*sizeof(char)))==NULL){
           fprintf(stderr,"\nreadimage:  Memory allocation failure\n");
           freeimage(image);
           krclose(file);
           return(NULL);
       }

       if(image->data_encode_scheme == VFF_DES_RAW) {
           if (block_read(file,(char *)(image->location), locsize) != locsize) {
               fprintf(stderr,"\nreadimage: ");
    	       fprintf(stderr,"Incorrect byte count reading locations!\n");
               freeimage(image);
               krclose(file);
               return(NULL);
           }
       } else {
           if (read_compressed(file,(char *)image->location,locsize,image) 
                != locsize) {
               fprintf(stderr,"\nreadimage: ");
    	       fprintf(stderr,"Unable to interpret compressed locations!\n");
               freeimage(image);
               krclose(file);
               return(NULL);
            }
       } /* fi */

       elem_size = getmachsize(src_machine,(unsigned long)VFF_TYP_FLOAT);
       dimension = locsize/elem_size;
       i = cast_data((unsigned char **)&(image->location),
                     (unsigned int)dimension, 
                     (unsigned int)VFF_TYP_FLOAT, 
                     (unsigned int)src_machine, 
                     (unsigned int)dest_machine);
       if(!i){
          fprintf(stderr,"\nData format conversion failed in readimage().\n");
          fprintf(stderr,"Error occured while reading location data.\n");
          return(0);
       }

    } /* end if locsize!=0 */

    /* 
     * Read  image data 
     */
    if(imgsize!=0){
       if((image->imagedata = (char *)malloc((unsigned)imgsize*sizeof(char)))
          ==NULL){
          fprintf(stderr,"\nreadimage:  Memory allocation failure\n");
          freeimage(image);
          krclose(file);
          return(NULL);
       }

       if(image->data_encode_scheme == VFF_DES_RAW) {
           if (block_read(file,image->imagedata, imgsize) != imgsize) {
               fprintf(stderr,"\nreadimage: ");
       	       fprintf(stderr,"Incorrect byte count reading image data!\n");
               freeimage(image);
               krclose(file);
               return(NULL);
           }
       } else {
          if (read_compressed(file,image->imagedata,imgsize,image) != imgsize) {
             fprintf(stderr,"\nreadimage: ");
             fprintf(stderr,"Unable to interpret compressed image data!\n");
             freeimage(image);
             krclose(file);
             return(NULL);
           }
       } /* fi */

       if(image->data_storage_type!=VFF_TYP_BIT){
          elem_size = getmachsize(src_machine,image->data_storage_type);
          dimension = imgsize/elem_size;
          i = cast_data((unsigned char **) &(image->imagedata),
                            (unsigned int)dimension,
                            (unsigned int)image->data_storage_type, 
                            (unsigned int)src_machine, 
                            (unsigned int)dest_machine); 
          if(!i){
             fprintf(stderr,
                     "\nData format conversion failed in readimage().\n");
             fprintf(stderr,"Error occurred while reading image data.\n");
             return(0);
          }

       }
    } /* end if imgsize!=0 */

  krclose(file);

  image->machine_dep = machtype(NULL);

  /* 
   * Return the whole mess to the caller 
   */
  return(image);
}

krclose(file)
int file;
{
   kflock(file,LOCK_UN);
   kclose(file);
}
