/**********************************************************************
 
  igbhead - program to display and remove/modify/create IGB headers

  usage igbhead [options] file

  author: Edward Vigmond

 **********************************************************************/
#include<cstdio>
#include<string>
#include "IGBheader.h"
#include "cmdline.h"
using namespace std;

void output_header( IGBheader* );

main( int argc, char* argv[] )
{
  gengetopt_args_info args_info;

  // let's call our cmdline parser 
  if (cmdline_parser (argc, argv, &args_info) != 0)
     exit(1);

  if( argc == 1 || args_info.inputs_num != 1 ) {
	cerr << "\nigbhead [OPTIONS] file" << endl;
	cerr << "\tadd, edit or remove igb headers" << endl;
	cerr << "\trun igbhead --help to see options" << endl << endl;
	exit(0);
  }

  // the last arg must be a file name
  gzFile in = gzopen( args_info.inputs[0], "r" );
  if( in == NULL ) {
	  cerr << "File not found: " << args_info.inputs[0] << endl;
	  exit(1);
  }
  IGBheader* header= new IGBheader( in );
  if( header->read() == 0 ) gzrewind( in );

  // just output the current header
  if( argc==2 ) {
	output_header( header );
	gzclose( in );
	exit(0);
  }

  if( args_info.x_given ) header->x( args_info.x_arg );
  if( args_info.y_given ) header->y( args_info.y_arg );
  if( args_info.z_given ) header->z( args_info.z_arg );
  if( args_info.t_given ) header->t( args_info.t_arg );
  if( args_info.data_type_given ) header->type( args_info.data_type_arg );
  if( args_info.system_given ) header->systeme( args_info.system_arg );
  if( args_info.dim_x_given ) header->dim_x( args_info.dim_x_arg );
  if( args_info.dim_y_given ) header->dim_y( args_info.dim_y_arg );
  if( args_info.dim_z_given ) header->dim_z( args_info.dim_z_arg );
  if( args_info.dim_t_given ) header->dim_t( args_info.dim_t_arg );
  if( args_info.fac_x_given ) header->fac_x( args_info.fac_x_arg );
  if( args_info.fac_y_given ) header->fac_y( args_info.fac_y_arg );
  if( args_info.fac_z_given ) header->fac_z( args_info.fac_z_arg );
  if( args_info.fac_t_given ) header->fac_t( args_info.fac_t_arg );
  if( args_info.org_x_given ) header->org_x( args_info.org_x_arg );
  if( args_info.org_y_given ) header->org_y( args_info.org_y_arg );
  if( args_info.org_z_given ) header->org_z( args_info.org_z_arg );
  if( args_info.org_t_given ) header->org_t( args_info.org_t_arg );
  if( args_info.inc_x_given ) header->inc_x( args_info.inc_x_arg );
  if( args_info.inc_y_given ) header->inc_y( args_info.inc_y_arg );
  if( args_info.inc_z_given ) header->inc_z( args_info.inc_z_arg );
  if( args_info.inc_t_given ) header->inc_t( args_info.inc_t_arg );
  if( args_info.x_units_given ) header->unites_x( args_info.x_units_arg );
  if( args_info.y_units_given ) header->unites_y( args_info.y_units_arg );
  if( args_info.z_units_given ) header->unites_z( args_info.z_units_arg );
  if( args_info.t_units_given ) header->unites_t( args_info.t_units_arg );
  if( args_info.clear_comment_given ) header->comment(NULL);
  if( args_info.comment_given ) header->comment( args_info.comment_arg );
  if( args_info.data_factor_given ) header->facteur( args_info.data_factor_arg );
  if( args_info.data_zero_given ) header->zero( args_info.data_zero_arg );
  if( args_info.author_given ) header->aut_name( args_info.author_arg );
  if( args_info.transparent_given ){
		if( strlen(args_info.transparent_arg)!=2*Data_Size[header->type()] ){
		  cerr << "Incorrect tranparent value specified\n";
		  exit(1);
		} 
		// convert hex digits to bytes
		char* v = new char[Data_Size[header->type()]];
		char s[3], *pp;
		s[2] = '\0';
		for( int i=0; i<Data_Size[header->type()]; i++ ){
		  s[0] = args_info.transparent_arg[i*2];
		  s[1] = args_info.transparent_arg[i*2+1];
		  v[i] = strtol( s, &pp, 16 );
		}
		header->transparent( v );
  }
  if( args_info.no_transparent_given ) header->transparent( NULL );
  
  // count the number of data bytes 
  if( args_info.jive_time_given ) {
	z_off_t zo = gztell( in );
	const int bufsize=8196;
	char buff[bufsize];
	long nb=0, nr;
	while( (nr=gzread( in, buff, bufsize )) == bufsize )
	  nb += nr;
	nb += nr;
	header->t( float(nb)/header->x()/header->y()/header->z() );	
	gzseek( in, zo, SEEK_SET );
  }

  // make a temporary file
  string tmpfn = ".";
  tmpfn += args_info.inputs[0];
  tmpfn += ".tmp";
 
  // determine output file and if it is compressed
  bool compressed=false;
  string ofn;
  if( args_info.frankenstein_given ){
	  ofn = args_info.frankenstein_arg;
	  gzclose( in );
	  IGBheader *h = new IGBheader(in=gzopen( args_info.frankenstein_arg,"r" ));
	  if( h->read() == 0 ) gzrewind( in );
	  h->~IGBheader();
  } else
	  ofn = args_info.inputs[0]; 
  if(args_info.output_file_given)
	  ofn = args_info.output_file_arg;
  if( ofn.rfind(".gz") == ofn.length()-3 ) compressed=true;
	  
  gzFile gzout;
  FILE* fout;
  if( compressed )
	header->fileptr(gzout = gzopen( tmpfn.c_str(), "w" ) );
  else
	header->fileptr(fout= fopen( tmpfn.c_str(), "w" ) );

  if( !args_info.decapitate_given ) header->write();

  const int bufsize=1024;
  char buf[bufsize];
  int nb;
  if( compressed ){
	while( (nb=gzread( in, buf, bufsize )) > 0 ) gzwrite( gzout, buf, nb );
	gzclose( gzout );
  } else {
	while( (nb=gzread( in, buf, bufsize )) > 0 ) fwrite(buf, nb, 1, fout);
	fclose( fout );
  }
  gzclose( in );
  rename(  tmpfn.c_str(), ofn.c_str() );
}

