/*--------------------------------------------------------------------
 *    The MB-system:	mb_lgpl.c	9/13/2004
 *    $Id:  $
 *
 *    Copyright (c) 2004-2012 by
 *    David W. Caress (caress@mbari.org)
 *      Monterey Bay Aquarium Research Institute
 *      Moss Landing, CA 95039
 *    and Dale N. Chayes (dale@ldeo.columbia.edu)
 *      Lamont-Doherty Earth Observatory
 *      Palisades, NY 10964
 *
 *    This file contains source code modified from source files
 *    distributed as part of MB-System. In contrast to the GPL-licensed
 *    MB-System distributions, the code contained here is licensed
 *    under the Lesser GNU Public license, or LGPL. This means that
 *    compiled versions of these functions, or functions derived from
 *    modifications to this code, may be linked with commercial
 *    applications without imposing any restriction on the sale and
 *    and distribution of those applications.
 *
 *    The full LGPL text may be accessed at http://www.gnu.org/
 *
 *    The release of this code under the LGPL does not change the
 *    the GPL licensing of any code contained in the regular
 *    MB-System distribution.
 *
 *    The source code provided here does not come with any warranties,
 *    nor is it guarenteed to work on your computer or to do
 *    anything useful. The user assumes full responsibility for
 *    the use of this software. In particular, David W. Caress,
 *    Dale N. Chayes, the Lamont-Doherty Earth Observatory of
 *    Columbia University, the Monterey Bay Aquarium Research Institute,
 *    or any other individuals or organizations involved in the
 *    design and maintenance of the MB-System software package
 *    and derived distributions are NOT responsible for any
 *    damage that may follow from correct or incorrect use of this
 *    source code. Moreover, it should be noted that the source
 *    code provided here has NOT been tested after modification
 *    from the related functions that are part of MB-System.
 *
 *    To access MB-System documentation or source code releases see:
 *         http://www.mbari.org/data/mbsystem
 *         http://www.ldeo.columbia.edu/MB-System
 *
 *--------------------------------------------------------------------*/
/*
 * Author:	D. W. Caress
 * Originated:	September 13, 2004
 * Revised:	May 16, 2012
 *
 * $Log:  $
 *
 *--------------------------------------------------------------------*/
/*
 *    The header file mb_lgpl.h contains structure and macro definitions
 *    required for this source to compile.
 *
 *    The function mblgpl_read_fbt() is intended to provide an
 *    an example template for reading swath bathymetry stored in
 *    "fbt" files as part of the MB-System processing environment.
 *
 *    An application using this function must have already opened the
 *    the fbt file (ergo the FILE pointer fp) and allocated the data
 *    storage structure referenced by store using mblgpl_fbt_alloc().
 *
 *
 */

/* standard include files */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* mblgpl include file */
#include "mb_lgpl.h"

static char res_id[]="$Id:  $";

