 /*
  * Khoros: $Id: readheader.c,v 1.3 1992/03/20 23:41:09 dkhoros Exp $
  */

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

 /*
  * $Log: readheader.c,v $
 * Revision 1.3  1992/03/20  23:41:09  dkhoros
 * VirtualPatch5
 *
  */ 

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

/*
 *
 *  READHEADER- Read an KHOROS image header from the file pointed 
 *              to by the supplied file descriptor.
 *
 *  NOTE:       THIS CODE IS MACHINE DEPENDENT!
 *
 *  Written : Scott R. Wilson, University of New Mexico
 *  Date:     28-Mar-87
 *  Modified: 13-Jan-88  Scott R. Wilson - Changed machine type decoding and
 *                                         added support for NS32000.
 *             3-Apr-88  Scott R. Wilson - Better error messages.
 *
 *       23-May-88 Tom Sauer	 - Better error message for incorrect 
 *				   header.
 *       17-Jun-88 Mark Young	 - Changed all wait reads (added by Ron)
 *				   to use block_read().
 *       18-Feb-89 Scott R. Wilson - Updated to XV 3.0
 *       31-May-89 Scott R. Wilson - Updated to XV 3.1
 *       1991 Jeremey Worley - Completely rewritten. 
 */

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

#define BYTE_FIELD_SIZE 520
#define OTHER_FIELD_CNT 25 
#define VIFF_HEADER_SIZE 1024

