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



# include <stdio.h>
# include <fcntl.h> 

# include "C_volvis.h"


C_create_image_from_view( image, view )
C_Image		*image;
C_View		*view;

{
	C_Byte		*tmp_ptr;
	int		loop;

	image->width  = view->width_pixels;
	image->height = view->height_pixels;
	image->depth  = 3;

	image->red    = (C_Byte *) malloc( image->width * 
			image->height * sizeof(C_Byte) );

	image->green  = (C_Byte *) malloc( image->width * 
			image->height * sizeof(C_Byte) );

	image->blue   = (C_Byte *) malloc( image->width * 
			image->height * sizeof(C_Byte) );

	switch ( view->projection_type )
	{
	    case C_PARC:
		if ( view->shadows_enabled == FALSE &&
		     view->max_reflect_ray_level == 0 &&
		     view->max_transmit_ray_level == 0 &&
		     view->max_indirect_light_level == 0 )
		{	
		    image->image_info.render_type = C_PARC_RENDERING;
		}
		else
		{
	 	    image->image_info.render_type = C_PARC_RAYTRACE_RENDERING; 
		}

		break;
	
	    case C_RAY_TRACE:
		image->image_info.render_type = C_RAYTRACE_RENDERING;
		break;

	    case C_VOLRAD:
		image->image_info.render_type = C_RADIOSITY_RENDERING;
		break;
	}


	image->image_info.image_accuracy = view->image_accuracy;
	image->image_info.compute_shadows = view->shadows_enabled;
	image->image_info.levels_of_reflection = view->max_reflect_ray_level;
	image->image_info.levels_of_transmission = view->max_transmit_ray_level;
	image->image_info.levels_of_indirect_light = 
					view->max_indirect_light_level;

	tmp_ptr = image->red;
	for (loop = 0; loop < (view->width_pixels*view->height_pixels); loop++)
		*(tmp_ptr++) = 0;

	tmp_ptr = image->green;
	for (loop = 0; loop < (view->width_pixels*view->height_pixels); loop++)
		*(tmp_ptr++) = 0;

	tmp_ptr = image->blue;
	for (loop = 0; loop < (view->width_pixels*view->height_pixels); loop++)
		*(tmp_ptr++) = 0;
}

int C_write_image_to_file( image, filename ) 
C_Image		*image;
char		*filename;

{
	int	return_val;

	return_val =  C_write_rle_image_to_file( image, filename ); 

	if ( return_val == C_ERROR )
	{
	    C_message("Could not save compressed image file.\n");
	    return_val = C_write_uncompressed_image_to_file( image, filename );
	    if ( return_val == C_OK )
		C_message("Saved uncompressed image file\n");
	}

	return return_val;
}

int C_write_rle_image_to_file( image, filename )
C_Image         *image;
char            *filename;
 
