/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/



/*
 *                      File: C_texture_input.c
 *                    Author: Lisa Sobierajski
 *                      Date: 9/24/92
 *               Description: This file contains the routine used to read
 *			      a texture from a file into a voltex structure. 
 *      Modification History:
 *
 *              Who?            When?           Why?
 *      --------------------------------------------------------------------
 *
 */

/****           Standard C Includes             ****/
# include <stdio.h>
# include <fcntl.h>
# include <string.h>

/****           VolVis Includes                 ****/
# include "C_volvis.h"


/*
 *        Procedure Name: C_read_volume_texture
 *        Return Value: int 
 *                              The return value indicates whether or
 *				not this routine successfully read the
 *				texture file into the voltex structure.
 *				The value can be either C_ERROR, or C_OK.
 *        Input Variables:
 *
 *		filename -   The name of the file which contains the 
 *			     texture data
 *
 *       Output Variables: 
 *
 *		voltex   -   A pointer to the volume texture structure
 *			     in which the texture should be stored
 *
 *       Update Variables: none
 *       Global Variables: none
 *            Description:
 *
 *		This routine reads a texture from the file indicated by
 * 		filename, and stores the appropriate information within
 *		the volume texture structure pointed to by voltex.
 *		If the texture is read successfully, C_OK will be returned.
 *		C_ERROR will be returned for the following reasons:
 *
 *			- named file cannot be opened
 *			  (does not exist, permission denied, etc.)
 *			- the first value in the file is not the
 *			  C_TEXTURE_MAGIC (this would indicate that
 *			  this is not a valid texture file)
 *			- texture depth is not 3 - currently only 24 bit
 *			  texture files are supported, if the depth is
 *			  not 3 bytes (24 bits), this is currently considered
 *			  an error
 */
