/****************************************************************************/
/*                                                                          */
/*  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_raw2slc.c
 *		      Author: Lisa Sobierajski & Rick Avila
 *			Date: 06/19/93
 *		 Description: Converts Raw To Slice Data File
 *	Modification History:
 *
 *		Who?		When?		Why?
 *	--------------------------------------------------------------------
 *
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>

#include "C_volvis.h"

main( argc, argv )
char	argc;
char	**argv;
{
	extern C_Voxel_8bit	*C_encode_8bit_data();

	char			raw_file_name[C_MAX_STRING];
	char			slc_file_name[C_MAX_STRING];
	int			raw_file_id;
	int			slc_file_id;
	char			tmp_msg[C_MAX_STRING];
	int			x_voxels;
	int			y_voxels;
	int			z_voxels;
	float			x_units;
	float			y_units;
	float			z_units;
	int			unit_type;
	int			data_origin;
	int			data_modification;
	int			data_compression;
	int			bits_per_voxel;
	int			magic;
	C_DataOrigin		real_data_origin;
	C_DataModification 	real_data_modification;
	C_CompressionType 	real_data_compression;
	C_UnitType		real_unit_type;
	int			xy_plane_size;
	int			z_counter;
	C_Voxel_8bit		*plane_ptr;
	C_Voxel_8bit		*encode_ptr;
	int			encode_size;
	int			in_count;	/* Bytes Read */
	int			out_count;	/* Bytes Written */
	int			done;
	off_t			offset;

	C_msg("raw2slc 1.0 Conversion Beginning\n");

	do
	{
	    	printf("Raw file name : ");
	    	scanf("%s", raw_file_name );

	    	if( (raw_file_id = open(raw_file_name, O_RDONLY)) <= 0 )
	    	{
		    	sprintf( tmp_msg, "Can NOT Open %s\n", raw_file_name );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf("SLC file name : ");
	    	scanf("%s", tmp_msg );
		sprintf( slc_file_name, "%s.%s", tmp_msg, C_SLICE_EXTENSION );

	    	if((slc_file_id = 
			open(slc_file_name, O_WRONLY | O_CREAT, 0644 ))<=0)
	    	{
		    	sprintf( tmp_msg, "Can NOT Open %s\n", slc_file_name );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf("x size voxels (samples) : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &x_voxels );

		if ( x_voxels <= 0 || x_voxels > 10000 )
	    	{
		    	sprintf( tmp_msg, 
				"Unreasonable x size in voxels : %d\n",
				   x_voxels );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf("y size voxels (samples) : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &y_voxels );

		if ( y_voxels <= 0 || y_voxels > 10000 )
	    	{
		    	sprintf( tmp_msg, 
				"Unreasonable y size in voxels : %d\n",
				   y_voxels );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf("z size voxels (samples) : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &z_voxels );

		if ( z_voxels <= 0 || z_voxels > 10000 )
	    	{
		    	sprintf( tmp_msg, 
				"Unreasonable z size in voxels : %d\n",
				   z_voxels );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf("Bits per voxel (sample) : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &bits_per_voxel );

		if ( bits_per_voxel !=8 )
	    	{
		    	sprintf( tmp_msg, "Unreasonable bits per voxel : %d\n",
					   bits_per_voxel );
		    	C_err_msg( tmp_msg );
			C_err_msg("Bits per voxel should be 8\n");
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf(
		    "Size of a voxel (distance between samples) in units : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%f", &x_units );

		if ( x_units <= 0.0 )
	    	{
		    	sprintf( tmp_msg, "Unreasonable x unit size : %f\n",
					   x_units );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf(
		    "Size of a voxel (distance between samples) in units : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%f", &y_units );

		if ( y_units <= 0.0 )
	    	{
		    	sprintf( tmp_msg, "Unreasonable y unit size : %f\n",
					   y_units );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
	    	printf(
		    "Size of a voxel (distance between samples) in units : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%f", &z_units );

		if ( z_units <= 0.0 )
	    	{
		    	sprintf( tmp_msg, "Unreasonable z unit size : %f\n",
					   z_units );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
  		printf("\t\t Units Types = \n");
  		printf("\t\t         0 Specifies Meter\n");
  		printf("\t\t         1 Specifies Millimeter\n");
  		printf("\t\t         2 Specifies Micrometer\n");
  		printf("\t\t         3 Specifies Foot\n");
	    	printf( "Unit type : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &unit_type );

		if ( unit_type < 0 || unit_type > 3 )
	    	{
		    	sprintf( tmp_msg, "Unreasonable unit type : %d\n",
					   unit_type );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
  		printf("\t\t Data Origin = \n");
  		printf("\t\t         0 Specifies BioRad Confocal Microscope\n");
  		printf("\t\t         1 Specifies Magnetic Resonance\n");
  		printf("\t\t         2 Specifies Computed Tomography\n");
  		printf("\t\t         3 Specifies Simulation\n");
  		printf("\t\t         4 Specifies Binary Voxelized Data\n");
  		printf("\t\t         5 Specifies Fuzzy Voxelized Data\n");
  		printf("\t\t         6 Specifies Other\n");
	    	printf( "Data origin : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &data_origin );

		if ( data_origin < 0 || data_origin > 6 )
	    	{
		    	sprintf( tmp_msg, "Unreasonable data origin : %d\n",
					   data_origin );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
  		printf("\t\t Data Modification = \n");
  		printf("\t\t         0 Specifies Original Data\n");
  		printf("\t\t         1 Specifies Resampled Data\n");
  		printf("\t\t         2 Specifies Filtered Data\n");
  		printf("\t\t         3 Specifies Resampled, Filtered Data\n");
  		printf("\t\t         4 Specifies Other Modification\n");
	    	printf( "Data modification : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &data_modification );

		if ( data_modification < 0 || data_modification > 4 )
	    	{
		    	sprintf( tmp_msg, 
				"Unreasonable data modification : %d\n",
				 data_modification );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	do
	{
  		printf("\t\t Data Compression = \n");
  		printf("\t\t         0 Specifies No Compression\n");
  		printf("\t\t         1 Specifies Run Length Encoding\n");
	    	printf( "Data compression : ");
	    	scanf("%s", tmp_msg );
		sscanf( tmp_msg, "%d", &data_compression );

		if ( data_compression < 0 || data_compression > 1 )
	    	{
		    	sprintf( tmp_msg, 
				"Unreasonable data compression : %d\n",
				 data_compression );
		    	C_err_msg( tmp_msg );
			done = FALSE;
	    	}
		else	
			done = TRUE;
	} while ( !done );

	switch( unit_type )
	{
	   case 0: real_unit_type = C_METER_UNIT;	break;
	   case 1: real_unit_type = C_MILLIMETER_UNIT;	break;
	   case 2: real_unit_type = C_MICRON_UNIT;	break;
	   case 3: real_unit_type = C_FOOT_UNIT;	break;
	   case 4: real_unit_type = C_INCH_UNIT;	break;
	}

	switch( data_origin )
	{
	   case 0: real_data_origin = C_BIORAD_CONFOCAL_DATA;	   break;
	   case 1: real_data_origin = C_MAGNETIC_RESONANCE_DATA;   break;
	   case 2: real_data_origin = C_COMPUTED_TOMOGRAPHY_DATA;  break;
	   case 3: real_data_origin = C_SIMULATION_DATA;	   break;
	   case 4: real_data_origin = C_BINARY_VOXELIZED_DATA;	   break;
	   case 5: real_data_origin = C_FUZZY_VOXELIZED_DATA;	   break;
	   case 6: real_data_origin = C_OTHER_DATA_ORIGIN;	   break;
	}

	switch( data_modification )
	{
	   case 0: real_data_modification = C_ORIGINAL_DATA;	   
		   break;
	   case 1: real_data_modification = C_RESAMPLED_DATA;   
		   break;
	   case 2: real_data_modification = C_FILTERED_DATA;  
		   break;
	   case 3: real_data_modification = C_RESAMPLED_FILTERED_DATA;	   
		   break;
	   case 4: real_data_modification = C_OTHER_DATA_MODIFICATION;	   
		   break;
	}

	switch( data_compression )
	{
	   case 0: real_data_compression = C_NO_COMPRESSION;	   break;
	   case 1: real_data_compression = C_RUN_LENGTH_ENCODE;    break;
	}

	magic = C_SLICE_MAGIC;

	/* Write The Header Onto The Slice File */
	write( slc_file_id, &magic, sizeof(int) );
	write( slc_file_id, &x_voxels, sizeof(int) );
	write( slc_file_id, &y_voxels, sizeof(int) );
	write( slc_file_id, &z_voxels, sizeof(int) );
	write( slc_file_id, &bits_per_voxel, sizeof(int) );
	write( slc_file_id, &x_units, sizeof(float) );
	write( slc_file_id, &y_units, sizeof(float) );
	write( slc_file_id, &z_units, sizeof(float) );
	write( slc_file_id, &real_unit_type, sizeof(C_UnitType) );
	write( slc_file_id, &real_data_origin, sizeof(C_DataOrigin) );
	write( slc_file_id, &real_data_modification,sizeof(C_DataModification));
	write( slc_file_id, &real_data_compression,sizeof(C_CompressionType));

	offset = lseek( slc_file_id, 0, SEEK_CUR );

	
	do 
	{
	  switch ( bits_per_voxel )
	  {
	    case 8:
	      /* Read In The Raw Data & Write Out Slice Data Plane By Plane */
	      xy_plane_size = x_voxels * y_voxels;

	      /* Allocate Space For 1 Plane */
	      plane_ptr = 
		  (C_Voxel_8bit *)malloc(sizeof(C_Voxel_8bit)*xy_plane_size);

	      if( plane_ptr == NULL )
	      {
		C_err_msg("Can NOT Allocate Memory For 1 Plane Of Data\n");
		exit( C_ERROR );
	      }

	      done = TRUE;
	      encode_ptr = NULL;

	      for( z_counter=0; z_counter<z_voxels; z_counter++ )
	      {
		in_count = read(  raw_file_id, plane_ptr, xy_plane_size );
		if( in_count != xy_plane_size )
		{
			C_err_msg("Can NOT Read Data From File\n");
		}

		switch ( real_data_compression )
		{
		  case C_NO_COMPRESSION:
		    out_count= write( slc_file_id, plane_ptr, xy_plane_size );
		    if( out_count != xy_plane_size )
		    {
			    C_err_msg("Can NOT Write Data To File\n");
		    }
		
		    break;

		  case C_RUN_LENGTH_ENCODE:
		    if ( encode_ptr )
			free( encode_ptr );

		    encode_ptr = C_encode_8bit_data( plane_ptr, xy_plane_size,
						     &encode_size );

		    if ( !encode_ptr )
		    {
			C_msg("Could not compress - writing uncompressed\n");
			done = FALSE;
			z_counter = z_voxels;
			real_data_compression = C_NO_COMPRESSION;
			lseek( slc_file_id, offset, SEEK_SET );
			lseek( raw_file_id, 0, SEEK_SET );
		    }
		    else
		    {
		      out_count= write( slc_file_id, &encode_size, sizeof(int));
		      if( out_count != sizeof(int) )
		      {
			    C_err_msg("Can NOT Write Data To File\n");
		      }

		      out_count= write( slc_file_id, encode_ptr, encode_size );
		      if( out_count != encode_size )
		      {
			    C_err_msg("Can NOT Write Data To File\n");
		      }
		    }

		    break;
		}
	      }

	      free( plane_ptr );
    
	      break;
	   }
	 } while (!done);

	close( raw_file_id );
	close( slc_file_id );


	C_msg("raw2slc 0.1 Conversion Complete\n");
	  

}

C_message( string )
char	*string;
{
	printf("%s", string);
}

C_error_message( string )
char	*string;
{
	printf("ERROR: %s", string);
}

C_msg( string )
char	*string;
{
	printf("%s", string);
}

C_err_msg( string )
char	*string;
{
	printf("ERROR: %s", string);
}