{
	extern C_Byte		*C_encode_8bit_data();
	int			fd;
	C_Byte			*encode_ptr;
	C_CompressionType	compress_type;
	int			num_bytes;
	char			string[300];
	int			magic_num = C_IMAGE_MAGIC;


	if ( (fd = open( filename, O_RDONLY)) > 0 )
	{
	  if ( C_MASTER_PROCESS )
	  {
		C_error_message("That file already exists!\n");
		close(fd);
		return C_ERROR;
	  }
	  else
		exit();
	}

	fd = open( filename, O_WRONLY | O_CREAT, 0644 );

	if (fd < 0)
	{
		fprintf(stderr, "Error opening file: %s\n", filename );
		return C_ERROR;
	}

	write( fd, &(magic_num), sizeof(int) );
	write( fd, &(image->width),  sizeof(int) );
	write( fd, &(image->height), sizeof(int) );
	write( fd, &(image->depth),  sizeof(int) );
	write( fd, &(image->image_info.image_accuracy),sizeof(C_ImageAccuracy));
	write( fd, &(image->image_info.compute_time), sizeof(float) );
	write( fd, &(image->image_info.render_type), sizeof( C_RenderingType ));
	
	switch ( image->image_info.render_type )
	{
	    case C_RAYTRACE_RENDERING:
	    case C_PARC_RAYTRACE_RENDERING:

		write( fd, &(image->image_info.compute_shadows), sizeof(int) );
		write( fd, &(image->image_info.levels_of_reflection), 
					sizeof(int) );
		write( fd, &(image->image_info.levels_of_transmission), 
					sizeof(int) );
		write( fd, &(image->image_info.levels_of_indirect_light), 
					sizeof(int) );
	
		break;
	}

	compress_type = C_RUN_LENGTH_ENCODE;

	write( fd, &compress_type, sizeof(C_CompressionType) );

	if ( image->depth == 1)
	{
		encode_ptr = C_encode_8bit_data( image->red, 
				image->width * image->height, &num_bytes );

		if (!encode_ptr) 
		{
		  close( fd );
		  sprintf( string, "/bin/rm %s", filename );
		  system( string );
		  return C_ERROR;
		}

		write( fd, &num_bytes, sizeof(int) );

		write( fd, encode_ptr, num_bytes * sizeof(C_Byte) );

		free ( encode_ptr );
		
	}
	else if ( image->depth == 3 )
	{
		encode_ptr = C_encode_8bit_data( image->red, 
				image->width * image->height, &num_bytes );

		if (!encode_ptr) 
		{
		  close( fd );
		  sprintf( string, "/bin/rm %s", filename );
		  system( string );
		  return C_ERROR;
		}

		write( fd, &num_bytes, sizeof(int) );

		write( fd, encode_ptr, num_bytes * sizeof(C_Byte) );

		free ( encode_ptr );
		
		encode_ptr = C_encode_8bit_data( image->green, 
				image->width * image->height, &num_bytes );

		if (!encode_ptr) 
		{
		  close( fd );
		  sprintf( string, "/bin/rm %s", filename );
		  system( string );
		  return C_ERROR;
		}

		write( fd, &num_bytes, sizeof(int) );

		write( fd, encode_ptr, num_bytes * sizeof(C_Byte) );

		free ( encode_ptr );
		
		encode_ptr = C_encode_8bit_data( image->blue, 
				image->width * image->height, &num_bytes );

		if (!encode_ptr) 
		{
		  close( fd );
		  sprintf( string, "/bin/rm %s", filename );
		  system( string );
		  return C_ERROR;
		}

		write( fd, &num_bytes, sizeof(int) );

		write( fd, encode_ptr, num_bytes * sizeof(C_Byte) );

		free ( encode_ptr );
	}

	close( fd );

	return C_OK;
}

int C_write_uncompressed_image_to_file( image, filename )
C_Image         *image;
char            *filename;
 
{
	int			fd;
	C_CompressionType	compress_type;
	int			magic_num = C_IMAGE_MAGIC;


	if ( (fd = open( filename, O_RDONLY)) > 0 )
	{
	  if ( C_MASTER_PROCESS )
	  {
		C_error_message("That file already exists!\n");
		close(fd);
		return C_ERROR;
	  }
	  else
		exit();
	}

	fd = open( filename, O_WRONLY | O_CREAT, 0644 );

	if (fd < 0)
	{
		fprintf(stderr, "Error opening file: %s\n", filename );
		return C_ERROR;
	}

	write( fd, &(magic_num), sizeof(int) );
	write( fd, &(image->width),  sizeof(int) );
	write( fd, &(image->height), sizeof(int) );
	write( fd, &(image->depth),  sizeof(int) );
	write( fd, &(image->image_info.image_accuracy),sizeof(C_ImageAccuracy));
	write( fd, &(image->image_info.compute_time), sizeof(float) );
	write( fd, &(image->image_info.render_type), sizeof( C_RenderingType ));
	
	switch ( image->image_info.render_type )
	{
	    case C_RAYTRACE_RENDERING:
	    case C_PARC_RAYTRACE_RENDERING:

		write( fd, &(image->image_info.compute_shadows), sizeof(int) );
		write( fd, &(image->image_info.levels_of_reflection), 
					sizeof(int) );
		write( fd, &(image->image_info.levels_of_transmission), 
					sizeof(int) );
		write( fd, &(image->image_info.levels_of_indirect_light), 
					sizeof(int) );
	
		break;
	}


	compress_type = C_NO_COMPRESSION;

	write( fd, &compress_type, sizeof(C_CompressionType) );

	if ( image->depth == 1)
	{
		write( fd, &(image->red), image->width * image->height );
	}
	else if ( image->depth == 3 )
	{
		write( fd, &(image->red), image->width * image->height );
		write( fd, &(image->green), image->width * image->height );
		write( fd, &(image->blue), image->width * image->height );
	}

	close( fd );

	return C_OK;
}


