// TIFFCONV.CPP

typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;

#include <iostream>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "..\scanfile.h"

using namespace std; //introduces namespace std

/* Function Prototypes */

void convert(int type);
short rotate_short(short inbuf);
unsigned long rotate_ulong(unsigned long inbuf);
void file_close(void);

/* Definitions */

#define	TIFF				1
#define TEXT				2
#define MAX_IMAGE_WIDTH		250		// Columns
#define MAX_IMAGE_LENGTH	400		// Rows

/* Variable Declarations */

FILE *out, *in;

/*************************************************************/

int main ( void )
{
	char menu_key;
		
	while(1)
  	{

		cout << "\n\n\nScanner File Converter 1.0";
		cout << "\n1 - Convert scan file to text.";
		cout << "\n9 - Exit.";
    	cout << "\n\nEnter Selection: ";

    	cin >> menu_key;

    	switch(menu_key)
    	{
      		case '1':
				convert(TEXT);
				break;


      		case '9':
				exit(0);
    	}
  	}
}

/*******************************************************/

void convert(int type)
{
#pragma unused(type)

  	char file_in[80], file_out[80];
	int file_num;
	ulong image_width, col, image_length, row;
	ushort ping_buff[END_BIN + 1], z_elev;
	uchar scan_line[MAX_IMAGE_WIDTH], scan_line_byte;
	struct def scan_info;
	

	// Get the scanner system info
	if((in = fopen("scaninfo.dat", "rb")) == NULL)
	{
		cout << "\nCould not open scaninfo.dat";
		file_close();
		return;
	}

  	if( fread(&scan_info, sizeof(scan_info), 1, in) != 1 )
  	{
    	cout << "\nError reading scaninfo.bin";
    	file_close();
    	return;
  	}

  	if(fclose(in))
  	{
  		cout << "\nScaninfo.bin file close error";
		file_close();
		return;
	}
	

	file_num = 0;

  	// File conversion loop
	while(1)
	{
	   
	    sprintf(file_in, "%d.bin", file_num);  // Make a name for the output file

	  	// Open the input file
		if((in = fopen(file_in, "rb")) == NULL)
		{
			cout << "\nCould not open " << file_in;
			file_close();
			return;
		}
	  
	 
	  	// Open the output file
	    sprintf(file_out, "%d.txt", file_num);  // Make a name for the output file

		if((out = fopen(file_out, "w")) == NULL)
	 	{
	 		cout << "\nCould not open " << file_out;
	 		file_close();
	 		return;
	 	}


	 	cout << "\nWriting Text file " << file_num;
		
		file_num++;	  
	
	  	// Figure the image data
	  	image_width = MAX_IMAGE_WIDTH;

		image_length = FLUOR_CELL_SIZE * rotate_short(scan_info.y_scan_len);
		if(image_length >= MAX_IMAGE_LENGTH)
		{
			cout << "\nImage length too large: " << image_length;
			return;
		}

		// Write the image data
		for(row=0; row< image_length; row++)
		{
		  	if( fread(ping_buff, sizeof(ushort),END_BIN+1, in) != END_BIN+1 )
		  	{
		    	cout << "\nError reading " << file_in;
		    	cout << "\nrow = " << row;
		    	file_close();
		    	return;
		  	}
				
			// Erase the main bang data
			for(col=1; col<= 12; col++)		
			{
				ping_buff[col] = 0;
			}

			// Initialize the scan line buffer
			for(col=0; col< MAX_IMAGE_WIDTH; col++)		
			{
				scan_line[col] = 0;
			}

			// Read the z-axis elevation
			z_elev = rotate_short(ping_buff[0]);
			
			// Test the elevation for reasonableness
			if(END_BIN+z_elev > MAX_IMAGE_WIDTH)
			{
				cout << "\nError: z_elev out of bounds " << z_elev << "row " << row;
		    	file_close();
		    	return;
			}
			
			// Write the elevation corrected ping data to a buffer
			for(col=1; col< END_BIN; col++)
			{
				scan_line_byte = (uchar)(rotate_short(ping_buff[col]));
				if(scan_line_byte > 255) scan_line[col+z_elev] = 255;
				else scan_line[col+z_elev] = scan_line_byte;
			}
			
			// Write the buffer data to a text file
			fprintf(out, "\n");
			for(col=1; col< MAX_IMAGE_WIDTH; col++)
			{
				fprintf(out, "%d\t", (int)scan_line[col]);
			} 

		}

		fclose(in);
		fclose(out);
	}
  	
  	file_close();
  	return;
}


/************************************************************
  The following rotate functions are used to correct the
  difference between the way Motorola and Intel processors
  store their data.  Motorola stores the high-byte of words
  in lower addresses.  Intel stores the high_byte in higher
  addresses.  Files transferred with XMODEM need to be corrected.
**************************************************************/

short rotate_short(short inbuf){
  union ushort_buf{
    unsigned short word;
    unsigned char byte[2];
  } tempbuf1, tempbuf2;

  tempbuf1.word = inbuf;
  tempbuf2.byte[0] = tempbuf1.byte[1];
  tempbuf2.byte[1] = tempbuf1.byte[0];

  return tempbuf2.word;
}

/**************************************************/


unsigned long rotate_ulong(unsigned long inbuf){
  union ulong_buf{
    unsigned long word;
    unsigned char byte[4];
  } tempbuf1, tempbuf2;

  tempbuf1.word = inbuf;
  tempbuf2.byte[0] = tempbuf1.byte[3];
  tempbuf2.byte[1] = tempbuf1.byte[2];
  tempbuf2.byte[2] = tempbuf1.byte[1];
  tempbuf2.byte[3] = tempbuf1.byte[0];

  return tempbuf2.word;
}

/*****************************************************/


void file_close(void)
{
	fclose(in);
	fclose(out);
}

/*****************************************************/