/*--------------------------------------------------------------------*/
int mblgpl_fbt_alloc(int verbose, struct mblgpl_fbt_struct **store_ptr,
			int *error)
{
	char	*function_name = "mblgpl_fbt_alloc";
	int	status = MBLGPL_SUCCESS;
	struct mblgpl_fbt_struct *store;

	/* print input debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> called\n",
			function_name);
		fprintf(stderr,"dbg2  Input arguments:\n");
		fprintf(stderr,"dbg2       verbose:    %d\n",verbose);
		fprintf(stderr,"dbg2       store_ptr:  %p\n",store_ptr);
		}

	/* allocate memory for data structure */
	status = mblgpl_malloc(verbose,sizeof(struct mblgpl_fbt_struct),
				store_ptr,error);

	/* get store */
	store = *store_ptr;

	/* initialize values in structure */
	store->kind = MBLGPL_DATA_NONE;
	store->time_d = 0.0;
	store->longitude = 0.0;
	store->latitude = 0.0;
	store->sonardepth = 0.0;
	store->altitude = 0.0;
	store->heading = 0.0;
	store->speed = 0.0;
	store->roll = 0.0;
	store->pitch = 0.0;
	store->heave = 0.0;
	store->beam_xwidth = 0.0;
	store->beam_lwidth = 0.0;
	store->beams_bath = 0;
	store->beams_amp = 0;
	store->pixels_ss = 0;
	store->spare1 = 0;
	store->beams_bath_alloc = 0;
	store->beams_amp_alloc = 0;
	store->pixels_ss_alloc = 0;
	store->depth_scale = 0.0;
	store->distance_scale = 0.0;
	store->ss_type = 0;
	store->spare2 = 0;
	store->beamflag = NULL;
	store->bath = NULL;
	store->amp = NULL;
	store->bath_acrosstrack = NULL;
	store->bath_alongtrack = NULL;
	store->ss = NULL;
	store->ss_acrosstrack = NULL;
	store->ss_alongtrack = NULL;
	memset(store->comment, 0, MBLGPL_FBT_COMMENTSIZE);

	/* print output debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> completed\n",
			function_name);
		fprintf(stderr,"dbg2  Return values:\n");
		fprintf(stderr,"dbg2       *store_ptr: %p\n",*store_ptr);
		fprintf(stderr,"dbg2       error:      %d\n",*error);
		fprintf(stderr,"dbg2  Return status:\n");
		fprintf(stderr,"dbg2       status:     %d\n",status);
		}

	/* return status */
	return(status);
}
/*--------------------------------------------------------------------*/
int mblgpl_fbt_deall(int verbose, struct mblgpl_fbt_struct **store_ptr,
			int *error)
{
	char	*function_name = "mblgpl_fbt_deall";
	int	status = MBLGPL_SUCCESS;
	struct mblgpl_fbt_struct *store;

	/* print input debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> called\n",
			function_name);
		fprintf(stderr,"dbg2  Input arguments:\n");
		fprintf(stderr,"dbg2       verbose:    %d\n",verbose);
		fprintf(stderr,"dbg2       *store_ptr: %p\n",*store_ptr);
		}

	/* get store */
	store = *store_ptr;

	/* deallocate memory for data structures */
	status = mblgpl_free(verbose,&store->beamflag,error);
	status = mblgpl_free(verbose,&store->bath,error);
	status = mblgpl_free(verbose,&store->bath_acrosstrack,error);
	status = mblgpl_free(verbose,&store->bath_alongtrack,error);
	status = mblgpl_free(verbose,&store->amp,error);
	status = mblgpl_free(verbose,&store->ss,error);
	status = mblgpl_free(verbose,&store->ss_acrosstrack,error);
	status = mblgpl_free(verbose,&store->ss_alongtrack,error);

	/* deallocate memory for data structure */
	status = mblgpl_free(verbose,store,error);

	/* print output debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> completed\n",
			function_name);
		fprintf(stderr,"dbg2  Return values:\n");
		fprintf(stderr,"dbg2       store_ptr:  %p\n",store_ptr);
		fprintf(stderr,"dbg2       error:      %d\n",*error);
		fprintf(stderr,"dbg2  Return status:\n");
		fprintf(stderr,"dbg2       status:     %d\n",status);
		}

	/* return status */
	return(status);
}
/*--------------------------------------------------------------------*/
int mblgpl_read_fbt(int verbose, FILE *fp, struct mblgpl_fbt_struct *store, int *error)
{
	char	*function_name = "mblgpl_read_fbt";
	int	status = MBLGPL_SUCCESS;
	struct mblgpl_oldfbt_struct oldstore;
	int	read_size;
	short	*flag;
	short	short_transducer_depth;
	short	short_altitude;
	int	header_length;
	char	buffer[MBLGPL_FBT_COMMENTSIZE];
	int	index;
	double	newdepthscale;
	double	depthmax;
	int	time_i[7], time_j[6];
	int	version;
	int	i;

	/* print input debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> called\n",
			function_name);
		fprintf(stderr,"dbg2  Input arguments:\n");
		fprintf(stderr,"dbg2       verbose:    %d\n",verbose);
		fprintf(stderr,"dbg2       fp:         %p\n",fp);
		fprintf(stderr,"dbg2       store:      %p\n",store);
		}

	/* read next header id from file */
	if ((status = fread(buffer,1,2,fp)) == 2)
		{
		status = MBLGPL_SUCCESS;
		*error = MBLGPL_ERROR_NO_ERROR;
		}
	else
		{
		status = MBLGPL_FAILURE;
		*error = MBLGPL_ERROR_EOF;
		}

	/* read rest of header from file */
	if (status == MBLGPL_SUCCESS)
		{
		flag = (short *) buffer;
		if (*flag == MBLGPL_FBT_ID_V4DATA)
			{
			store->kind = MBLGPL_DATA_DATA;
			header_length = MBLGPL_FBT_V4HEADERSIZE;
			version = 4;
			}
		else if (*flag == MBLGPL_FBT_ID_COMMENT2)
			{
			store->kind = MBLGPL_DATA_COMMENT;
			header_length = 2;
			}
		else if (*flag == MBLGPL_FBT_ID_V3DATA)
			{
			store->kind = MBLGPL_DATA_DATA;
			header_length = MBLGPL_FBT_V3HEADERSIZE;
			version = 3;
			}
		else if (*flag == MBLGPL_FBT_ID_V2DATA)
			{
			store->kind = MBLGPL_DATA_DATA;
			header_length = MBLGPL_FBT_V2HEADERSIZE;
			version = 2;
			}
		else if (*flag == MBLGPL_FBT_ID_V1DATA)
			{
			store->kind = MBLGPL_DATA_DATA;
			header_length = MBLGPL_FBT_V1HEADERSIZE;
			version = 1;
			}
		else if (*flag == MBLGPL_FBT_ID_COMMENT1)
			{
			store->kind = MBLGPL_DATA_COMMENT;
			header_length = MBLGPL_FBT_V1HEADERSIZE;
			}
		else
			{
			status = MBLGPL_FAILURE;
			*error = MBLGPL_ERROR_UNINTELLIGIBLE;
			store->kind = MBLGPL_DATA_NONE;
			}
		}
	if (status == MBLGPL_SUCCESS
	    && header_length == 2)
		{
		/* only 2 byte header for new style comment */
		status = MBLGPL_SUCCESS;
		*error = MBLGPL_ERROR_NO_ERROR;
		}
	else if (status == MBLGPL_SUCCESS
	    && (status = fread(&buffer[2],1,header_length-2,
			fp)) == header_length-2)
		{
		status = MBLGPL_SUCCESS;
		*error = MBLGPL_ERROR_NO_ERROR;
		}
	else
		{
		status = MBLGPL_FAILURE;
		*error = MBLGPL_ERROR_EOF;
		}

	if (status == MBLGPL_SUCCESS && store->kind == MBLGPL_DATA_DATA)
		{
		if (version == 4)
			{
			index = 2;
			mblgpl_get_binary_double(MBLGPL_NO, (void *)  &buffer[index], &store->time_d); index +=8;
			mblgpl_get_binary_double(MBLGPL_NO, (void *)  &buffer[index], &store->longitude); index +=8;
			mblgpl_get_binary_double(MBLGPL_NO, (void *)  &buffer[index], &store->latitude); index +=8;
			mblgpl_get_binary_double(MBLGPL_NO, (void *)  &buffer[index], &store->sonardepth); index +=8;
			mblgpl_get_binary_double(MBLGPL_NO, (void *)  &buffer[index], &store->altitude); index +=8;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->heading); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->speed); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->roll); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->pitch); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->heave); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->beam_xwidth); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->beam_lwidth); index +=4;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &store->beams_bath); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &store->beams_amp); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &store->pixels_ss); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &store->spare1); index +=2;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->depth_scale); index +=4;
			mblgpl_get_binary_float(MBLGPL_NO, (void *)  &buffer[index], &store->distance_scale); index +=4;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &store->ss_type); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &store->spare2); index +=2;
			}
		else
			{
			index = 2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.year); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.day); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.min); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.sec); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.msec); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.lon2u); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.lon2b); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.lat2u); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.lat2b); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.heading); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.speed); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.beams_bath); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.beams_amp); index +=2;
			mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.pixels_ss); index +=2;
			if (version == 1)
				{
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.depth_scale); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.distance_scale); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &short_transducer_depth); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &short_altitude); index +=2;
				oldstore.transducer_depth = (int) (oldstore.depth_scale * short_transducer_depth);
				oldstore.altitude = (int) (oldstore.depth_scale * short_altitude);
				}
			else if (version == 2)
				{
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.depth_scale); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.distance_scale); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &short_transducer_depth); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &short_altitude); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.beam_xwidth); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.beam_lwidth); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.ss_type); index +=2;
				oldstore.transducer_depth = (int) (oldstore.depth_scale * short_transducer_depth);
				oldstore.altitude = (int) (oldstore.depth_scale * short_altitude);
				}
			else if (version == 3)
				{
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.depth_scale); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.distance_scale); index +=2;
				mblgpl_get_binary_int(MBLGPL_NO, (void *)  &buffer[index], &oldstore.transducer_depth); index +=4;
				mblgpl_get_binary_int(MBLGPL_NO, (void *)  &buffer[index], &oldstore.altitude); index +=4;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.beam_xwidth); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.beam_lwidth); index +=2;
				mblgpl_get_binary_short(MBLGPL_NO, (void *)  &buffer[index], &oldstore.ss_type); index +=2;
				}

			/* translate old data to current */

			/* get time */
			time_j[0] = oldstore.year;
			time_j[1] = oldstore.day;
			time_j[2] = oldstore.min;
			time_j[3] = oldstore.sec;
			time_j[4] = 1000 * oldstore.msec;
			mblgpl_get_itime(verbose,time_j,time_i);
			mblgpl_get_time(verbose,time_i,&store->time_d);

			/* get navigation */
			store->longitude = ((double) oldstore.lon2u)/60.
						+ ((double) oldstore.lon2b)/600000.;
			store->latitude = ((double) oldstore.lat2u)/60.
						+ ((double) oldstore.lat2b)/600000. - 90.;

			/* get sonardepth and altitude */
			store->sonardepth = 0.001 * oldstore.transducer_depth;
		    	store->altitude = 0.001 * oldstore.altitude;

			/* get heading (360 degrees = 65536) and speed */
			store->heading = (float) (0.0054932 * oldstore.heading);
			store->speed = (float)(0.01 * oldstore.speed);

			/* set roll and pitch to zero */
			store->roll = 0.0;
			store->pitch = 0.0;

			/* set beamwidths in mb_io structure */
			if (oldstore.beam_xwidth > 0)
			    store->beam_xwidth = 0.01 * oldstore.beam_xwidth;
			else
			    store->beam_xwidth = 2.0;
			if (oldstore.beam_lwidth > 0)
			    store->beam_lwidth = 0.01 * oldstore.beam_lwidth;
			else
			    store->beam_lwidth = 2.0;

			/* get beams_bath, beams_amp, pixels_ss */
			store->beams_bath = oldstore.beams_bath;
			store->beams_amp = oldstore.beams_amp;
			store->pixels_ss = oldstore.pixels_ss;
			store->spare1 = 0;

			/* get scaling */
			store->depth_scale = 0.001 * oldstore.depth_scale;
			store->distance_scale = 0.001 * oldstore.distance_scale;

			/* get sidescan type */
			store->ss_type = oldstore.ss_type;
			store->spare2 = 0;
			}
		}

	/* print debug statements */
	if (verbose >= 5)
		{
		fprintf(stderr,"\ndbg5  New header read in function <%s>\n",
			function_name);
		fprintf(stderr,"dbg5       flag:       %d\n",*flag);
		}
	if (verbose >= 5 && store->kind == MBLGPL_DATA_DATA && version < 4)
		{
		fprintf(stderr,"\ndbg5  Old version header read in function <%s>\n",function_name);
		fprintf(stderr,"dbg5       version:          %d\n",version);
		fprintf(stderr,"dbg5       year:             %d\n",oldstore.year);
		fprintf(stderr,"dbg5       day:              %d\n",oldstore.day);
		fprintf(stderr,"dbg5       minute:           %d\n",oldstore.min);
		fprintf(stderr,"dbg5       second:           %d\n",oldstore.sec);
		fprintf(stderr,"dbg5       msec:             %d\n",oldstore.msec);
		fprintf(stderr,"dbg5       lonu:             %d\n",oldstore.lon2u);
		fprintf(stderr,"dbg5       lonb:             %d\n",oldstore.lon2b);
		fprintf(stderr,"dbg5       latu:             %d\n",oldstore.lat2u);
		fprintf(stderr,"dbg5       latb:             %d\n",oldstore.lat2b);
		fprintf(stderr,"dbg5       heading:          %d\n",oldstore.heading);
		fprintf(stderr,"dbg5       speed:            %d\n",oldstore.speed);
		fprintf(stderr,"dbg5       beams bath:       %d\n",oldstore.beams_bath);
		fprintf(stderr,"dbg5       beams amp:        %d\n",oldstore.beams_amp);
		fprintf(stderr,"dbg5       pixels ss:        %d\n",oldstore.pixels_ss);
		fprintf(stderr,"dbg5       depth scale:      %d\n",oldstore.depth_scale);
		fprintf(stderr,"dbg5       dist scale:       %d\n",oldstore.distance_scale);
		fprintf(stderr,"dbg5       transducer_depth: %d\n",oldstore.transducer_depth);
		fprintf(stderr,"dbg5       altitude:         %d\n",oldstore.altitude);
		fprintf(stderr,"dbg5       beam_xwidth:      %d\n",oldstore.beam_xwidth);
		fprintf(stderr,"dbg5       beam_lwidth:      %d\n",oldstore.beam_lwidth);
		fprintf(stderr,"dbg5       ss_type:          %d\n",oldstore.ss_type);
		fprintf(stderr,"dbg5       status:           %d\n",status);
		fprintf(stderr,"dbg5       error:            %d\n",*error);
		}
	if (verbose >= 5 && store->kind == MBLGPL_DATA_DATA)
		{
		fprintf(stderr,"\ndbg5  Current version header values in function <%s>\n",function_name);
		fprintf(stderr,"dbg5       time_d:           %f\n",store->time_d);
		fprintf(stderr,"dbg5       longitude:        %f\n",store->longitude);
		fprintf(stderr,"dbg5       latitude:         %f\n",store->latitude);
		fprintf(stderr,"dbg5       sonardepth:       %f\n",store->sonardepth);
		fprintf(stderr,"dbg5       altitude:         %f\n",store->altitude);
		fprintf(stderr,"dbg5       heading:          %f\n",store->heading);
		fprintf(stderr,"dbg5       speed:            %f\n",store->speed);
		fprintf(stderr,"dbg5       roll:             %f\n",store->roll);
		fprintf(stderr,"dbg5       pitch:            %f\n",store->pitch);
		fprintf(stderr,"dbg5       heave:            %f\n",store->heave);
		fprintf(stderr,"dbg5       beam_xwidth:      %f\n",store->beam_xwidth);
		fprintf(stderr,"dbg5       beam_lwidth:      %f\n",store->beam_lwidth);
		fprintf(stderr,"dbg5       beams_bath:       %d\n",store->beams_bath);
		fprintf(stderr,"dbg5       beams_amp:        %d\n",store->beams_amp);
		fprintf(stderr,"dbg5       pixels_ss:        %d\n",store->pixels_ss);
		fprintf(stderr,"dbg5       spare1:           %d\n",store->spare1);
		fprintf(stderr,"dbg5       depth_scale:      %f\n",store->depth_scale);
		fprintf(stderr,"dbg5       distance_scale:   %f\n",store->distance_scale);
		fprintf(stderr,"dbg5       ss_type:          %d\n",store->ss_type);
		fprintf(stderr,"dbg5       spare2:           %d\n",store->spare2);
		fprintf(stderr,"dbg5       status:           %d\n",status);
		fprintf(stderr,"dbg5       error:            %d\n",*error);
		}

	/* read next chunk of the data */
	if (status == MBLGPL_SUCCESS
		&& store->kind == MBLGPL_DATA_COMMENT)
		{
		read_size = MBLGPL_FBT_COMMENTSIZE;
		if ((status = fread(store->comment,1,read_size,fp))
			== read_size)
			{
			status = MBLGPL_SUCCESS;
			*error = MBLGPL_ERROR_NO_ERROR;
			}
		else
			{
			status = MBLGPL_FAILURE;
			*error = MBLGPL_ERROR_EOF;
			}

		/* print debug messages */
		if (verbose >= 5 && status == MBLGPL_SUCCESS)
			{
			fprintf(stderr,"\ndbg5  New comment read in function <%s>\n",
				function_name);
			fprintf(stderr,"dbg5       comment: %s\n",store->comment);
			}
		}
	else if (status == MBLGPL_SUCCESS
		&& store->kind == MBLGPL_DATA_DATA)
		{
		/* if needed reset numbers of beams and allocate
		   memory for store arrays */
		if (store->beams_bath > store->beams_bath_alloc)
		    {
		    store->beams_bath_alloc = store->beams_bath;
		    if (store->beamflag != NULL)
			status = mblgpl_free(verbose, &store->beamflag, error);
		    if (store->bath != NULL)
			status = mblgpl_free(verbose, &store->bath, error);
		    if (store->bath_acrosstrack != NULL)
			status = mblgpl_free(verbose, &store->bath_acrosstrack, error);
		    if (store->bath_alongtrack != NULL)
			status = mblgpl_free(verbose, &store->bath_alongtrack, error);
		    status = mblgpl_malloc(verbose,
				store->beams_bath_alloc * sizeof(char),
				&store->beamflag,error);
		    status = mblgpl_malloc(verbose,
				store->beams_bath_alloc * sizeof(short),
				&store->bath,error);
		    status = mblgpl_malloc(verbose,
				store->beams_bath_alloc * sizeof(short),
				&store->bath_acrosstrack,error);
		    status = mblgpl_malloc(verbose,
				store->beams_bath_alloc * sizeof(short),
				&store->bath_alongtrack,error);

		    /* deal with a memory allocation failure */
		    if (status == MBLGPL_FAILURE)
			{
			status = mblgpl_free(verbose, &store->beamflag, error);
			status = mblgpl_free(verbose, &store->bath, error);
			status = mblgpl_free(verbose, &store->bath_acrosstrack, error);
			status = mblgpl_free(verbose, &store->bath_alongtrack, error);
			status = MBLGPL_FAILURE;
			*error = MBLGPL_ERROR_MEMORY_FAIL;
			if (verbose >= 2)
				{
				fprintf(stderr,"\ndbg2  MBLGPL function <%s> terminated with error\n",
					function_name);
				fprintf(stderr,"dbg2  Return values:\n");
				fprintf(stderr,"dbg2       error:      %d\n",*error);
				fprintf(stderr,"dbg2  Return status:\n");
				fprintf(stderr,"dbg2       status:  %d\n",status);
				}
			return(status);
			}
		    }
		if (store->beams_amp > store->beams_amp_alloc)
		    {
		    store->beams_amp_alloc = store->beams_amp;
		    if (store->amp != NULL)
			status = mblgpl_free(verbose, &store->amp, error);
		    status = mblgpl_malloc(verbose,
				store->beams_amp_alloc * sizeof(short),
				&store->amp,error);

		    /* deal with a memory allocation failure */
		    if (status == MBLGPL_FAILURE)
			{
			status = mblgpl_free(verbose, &store->amp, error);
			status = MBLGPL_FAILURE;
			*error = MBLGPL_ERROR_MEMORY_FAIL;
			if (verbose >= 2)
				{
				fprintf(stderr,"\ndbg2  MBLGPL function <%s> terminated with error\n",
					function_name);
				fprintf(stderr,"dbg2  Return values:\n");
				fprintf(stderr,"dbg2       error:      %d\n",*error);
				fprintf(stderr,"dbg2  Return status:\n");
				fprintf(stderr,"dbg2       status:  %d\n",status);
				}
			return(status);
			}
		    }
		if (store->pixels_ss > store->pixels_ss_alloc)
		    {
		    store->pixels_ss_alloc = store->pixels_ss;
		    if (store->ss != NULL)
			status = mblgpl_free(verbose, &store->ss, error);
		    if (store->ss_acrosstrack != NULL)
			status = mblgpl_free(verbose, &store->ss_acrosstrack, error);
		    if (store->ss_alongtrack != NULL)
			status = mblgpl_free(verbose, &store->ss_alongtrack, error);
		    status = mblgpl_malloc(verbose,
				store->pixels_ss_alloc * sizeof(short),
				&store->ss,error);
		    status = mblgpl_malloc(verbose,
				store->pixels_ss_alloc * sizeof(short),
				&store->ss_acrosstrack,error);
		    status = mblgpl_malloc(verbose,
				store->pixels_ss_alloc * sizeof(short),
				&store->ss_alongtrack,error);

		    /* deal with a memory allocation failure */
		    if (status == MBLGPL_FAILURE)
			{
			status = mblgpl_free(verbose, &store->ss, error);
			status = mblgpl_free(verbose, &store->ss_acrosstrack, error);
			status = mblgpl_free(verbose, &store->ss_alongtrack, error);
			status = MBLGPL_FAILURE;
			*error = MBLGPL_ERROR_MEMORY_FAIL;
			if (verbose >= 2)
				{
				fprintf(stderr,"\ndbg2  MBLGPL function <%s> terminated with error\n",
					function_name);
				fprintf(stderr,"dbg2  Return values:\n");
				fprintf(stderr,"dbg2       error:      %d\n",*error);
				fprintf(stderr,"dbg2  Return status:\n");
				fprintf(stderr,"dbg2       status:  %d\n",status);
				}
			return(status);
			}
		    }

		/* read bathymetry */
		read_size = sizeof(char)*store->beams_bath;
		status = fread(store->beamflag,1,read_size,fp);
		read_size = sizeof(short int)*store->beams_bath;
		status = fread(store->bath,1,read_size,fp);
		status = fread(store->bath_acrosstrack,1,read_size,fp);
		status = fread(store->bath_alongtrack,1,read_size,fp);

		/* read amplitudes */
		read_size = sizeof(short int)*store->beams_amp;
		status = fread(store->amp,1,read_size,fp);

		/* read sidescan */
		read_size = sizeof(short int)*store->pixels_ss;
		status = fread(store->ss,1,read_size,fp);
		status = fread(store->ss_acrosstrack,1,read_size,fp);
		status = fread(store->ss_alongtrack,1,read_size,fp);

		/* byte swap the data if necessary */
#ifdef BYTESWAPPED
		for (i=0;i<store->beams_bath;i++)
			{
			store->bath[i] = mblgpl_swap_short(store->bath[i]);
			store->bath_acrosstrack[i]
				= mblgpl_swap_short(store->bath_acrosstrack[i]);
			store->bath_alongtrack[i]
				= mblgpl_swap_short(store->bath_alongtrack[i]);
			}
		for (i=0;i<store->beams_amp;i++)
			{
			store->amp[i] = mblgpl_swap_short(store->amp[i]);
			}
		for (i=0;i<store->pixels_ss;i++)
			{
			store->ss[i] = mblgpl_swap_short(store->ss[i]);
			store->ss_acrosstrack[i]
				= mblgpl_swap_short(store->ss_acrosstrack[i]);
			store->ss_alongtrack[i]
				= mblgpl_swap_short(store->ss_alongtrack[i]);
			}
#endif

		/* subtract the transducer depth from the bathymetry if version
			1 or 2 data has been read */
		if (version < 3)
			{
			depthmax = 0.0;
			for (i=0;i<store->beams_bath;i++)
				{
				depthmax = MAX(depthmax, (store->depth_scale * store->bath[i] - store->sonardepth));
				}
			if (depthmax > 0.0)
				newdepthscale = 0.001 * (double)(MAX((int) (1 + depthmax / 30.0), 1));
			for (i=0;i<store->beams_bath;i++)
				{
				store->bath[i] = (short)((store->depth_scale * store->bath[i] - store->sonardepth) / newdepthscale);
				}
			store->depth_scale = newdepthscale;
			}

		/* check for end of file */
		if (status == read_size)
			{
			status = MBLGPL_SUCCESS;
			*error = MBLGPL_ERROR_NO_ERROR;
			}
		else
			{
			status = MBLGPL_FAILURE;
			*error = MBLGPL_ERROR_EOF;
			}

		/* print debug messages */
		if (verbose >= 5 && status == MBLGPL_SUCCESS)
			{
			fprintf(stderr,"\ndbg5  New data read in function <%s>\n",
				function_name);
			fprintf(stderr,"dbg5       beams_bath: %d\n",
				store->beams_bath);
			for (i=0;i<store->beams_bath;i++)
			  fprintf(stderr,"dbg5       beam:%d  flag:%d  bath:%d  acrosstrack:%d  alongtrack:%d\n",
				i,store->beamflag[i],store->bath[i],
				store->bath_acrosstrack[i],store->bath_alongtrack[i]);
			fprintf(stderr,"dbg5       beams_amp:  %d\n",
				store->beams_amp);
			for (i=0;i<store->beams_amp;i++)
			  fprintf(stderr,"dbg5       beam:%d  flag:%d  amp:%d  acrosstrack:%d  alongtrack:%d\n",
				i,store->beamflag[i],store->amp[i],
				store->bath_acrosstrack[i],store->bath_alongtrack[i]);
			fprintf(stderr,"dbg5       pixels_ss:  %d\n",
				store->pixels_ss);
			  fprintf(stderr,"dbg5       pixel:%d  ss:%d acrosstrack:%d  alongtrack:%d\n",
				i,store->ss[i],
				store->ss_acrosstrack[i],store->ss_alongtrack[i]);
			}
		}

	/* print output debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> completed\n",
			function_name);
		fprintf(stderr,"dbg2  Return values:\n");
		fprintf(stderr,"dbg2       error:      %d\n",*error);
		fprintf(stderr,"dbg2  Return status:\n");
		fprintf(stderr,"dbg2       status:  %d\n",status);
		}

	/* return status */
	return(status);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_get_binary_short copies a binary short from
 *	a buffer, swapping if necessary
 */