int C_read_volume_texture( filename, voltex )
char		*filename;
C_VolTexture	*voltex;
{
	/****    External Routines    ****/
	extern  void	C_error_message();  /* From MOTIF_mes_ui.c        */

	/****    Local Variables    ****/
	int	fd;			    /* File descriptor            */
	int	depth;			    /* depth of texture           */
	int	magic_num;		    /* magic number from file     */
	char	string[80];		    /* string for C_error_message */


	/****    Try to open the file    ****/
	fd = open( filename, O_RDONLY );

	/****    If the file cannot be opened, display an error   ****/
	/****    message and return C_ERROR.			  ****/
	if ( fd < 0 )
	{
		sprintf( string, "ERROR - Could not open: %s\n", filename );
		C_error_message( string );
		return C_ERROR ;
	}

	voltex->texture_name = (char *) malloc( strlen( filename ) + 1 );
	sprintf( voltex->texture_name, "%s", filename );

	/****    Read the first four bytes and compare with     ****/
	/****    C_TEXTURE_MAGIC			        ****/
	read( fd, &magic_num, sizeof(int) );

	/****    If the magic numbers do not match, this is not ****/
	/****    a texture file - print the appropriate error   ****/
	/****    message and return C_ERROR                     ****/
	if ( magic_num != C_TEXTURE_MAGIC ) 
	{
	    sprintf( string, "%s is not a texture file!\n", filename );
	    C_error_message( string );

	    switch ( magic_num )
	    {
	      case C_SLICE_MAGIC:

		sprintf( string, "%s is a slice file!\n", filename );
		C_error_message( string );
		break;

	      case C_IMAGE_MAGIC:

		sprintf( string, "%s is a slice file!\n", filename );
		C_error_message( string );
		break;

	      case C_FUNCTION_MAGIC:

		sprintf( string, "%s is a slice file!\n", filename );
		C_error_message( string );
		break;

	      case C_ANIMATION_MAGIC:

		sprintf( string, "%s is a slice file!\n", filename );
		C_error_message( string );
		break;

	      default:

		break;

	    }

	    close ( fd );
	    return C_ERROR;
	}

	/****   Read the x, y, and z resolutions and the depth  ****/
	/****	of the texture data                             ****/
	/****   If at any point the read does not work, print   ****/	
	/****   an error message and return C_ERROR		****/

	if ( read( fd, &(voltex->xres), sizeof(int) ) != sizeof(int) )
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		close ( fd );
		return C_ERROR;
	}
	if ( read( fd, &(voltex->yres), sizeof(int) ) != sizeof(int) )
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		close ( fd );
		return C_ERROR;
	}
	if ( read( fd, &(voltex->zres), sizeof(int) ) != sizeof(int) )
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		close ( fd );
		return C_ERROR;
	}
	if ( read( fd, &depth, sizeof(int) ) != sizeof(int) )
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		close ( fd );
		return C_ERROR;
	}

	/****   If the depth is not 3 bytes, then print an error   ****/
	/****   message and return C_ERROR.  This routine          ****/
	/****   will be expanded in the future to handle more      ****/
	/****   depths						   ****/
	if (depth != 3)
	{
		sprintf( string, "%s: Invalid texture depth!\n", filename );
		C_error_message( string );
		close ( fd );
		return C_ERROR;
	}

	/****    Malloc space for the red part of texture.  If    ****/
	/****    there is not enough memory, print an error       ****/
	/****    message and return C_ERROR			  ****/
	voltex->red = (C_Byte *) malloc( voltex->xres * voltex->yres *
					 voltex->zres * sizeof(C_Byte) );
	if (!voltex->red)
	{
		C_error_message("Not Enough Memory!\n");
		close ( fd );
		return C_ERROR;
	}

	/****    Malloc space for the green part of texture.  If  ****/
	/****    there is not enough memory, print an error       ****/
	/****    message, free allocated memory, and return       ****/
	/****    C_ERROR					  ****/
	voltex->green = (C_Byte *) malloc( voltex->xres * voltex->yres *
					 voltex->zres * sizeof(C_Byte) );
	if (!voltex->green)
	{
		C_error_message("Not Enough Memory!\n");
		free ( voltex->red );
		close ( fd );
		return C_ERROR;
	}

	/****    Malloc space for the blue part of texture.  If   ****/
	/****    there is not enough memory, print an error       ****/
	/****    message, free allocated memory, and return       ****/
	/****    C_ERROR					  ****/
	voltex->blue = (C_Byte *) malloc( voltex->xres * voltex->yres *
					 voltex->zres * sizeof(C_Byte) );
	if (!voltex->blue)
	{
		C_error_message("Not Enough Memory!\n");
		free ( voltex->red );
		free ( voltex->green );
		close ( fd );
		return C_ERROR;
	}


	/****    Read in the red data.  If the file ends before the  ****/
	/****    data is read, print an error message, free all      ****/
	/****    allocated memory and return C_ERROR		     ****/
	if ( read( fd, voltex->red, 
		voltex->xres * voltex->yres * voltex->zres * sizeof(C_Byte) )
	     != voltex->xres * voltex->yres * voltex->zres * sizeof(C_Byte) ) 
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		free ( voltex->red );
		free ( voltex->green );
		free ( voltex->blue );
		close ( fd );
		return C_ERROR;
	}

	/****    Read in the green data. If the file ends before the ****/
	/****    data is read, print an error message, free all      ****/
	/****    allocated memory and return C_ERROR		     ****/
	if ( read( fd, voltex->green, 
		voltex->xres * voltex->yres * voltex->zres * sizeof(C_Byte) )
	     != voltex->xres * voltex->yres * voltex->zres * sizeof(C_Byte) ) 
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		free ( voltex->red );
		free ( voltex->green );
		free ( voltex->blue );
		close ( fd );
		return C_ERROR;
	}


	/****    Read in the blue data.  If the file ends before the ****/
	/****    data is read, print an error message, free all      ****/
	/****    allocated memory and return C_ERROR		     ****/
	if( read( fd, voltex->blue, 
		voltex->xres * voltex->yres * voltex->zres * sizeof(C_Byte) )
	     != voltex->xres * voltex->yres * voltex->zres * sizeof(C_Byte) ) 
	{
		sprintf( string, "%s: Incomplete File!\n", filename );
		C_error_message( string );
		free ( voltex->red );
		free ( voltex->green );
		free ( voltex->blue );
		close ( fd );
		return C_ERROR;
	}


	/****    Set the references to the texture to 0, since no    ****/
	/****    volume is currently using it			     ****/
	voltex->references = 0;

	/****    Close the file    ****/
	close( fd );

	return C_OK;

}

	
