/****************************************************************************/
/*                                                                          */
/*  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_pic2slc.c
 *		      Author: Rick Avila & Lisa Sobierajski
 *			Date: 02/02/92
 *		 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"

#define HEADER_SIZE		76

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

	char			pic_file_name[C_MAX_STRING];
	char			slc_file_name[C_MAX_STRING];
	char			tmp_msg[C_MAX_STRING];
	unsigned char		header[HEADER_SIZE];
	int			pic_file_id;
	int			slc_file_id;
	float			optical_step;
	float			cal_factor;
	float			pix_length;
	int			x_voxels;
	int			y_voxels;
	int			z_voxels;
	float			x_units;
	float			y_units;
	float			z_units;
	C_UnitType		real_unit_type;
        C_DataOrigin            real_data_origin;
        C_DataModification      real_data_modification;
        C_CompressionType       real_data_compression;
	int			xy_plane_size;
	int			z_counter;
	C_Voxel_8bit		*plane_ptr;
        C_Voxel_8bit            *encode_ptr;
        int                     encode_size;
	off_t                   offset;
	int			in_count;	/* Bytes Read */
	int			out_count;	/* Bytes Written */
	int			ival();
	float			fval();
	int			done;
	int			bits_per_voxel;
	int			data_compression;
	int			magic;
	

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


        do
        {
                printf("Pic file name : ");
                scanf("%s", tmp_msg );
		sprintf( pic_file_name, "%s.pic", tmp_msg );
 
                if( (pic_file_id = open(pic_file_name, O_RDONLY)) <= 0 )
                {
                        sprintf( tmp_msg, "Can NOT Open %s\n", pic_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("Optical step : ");
                scanf("%s", tmp_msg );
                sscanf( tmp_msg, "%f", &optical_step );
 
                if ( optical_step <= 0.0 )
                {
                        sprintf( tmp_msg,
                                "Unreasonable optical step : %d\n",
                                   optical_step );
                        C_err_msg( tmp_msg );
                        done = FALSE;
                }
                else
                        done = TRUE;
        } while ( !done );
 

        do
        {
                printf("Calibration Factor : ");
                scanf("%s", tmp_msg );
                sscanf( tmp_msg, "%f", &cal_factor );
 
                if ( cal_factor <= 0.0 )
                {
                        sprintf( tmp_msg,
                                "Unreasonable calibration factor : %d\n",
                                   cal_factor );
                        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( data_compression )
        {
           case 0: real_data_compression = C_NO_COMPRESSION;       break;
           case 1: real_data_compression = C_RUN_LENGTH_ENCODE;    break;
        }


	/*******************************/
	/* Read In the Confocal Header */
	/*******************************/
	if( (read( pic_file_id, header, HEADER_SIZE )) != HEADER_SIZE )
	{
		sprintf( tmp_msg,"Can NOT Read Header of %s\n", pic_file_name );
		C_err_msg( tmp_msg );
		exit( C_ERROR );
	}

	/*********************************************************/
	/* Check To See That This Is A VALID Confocal Image File */
	/*********************************************************/
	if( ival(54,header) != 12345 )
	{
		C_err_msg( "This Is NOT A Valid Confocal Image File.\n" );
		exit( C_ERROR );
	}

	/****************************************/
	/* Retrieve Relevant Header Information */
	/****************************************/
	x_voxels   = ival( 0, header );
	y_voxels   = ival( 2, header );
	z_voxels   = ival( 4, header );

	pix_length = cal_factor/((ival(64,header))*(fval(66,header)));

	x_units    = pix_length;
	y_units    = pix_length;
	z_units    = optical_step;

	real_unit_type = C_MICRON_UNIT;
	real_data_origin = C_BIORAD_CONFOCAL_DATA;
	real_data_modification = C_ORIGINAL_DATA;
	bits_per_voxel = 8;

        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));
 
        offset = lseek( slc_file_id, 0, SEEK_CUR );
 


	do
	{

            write(slc_file_id,&real_data_compression,sizeof(C_CompressionType));

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

	    /***************************/
	    /* Loop Through All Planes */
	    /***************************/
	    for( z_counter=0; z_counter<z_voxels; z_counter++ )
	    {
		/***************************/
		/* Read In A Plane Of Data */
		/***************************/
		in_count = read(  pic_file_id, plane_ptr, xy_plane_size );
		if( in_count != xy_plane_size )
		{
			sprintf( tmp_msg, "Can NOT Read Image Plane %d of %s\n",
				 z_counter, pic_file_name );
			C_err_msg( tmp_msg );
		}

		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( pic_file_id, HEADER_SIZE, 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 Up Memory */
	    /******************/
	    free( plane_ptr );

	} while ( !done );

	/***********************/
	/* Close Up Open Files */
	/***********************/
	close( pic_file_id );
	close( slc_file_id );


	C_msg("pic2slc 1.0 Conversion Complete\n");
}

float fval( start, buffer )
int		start;		/* Byte To Start On In Header */
unsigned char	*buffer;	/* Pointer To Header Storage  */
{
	unsigned char	float_num[4];	/* Temp Storage */
	float		temp_float;

	/* Swap The Bytes */
	float_num[0] = buffer[start+3];
	float_num[1] = buffer[start+2];
	float_num[2] = buffer[start+1];
	float_num[3] = buffer[start+0];

	temp_float = (*((float *)(float_num)));

	return( temp_float );
}

int ival( start, buffer )
int		start;		/* Byte To Start On In Header */
unsigned char	*buffer;	/* Pointer To Header Storage  */
{
	int	temp_int;

	/* Compute The Value of The Integer With Bytes Swapped */
	temp_int = (buffer[start] + (buffer[start+1])*256);

	return( temp_int );
}

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);
}