int mblgpl_get_binary_short(int swapped, void *buffer, short *value)
{
	memcpy(value, buffer, sizeof(short));
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    *value = mblgpl_swap_short(*value);
#else
	if (swapped == MBLGPL_YES)
	    *value = mblgpl_swap_short(*value);
#endif
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_get_binary_int copies a binary int from
 *	a buffer, swapping if necessary
 */
int mblgpl_get_binary_int(int swapped, void *buffer, int *value)
{
	memcpy(value, buffer, sizeof(int));
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    *value = mblgpl_swap_int(*value);
#else
	if (swapped == MBLGPL_YES)
	    *value = mblgpl_swap_int(*value);
#endif
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_get_binary_float copies a binary float from
 *	a buffer, swapping if necessary
 */
int mblgpl_get_binary_float(int swapped, void *buffer, float *value)
{
	memcpy(value, buffer, sizeof(float));
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    mblgpl_swap_float(value);
#else
	if (swapped == MBLGPL_YES)
	    mblgpl_swap_float(value);
#endif
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_get_binary_double copies a binary double from
 *	a buffer, swapping if necessary
 */
int mblgpl_get_binary_double(int swapped, void *buffer, double *value)
{
	memcpy(value, buffer, sizeof(double));
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    mblgpl_swap_double(value);
#else
	if (swapped == MBLGPL_YES)
	    mblgpl_swap_double(value);
#endif
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_put_binary_short copies a binary short to
 *	a buffer, swapping if necessary
 */
int mblgpl_put_binary_short(int swapped, short value, void *buffer)
{
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    value = mblgpl_swap_short(value);
#else
	if (swapped == MBLGPL_YES)
	    value = mblgpl_swap_short(value);
#endif
	memcpy(buffer, &value, sizeof(short));
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_put_binary_int copies a binary int to
 *	a buffer, swapping if necessary
 */
int mblgpl_put_binary_int(int swapped, int value, void *buffer)
{
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    value = mblgpl_swap_int(value);
#else
	if (swapped == MBLGPL_YES)
	    value = mblgpl_swap_int(value);
#endif
	memcpy(buffer, &value, sizeof(int));
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_put_binary_float copies a binary float to
 *	a buffer, swapping if necessary
 */
int mblgpl_put_binary_float(int swapped, float value, void *buffer)
{
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    mblgpl_swap_float(&value);
#else
	if (swapped == MBLGPL_YES)
	    mblgpl_swap_float(&value);
#endif
	memcpy(buffer, &value, sizeof(float));
	return(0);
}
/*--------------------------------------------------------------------*/
/*	function mblgpl_put_binary_double copies a binary double to
 *	a buffer, swapping if necessary
 */
int mblgpl_put_binary_double(int swapped, double value, void *buffer)
{
#ifdef BYTESWAPPED
	if (swapped == MBLGPL_NO)
	    mblgpl_swap_double(&value);
#else
	if (swapped == MBLGPL_YES)
	    mblgpl_swap_double(&value);
#endif
	memcpy(buffer, &value, sizeof(double));
	return(0);
}
/*--------------------------------------------------------------------*/
int mblgpl_malloc(int verbose, size_t size, void **ptr, int *error)
{
	char	*function_name = "mblgpl_malloc";
	int	status = MBLGPL_SUCCESS;

	/* print input debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> called\n",
			function_name);
		fprintf(stderr,"dbg2  Input arguments:\n");
		fprintf(stderr,"dbg2       verbose:    %d\n",verbose);
		fprintf(stderr,"dbg2       size:       %lu\n",size);
		fprintf(stderr,"dbg2       ptr:        %p\n",ptr);
		fprintf(stderr,"dbg2       *ptr:       %p\n",*ptr);
		}

	/* allocate memory */
	*ptr = NULL;
	if (size > 0)
		{
		if ((*ptr = (void *) malloc(size)) == NULL)
			{
			*error = MBLGPL_ERROR_MEMORY_FAIL;
			status = MBLGPL_FAILURE;
			}
		else
			{
			*error = MBLGPL_ERROR_NO_ERROR;
			status = MBLGPL_SUCCESS;
			}
		}
	else
		{
		*ptr = NULL;
		*error = MBLGPL_ERROR_NO_ERROR;
		status = MBLGPL_SUCCESS;
		}

	/* print output debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> completed\n",
			function_name);
		fprintf(stderr,"dbg2  Return values:\n");
		fprintf(stderr,"dbg2       ptr:        %p\n",*ptr);
		fprintf(stderr,"dbg2       error:      %d\n",*error);
		fprintf(stderr,"dbg2  Return status:\n");
		fprintf(stderr,"dbg2       status:  %d\n",status);
		}

	/* return status */
	return(status);
}
/*--------------------------------------------------------------------*/
int mblgpl_free(int verbose, void **ptr, int *error)
{
	char	*function_name = "mblgpl_free";
	int	status = MBLGPL_SUCCESS;

	/* print input debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> called\n",
			function_name);
		fprintf(stderr,"dbg2  Input arguments:\n");
		fprintf(stderr,"dbg2       verbose:    %d\n",verbose);
		fprintf(stderr,"dbg2       ptr:        %p\n",*ptr);
		}

	/* deallocate the memory if *ptr is not NULL */
	if (*ptr != NULL)
		{
		/* free the memory */
		free(*ptr);
		*ptr = NULL;
		}

	/* assume success */
	*error = MBLGPL_ERROR_NO_ERROR;
	status = MBLGPL_SUCCESS;

	/* print output debug statements */
	if (verbose >= 2)
		{
		fprintf(stderr,"\ndbg2  MBLGPL function <%s> completed\n",
			function_name);
		fprintf(stderr,"dbg2  Return value:\n");
		fprintf(stderr,"dbg2       ptr:        %p\n",*ptr);
		fprintf(stderr,"dbg2       error:      %d\n",*error);
		fprintf(stderr,"dbg2  Return status:\n");
		fprintf(stderr,"dbg2       status:     %d\n",status);
		}

	/* return status */
	return(status);
}
/*--------------------------------------------------------------------*/