struct xvimage
*readheader(file)
int file;
{
    struct xvimage *imageptr;
    unsigned char *temp,*temp2,*temp3,*temp4;
    int convert_order(), convert_long(), convert_float();
    long machtype(),current_machine,source_machine;
    long current_order,source_order,word_size,getmachorder();
    unsigned char id1,id2;
    int numread,headersize;  /* Added by Ron. E. Neher to fix pipe problem */
    int i;

    /* 
     * Grab space for the image structure and read it 
     */

    if((imageptr = (struct xvimage *)kcalloc(1,sizeof(struct xvimage)))==NULL){
       (void)fprintf(stderr,"\nreadheader: Not enough memory ");
       (void)fprintf(stderr,"for image header\n");
       return(NULL);
    }

    /*
     * malloc some temp space that we'll be needing later
     */
    headersize = VIFF_HEADER_SIZE;
    if((temp = (unsigned char *)kcalloc(1,(unsigned)headersize))==NULL){
       (void)fprintf(stderr,"\nreadheader: Not enough memory to read ");
       (void)fprintf(stderr,"image header\n");
       return(NULL);
    }

    if((temp2 = (unsigned char *)kcalloc(1,5*sizeof(long)))==NULL){
       (void)fprintf(stderr,"\nreadheader: Not enough memory to read ");
       (void)fprintf(stderr,"image header\n");
       return(NULL);
    }
    if((temp3 = (unsigned char *)kcalloc(1,2*sizeof(float)))==NULL){
       (void)fprintf(stderr,"\nreadheader: Not enough memory to read ");
       (void)fprintf(stderr,"image header\n");
       return(NULL);
    }
    if((temp4 = (unsigned char *)kcalloc(1,18*sizeof(long)))==NULL){
       (void)fprintf(stderr,"\nreadheader: Not enough memory to read ");
       (void)fprintf(stderr,"image header\n");
       return(NULL);
    }

    /*
     * attempt to read the whole header in.
     */

    if((numread = block_read(file,(char *)temp, headersize))!=headersize){
        (void) fprintf(stderr,"\nreadheader: Incorrect header byte count: ");
	(void) fprintf(stderr,"found %d, should be %d\n",numread,headersize);
        (void) fprintf(stderr,"Possible invalid input VIFF data or an empty ");
        (void) fprintf(stderr,"file.\n");
        free(imageptr);
        return(NULL);
    }

    /*
     * fill in the portions of the header that we never need conversion
     */

    (void)bcopy((char *)temp,(char *)imageptr,BYTE_FIELD_SIZE);

    /* 
     * check to see if we are an VIFF file 
     */

    id1 = imageptr->identifier;
    id2 = XV_FILE_MAGIC_NUM;
    if (id1 != id2 || imageptr->file_type != XV_FILE_TYPE_XVIFF) {
        (void)fprintf(stderr,"\nreadheader: Cannot read non-VIFF file!\n");
        (void)free(imageptr);
        return(NULL);
    }
    
    
    /* 
     * Check the release and version numbers 
     */

    if (imageptr->release != XV_IMAGE_REL_NUM ||
        imageptr->version != XV_IMAGE_VER_NUM)
    {
        (void) fprintf(stderr,"\nreadheader: Release or version number ");
	(void) fprintf(stderr,"mismatch!\n");
        (void) fprintf(stderr,"readheader: Release is %d, should be %d\n",
                imageptr->release,XV_IMAGE_REL_NUM);
        (void) fprintf(stderr,"readheader: Version is %d, should be %d\n",
                imageptr->version,XV_IMAGE_VER_NUM);
        free(imageptr);
        return(NULL);
    }

    /* 
     * See if we need to convert the header to the current machine type 
     */

    current_machine = machtype(NULL);
    current_order =   getmachorder(current_machine);
    source_machine  = imageptr->machine_dep;
    source_order =    getmachorder(source_machine);

    word_size = 4;

    /*
     * we use IEEE format on crays for the header since their wordsize
     * is different
     */
    if(source_machine==VFF_DEP_CRAYORDER){
       source_machine = VFF_DEP_IEEEORDER;
       source_order = VFF_DEP_BIGENDIAN;
    }

    if(current_machine==source_machine){
        bcopy((char *)(temp + BYTE_FIELD_SIZE),
              (char *)&imageptr->row_size,
              (VIFF_HEADER_SIZE - BYTE_FIELD_SIZE)); 
    }else{
        i = convert_order((unsigned char *)(temp+BYTE_FIELD_SIZE),
                      (unsigned int)source_order,
                      (unsigned int)VFF_DEP_BIGENDIAN,
                      (unsigned int)OTHER_FIELD_CNT,
                      (unsigned int)word_size);
        if(!i){
           fprintf(stderr,"\nOrder conversion failed in readheader.\n");
           free(temp);
           free(temp2);
           free(temp3);
           free(temp4);
           return(0);
        }

        /*
         * this call converts row_size through starty to new encoding
         */

        bcopy((char *)(temp+BYTE_FIELD_SIZE),(char *)temp2,20);
        i = convert_long((unsigned char **)&temp2,
                             (unsigned int)source_machine,
                             (unsigned int)current_machine,
                             (unsigned int)5);
        if(!i){
           fprintf(stderr,"\nData format conversion failed in readheader.\n");
           free(temp);
           free(temp2);
           free(temp3);
           free(temp4);
           return(0);
        }

        /* 
         * this call converts pixsizx and pixsizy to new encoding 
         */

        bcopy((char *)(temp+BYTE_FIELD_SIZE+20),(char *)temp3,8);
        i = convert_float((unsigned char **)&temp3,
                             (unsigned int)source_machine,
                             (unsigned int)current_machine,
                             (unsigned int)2);
        if(!i){
           fprintf(stderr,"\nData format conversion failed in readheader.\n");
           free(temp);
           free(temp2);
           free(temp3);
           free(temp4);
           return(0);
        }
 
        /* 
         * this call converts location_type through fspare2 to new encoding
         */

        bcopy((char *)(temp+BYTE_FIELD_SIZE+28),(char *)temp4,72);
        i = convert_long((unsigned char **)&temp4,
                             (unsigned int)source_machine,
                             (unsigned int)current_machine,
                             (unsigned int)18);
        if(!i){
           fprintf(stderr,"\nData format conversion failed in readheader.\n");
           free(temp);
           free(temp2);
           free(temp3);
           free(temp4);
           return(0);
        }


        bcopy((char *)temp2,(char *)&imageptr->row_size,5*sizeof(long));
        bcopy((char *)temp3,(char *)&imageptr->pixsizx,2*sizeof(float));
        bcopy((char *)temp4,(char *)&imageptr->location_type,18*sizeof(long));

        i = convert_order((unsigned char *)(&imageptr->row_size),
                      (unsigned int)VFF_DEP_BIGENDIAN,
                      (unsigned int)current_order,
                      (unsigned int)OTHER_FIELD_CNT,
                      (unsigned int)word_size);
        if(!i){
           fprintf(stderr,"\nData format conversion failed in readheader.\n");
           free(temp);
           return(0);
        }

        free(temp2);
        free(temp3);
        free(temp4);

        /*
         * this last call converts the resulting header to the
         * correct byte order
         */

        if(current_machine==VFF_DEP_CRAYORDER)
           word_size = 8;
        else
           word_size = 4;


    } /* fi big if */

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