int C_read_image_from_file( image, filename ) 
C_Image		*image;
char		*filename;
{

	extern C_Byte		*C_decode_8bit_data();
	int			fd;
	C_CompressionType	compress_type;
	int			rle_size;
	C_Byte			*encode_ptr;
	int			magic_num;
	char			string[256];

	fd = open( filename, O_RDONLY );

	if (fd < 0)
	{
		C_error_message("Could Not Open Image!!!\n");
		return C_ERROR;
	}

	read( fd, &magic_num, sizeof(int) );		

        /****    If the magic numbers do not match, this is not ****/
        /****    an image  file - print the appropriate error   ****/
        /****    message and return C_ERROR                     ****/
        if ( magic_num != C_IMAGE_MAGIC )
        {
            sprintf( string, "%s is not an image file!\n", filename );
            C_error_message( string );
 
            switch ( magic_num )
            {
              case C_TEXTURE_MAGIC:
 
                sprintf( string, "%s is a texture file!\n", filename );
                C_error_message( string );
                break;
 
              case C_SLICE_MAGIC:
 
                sprintf( string, "%s is a slice file!\n", filename );
                C_error_message( string );
                break;
 
              case C_FUNCTION_MAGIC:
 
                sprintf( string, "%s is a function file!\n", filename );
                C_error_message( string );
                break;
 
              case C_ANIMATION_MAGIC:
 
                sprintf( string, "%s is an animation file!\n", filename );
                C_error_message( string );
                break;
 
              default:
 
                break;
 
            }
            close ( fd );
            return C_ERROR;
        }


	read( fd, &(image->width), sizeof(int) );		
	read( fd, &(image->height), sizeof(int) );		
	read( fd, &(image->depth), sizeof(int) );		
	read( fd, &(image->image_info.image_accuracy), sizeof(C_ImageAccuracy));
	read( fd, &(image->image_info.compute_time), sizeof(float) );
	read( fd, &(image->image_info.render_type), sizeof( C_RenderingType ) );
	
	switch ( image->image_info.render_type )
	{
	    case C_RAYTRACE_RENDERING:
	    case C_PARC_RAYTRACE_RENDERING:
		read( fd, &(image->image_info.compute_shadows), sizeof(int) );
		read( fd, &(image->image_info.levels_of_reflection), 
					sizeof(int) );
		read( fd, &(image->image_info.levels_of_transmission), 
					sizeof(int) );
		read( fd, &(image->image_info.levels_of_indirect_light), 
					sizeof(int) );
	
		break;
	}


	read( fd, &compress_type, sizeof(C_CompressionType) );

	switch ( compress_type )
	{
	  case C_NO_COMPRESSION:

		image->red = ( C_Byte * ) malloc( image->width * 
				image->height * sizeof( C_Byte ) );
		
		read( fd, &(image->red), image->width * image->height *
				      sizeof( C_Byte ) );

		if ( image->depth == 3 )
		{
			image->green = ( C_Byte * ) malloc( image->width * 
				image->height * sizeof( C_Byte ) );
		
			read( fd, &(image->green), image->width * 
				image->height * sizeof( C_Byte ) );

			image->blue = ( C_Byte * ) malloc( image->width * 
				image->height * sizeof( C_Byte ) );
		
			read( fd, &(image->blue), image->width * 
				image->height * sizeof( C_Byte ) );
		}
	
		break;
	
	case C_RUN_LENGTH_ENCODE:

		read( fd, &rle_size, sizeof(int) );

		encode_ptr = ( C_Byte * ) malloc( rle_size * sizeof(C_Byte) );

		read( fd, encode_ptr, rle_size * sizeof(C_Byte) );

		image->red = C_decode_8bit_data( encode_ptr, 
					     image->width * image->height );

		free( encode_ptr );

		if ( image->depth == 3 )
		{
			read( fd, &rle_size, sizeof(int) );

			encode_ptr = ( C_Byte * ) malloc( 
					rle_size * sizeof(C_Byte) );

			read( fd, encode_ptr, rle_size * sizeof(C_Byte) );

			image->green = C_decode_8bit_data( encode_ptr, 
					     image->width * image->height );

			free( encode_ptr );

			read( fd, &rle_size, sizeof(int) );

			encode_ptr = ( C_Byte * ) malloc( 
					rle_size * sizeof(C_Byte) );

			read( fd, encode_ptr, rle_size * sizeof(C_Byte) );

			image->blue = C_decode_8bit_data( encode_ptr, 
					     image->width * image->height );

			free( encode_ptr );

		}

		break;
	}

        close ( fd );
	return C_OK;
		
}