void output_header( IGBheader* header )
{
	bool tf;
    printf( "x dimension:\t%d\n", header->x() );
    printf( "y dimension:\t%d\n", header->y() );
    printf( "z dimension:\t%d\n", header->z() );
    printf( "t dimension:\t%d\n", header->t() );
    printf( "data type:\t%s\n", Header_Type[header->type()] );
    header->unites(tf);
	if( tf == true ) {
        printf( "Pixel units:\t%s\n", header->unites() );
  	}
	if( header->transparent() != NULL ) {
        printf( "Transparent:\t%s\n", header->transparentstr() );
	}
    header->zero(tf);
	if( tf == true ) {
        printf( "Pixel zero:\t%g\n", header->zero() );
    }
    header->unites(tf);
	if( tf == true ) {
        printf( "Pixel scaling:\t%g\n", header->facteur() );
    }
    header->dim_x(tf);
	if( tf == true ) {
        printf( "X size:\t\t%g\n", header->dim_x() );
    }
    header->unites_x(tf);
	if( tf == true ) {
        printf( "X units:\t%s\n", header->unites_x() );
    }
    header->inc_x(tf);
	if( tf == true ) {
        printf( "Increment in x:\t%g\n", header->inc_x() );
    }
    header->org_x(tf);
	if( tf == true ) {
        printf( "X origin:\t%g\n", header->org_x() );
    }
    header->fac_x(tf);
	if( tf == true ) {
        printf( "X scale factor:\t%g\n", header->fac_x() );
    }
    header->dim_y(tf);
	if( tf == true ) {
        printf( "Y size:\t\t%g\n", header->dim_y() );
    }
    header->unites_y(tf);
	if( tf == true ) {
        printf( "Y units:\t%s\n", header->unites_y() );
    }
    header->inc_y(tf);
	if( tf == true ) {
        printf( "Increment in y:\t%g\n", header->inc_y() );
    }
    header->org_y(tf);
	if( tf == true ) {
        printf( "Y origin:\t%g\n", header->org_y() );
    }
    header->fac_y(tf);
	if( tf == true ) {
  		printf( "Y scale factor:\t%s\n\n", header->fac_y() );
    }
    header->dim_z(tf);
	if( tf == true ) {
        printf( "Z size:\t\t%g\n", header->dim_z() );
    }
    header->unites_z(tf);
	if( tf == true ) {
        printf( "Z units:\t%s\n", header->unites_z() );
    }
    header->inc_z(tf);
	if( tf == true ) {
        printf( "Increment in z:\t%g\n", header->inc_z() );
    }
    header->org_z(tf);
	if( tf == true ) {
        printf( "Z origin:\t%g\n", header->org_z() );
    }
    header->fac_z(tf);
	if( tf == true ) {
        printf( "Z scale factor:\t%g\n", header->fac_z() );
    }
    header->dim_t(tf);
	if( tf == true ) {
        printf( "T size:\t\t%g\n", header->dim_t() );
    }
	header->unites_t(tf);
	if( tf == true ) {
        printf( "T units:\t%s\n", header->unites_t() );
    }
    header->inc_t(tf);
	if( tf == true ) {
        printf( "Increment in t:\t%g\n", header->inc_t() );
    }
    header->org_t(tf);
	if( tf == true ) {
        printf( "T origin:\t%g\n", header->org_t() );
    }
    header->fac_t(tf);
	if( tf == true ) {
        printf( "T scale factor:\t%g\n", header->fac_t() );
    }
	printf( "Created on:\t%s\n", header->systemestr());
    header->aut_name(tf);
	if( tf == true ) {
        printf( "Author:\t\t%s\n", header->aut_name() );
    }
	if( header->comment() != NULL ){
	  	char **cm = header->comment();
		int i=0;
		while( cm[i] != NULL )
        	printf( "#%s\n", cm[i++] );
    }
}


syntax highlighted by Code2HTML, v. 0.9.1