Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

file_tool.c

Go to the documentation of this file.
00001 
00002 #define VERSION         "3.2a (March 22, 2005)"
00003 
00004 /*----------------------------------------------------------------------
00005  * file_tool.c  - display or modify (binary?) info in files
00006  *
00007  * This is a pretty generic file processing tool, originally designed
00008  * to display and modify data at random places in files, and also to
00009  * deal with GEMS 5.x image files (e.g. being able to replace subject
00010  * names with 'x's).
00011  *
00012  * options:
00013  *
00014  *     special options:
00015  *
00016  *        -help                display help
00017  *        -help_ge             display help on GE info structures
00018  *        -hist                display history
00019  *        -debug    LEVEL      show extra info  (0, 1 or 2)
00020  *        -version             show version information
00021  *
00022  *     required 'options':
00023  *
00024  *        -infiles  file1 ...  specify files to display/alter
00025  *
00026  *     GE info options
00027  *
00028  *        -ge_all              display GE header and extras info
00029  *        -ge_header           display GE header info
00030  *        -ge_extras           display extra GE image info
00031  *        -ge_uv17             diplay the value of the uv17 variable
00032  *        -ge_run              diplay the run number - same as uv17
00033  *        -ge_off              diplay file offsets for various fields
00034  *
00035  *     GEMS 4.x options
00036  *
00037  *        -ge4_all             display GEMS 4.x series and image headers
00038  *        -ge4_series          display GEMS 4.x series header
00039  *        -ge4_image           display GEMS 4.x image header
00040  *
00041  *     raw ascii options:
00042  *
00043  *        -length   LENGTH     number of bytes to display/modify
00044  *        -mod_data DATA       specify modification data
00045  *        -mod_type TYPE       specify modification with a value or string
00046  *        -offset   OFFSET     display/modify from OFFSET bytes into files
00047  *        -quiet               do not display header info with output
00048  *
00049  *     numeric options:
00050  *
00051  *        -disp_int2           display data as 2-byte integers
00052  *        -disp_int4           display data as 4-byte integers
00053  *        -disp_real4          display data as 4-byte floats
00054  *        -swap_bytes          use byte swapping for numbers
00055  *
00056  * examples:
00057  * 
00058  *    file_tool -help
00059  *    file_tool -help_ge
00060  *    file_tool -ge_all -infiles I.100
00061  *    file_tool -ge_run -infiles I.?42
00062  *    file_tool -offset 100 -length 32 -infiles file1 file2
00063  *    file_tool -offset 100 -length 32 -quiet -infiles file1 file2
00064  *    file_tool -disp_int2 -swap -offset 1024 -length 16 -infiles file3
00065  *    file_tool -mod_data "hi there" -offset 2515 -length 8 -infiles I.*
00066  *    file_tool -debug 1 -mod_data x -mod_type val -offset 2515 \
00067  *              -length 21 -infiles I.*
00068  *----------------------------------------------------------------------
00069 */
00070 
00071 static char g_history[] = 
00072  "----------------------------------------------------------------------\n"
00073  " file_tool history:\n"
00074  "\n"
00075  " 1.0  September 11, 2002\n"
00076  "   - initial release\n"
00077  "\n"
00078  " 1.1  February 26, 2003\n"
00079  "   - added -quiet option\n"
00080  "   - use dynamic allocation for data to read\n"
00081  "\n"
00082  " 1.2  May 06, 2003  (will go to 2.0 after more changes are made)\n"
00083  "   - added interface for reading GEMS 4.x formatted image files\n"
00084  "   - added corresponding options -ge4_all, -ge4_image, -ge4_series\n"
00085  "   - added options to display raw numeric data:\n"
00086  "       disp_int2, disp_int4, disp_real4\n"
00087  "   - changed local version of l_THD_filesize to THD_filesize, as\n"
00088  "     the ge4_ functions may get that from mrilib.\n"
00089  "\n"
00090  " 2.0  May 29, 2003\n"
00091  "   - added information for ge4 study header\n"
00092  "   - added option -ge4_study\n"
00093  "\n"
00094  " 2.1  June 02, 2003\n"
00095  "   - changed format of call to ge4_read_header()\n"
00096  "   - made swap_[24]() static\n"
00097  "\n"
00098  " 2.2  July 27, 2003\n"
00099  "   - wrap unknown printed strings in NULL check\n"
00100  "\n"
00101  " 3.0  March 17, 2004\n"
00102  "   - added binary editing (gee, that's why I wrote it 18 months ago...)\n"
00103  "     (see -mod_type s/uint1, s/uint2, s/uint4, float4, float8\n"
00104  "   - added '-ge_off' option, to display file offsets for some GEMS fields\n"
00105  "   - added '-hist' option, to display this history\n"
00106  "\n"
00107  " 3.1  March 17, 2004\n"
00108  "   - only check length against data_len for string mods\n"
00109  "\n"
00110  " 3.2  March 24, 2004\n"
00111  "   - only check max length when modifying data (thanks, PSFB)\n"
00112  "\n"
00113  " 3.2a March 22, 2005\n"
00114  "   - removed all tabs\n"
00115  "----------------------------------------------------------------------\n";
00116 
00117 
00118 /* ----------------------------------------------------------------------
00119  * todo:
00120  *
00121  * - add option '-help_ge4'
00122  * ----------------------------------------------------------------------
00123 */
00124 
00125 #include <stdio.h>
00126 #include <stdlib.h>
00127 #include <string.h>
00128 #include <math.h>
00129 #include <sys/types.h>
00130 #include <sys/stat.h>
00131 #include <unistd.h>
00132 
00133 #include "file_tool.h"
00134 #include "ge4_header.h"
00135 
00136 char g_rep_output_data[MAX_STR_LEN];    /* in case user doesn't pass it in */
00137 
00138 static int swap_2 ( void * ptr );
00139 static int swap_4 ( void * ptr );
00140 
00141 /*------------------------------------------------------------
00142  *  - check that the program is used correctly
00143  *  - fill the param_t struct, based on user inputs
00144  *  - process the files (display/modify data from/in each file)
00145  *------------------------------------------------------------
00146 */
00147 int main ( int argc, char * argv[] )
00148 {
00149     param_t P;
00150     int     rv;
00151 
00152     if ( (rv = set_params( &P, argc, argv ) ) < 0 )
00153         return rv;
00154     else if ( rv > 0 )
00155         return 0;
00156 
00157     if ( (rv = attack_files( &P ) ) != 0 )
00158         return rv;
00159 
00160     return 0;
00161 }
00162 
00163 /*------------------------------------------------------------
00164  *  - foreach file
00165  *      - if we are displaying GE info, do so
00166  *      - else, display/modify pertinent data
00167  *------------------------------------------------------------
00168 */
00169 int
00170 attack_files( param_t * p )
00171 {
00172     int fc, rv;
00173 
00174     for ( fc = 0; fc < p->num_files; fc++ )
00175     {
00176         if ( p->ge_disp )
00177         {
00178             if ( (rv = process_ge( p->flist[fc], p )) != 0 )
00179                 return rv;
00180         }
00181         else if ( p->ge4_disp )
00182         {
00183             if ( (rv = process_ge4( p->flist[fc], p )) != 0 )
00184                 return rv;
00185         }
00186         else if ( ( rv = process_file( p->flist[fc], p) ) != 0 )
00187             return rv;
00188     }
00189 
00190     return 0;
00191 }
00192 
00193 
00194 /*------------------------------------------------------------
00195  * Run the relevant GEMS 4.x processing functions.
00196  *------------------------------------------------------------
00197 */
00198 int
00199 process_ge4( char * filename, param_t * p )
00200 {
00201     ge4_header H;
00202     int        rv;
00203 
00204     rv = ge4_read_header( &H, filename, 0 );
00205 
00206     if ( rv != 0 )
00207     {
00208         if ( p->ge4_disp )      /* then display the bad result */
00209         {
00210             printf( "%s : GEMS 4.x header failure : %d\n", filename, rv );
00211             return 0;
00212         }
00213         else                    /* else just return it */
00214             return -1;
00215     }
00216 
00217     if ( (p->debug > 1) || (p->ge4_disp & GE4_DISP_STUDY) )
00218         idisp_ge4_study_header( filename, &H.std_h );
00219 
00220     if ( (p->debug > 1) || (p->ge4_disp & GE4_DISP_SERIES) )
00221         idisp_ge4_series_header( filename, &H.ser_h );
00222 
00223     if ( (p->debug > 1) || (p->ge4_disp & GE4_DISP_IMAGE) )
00224         idisp_ge4_image_header( filename, &H.im_h );
00225 
00226     return 0;
00227 }
00228 
00229 
00230 /*------------------------------------------------------------
00231  * Run the relevant GE processing functions.
00232  *------------------------------------------------------------
00233 */
00234 int
00235 process_ge( char * filename, param_t * p )
00236 {
00237     ge_header_info H;
00238     ge_extras      E;
00239     ge_off         off;
00240     int            rv;
00241 
00242     rv = read_ge_header( filename, &H, &E, &off );
00243 
00244     if ( rv != 0 )
00245     {
00246         if ( p->ge_disp )  /* if we are here to display - state results */
00247         {
00248             printf( "%s : GE header failure : %d\n", filename, rv );
00249             return 0;  /* don't fail out */
00250         }
00251         else
00252             return -1;     /* else, just return the results */
00253     }
00254 
00255     if ( (p->debug > 1) || (p->ge_disp & GE_HEADER) )
00256         r_idisp_ge_header_info( filename, &H );
00257 
00258     if ( (p->debug > 1) || (p->ge_disp & GE_EXTRAS ) )
00259         r_idisp_ge_extras( filename, &E );
00260 
00261     if ( p->ge_disp & GE_OFF )
00262         disp_ge_offsets( filename, &off );
00263 
00264     if ( p->ge_disp & GE_UV17 )
00265         printf( "%s : run # %d\n", filename, H.uv17 );
00266 
00267     return 0;
00268 }
00269 
00270 
00271 /*------------------------------------------------------------
00272  * Do the processing for the given file:
00273  *
00274  *   - open the file
00275  *   - go to the user-specified offset (may be 0)
00276  *   - read the relevant number of bytes
00277  *   - if display info, print out data
00278  *   - if modifying, go back to 'offset' and write data
00279  *   - close file
00280  *------------------------------------------------------------
00281 */
00282 int
00283 process_file( char * filename, param_t * p )
00284 {
00285     FILE        * fp;
00286     static char * fdata = NULL;
00287     int           nbytes;
00288 
00289     if ( (fp = fopen( filename, "r+" )) == NULL )
00290     {
00291         fprintf( stderr, "failure: cannot open <%s> for 'rw'\n", filename );
00292         return -1;
00293     }
00294 
00295     if ( fdata == NULL )
00296     {
00297         fdata = (char*) calloc( p->length, sizeof(char) );
00298         if ( fdata == NULL )
00299         {
00300             fprintf( stderr, "failure: cannot allocate %d bytes for data\n",
00301                      p->length );
00302             return -1;
00303         }
00304     }
00305 
00306     if ( fseek( fp, p->offset, SEEK_SET ) )
00307     {
00308         fprintf( stderr, "failure: cannot seek to <%ld> in file '%s'\n",
00309                  p->offset, filename );
00310         fclose( fp );
00311         return -1;
00312     }
00313 
00314     if ( (nbytes = fread( fdata, 1, p->length, fp )) != p->length )
00315     {
00316         fprintf( stderr, "failure: read only %d of %d bytes from file '%s'\n",
00317                  nbytes, p->length, filename );
00318         fclose( fp );
00319         return -1;
00320     }
00321 
00322     /* display file contents */
00323     if ( !p->modify || p->debug )
00324     {
00325         if ( ! p->quiet && ! p->ndisp )
00326             printf( "<%s> : '", filename );
00327 
00328         /* handle the numeric display */
00329         if ( p->ndisp )
00330         {
00331             if ( disp_numeric_data( fdata, p, stdout ) )
00332             {
00333                 fclose( fp );
00334                 return -1;
00335             }
00336         }
00337         else if ( (nbytes = fwrite(fdata, 1, p->length, stdout)) != p->length )
00338         {
00339             fprintf( stderr, "\nfailure: wrote only %d of %d bytes to '%s'\n",
00340                      nbytes, p->length, "stdout" );
00341             fclose( fp );
00342             return -1;
00343         }
00344         if ( ! p->quiet && ! p->ndisp )
00345             puts( "'" );        /* single quote plus newline */
00346     }
00347 
00348     if ( p->modify )  /* if writing back to file */
00349     {
00350         if ( fseek( fp, p->offset, SEEK_SET ) )
00351         {
00352             fprintf( stderr, "failure: cannot re-seek to <%ld> in file '%s'\n",
00353                      p->offset, filename );
00354             fclose( fp );
00355             return -1;
00356         }
00357 
00358         if ( (nbytes = write_data_to_file( fp, filename, p ) ) < 0 )
00359         {
00360             fclose( fp );
00361             return -1;
00362         }
00363 
00364         if ( p->debug > 0 )
00365         {
00366             printf( "wrote '%s' (%d bytes) to file '%s', position %ld\n",
00367                     p->mod_data, p->length, filename, p->offset );
00368         }
00369     }
00370 
00371     fclose( fp );
00372 
00373     return 0;
00374 }
00375 
00376 
00377 /*------------------------------------------------------------
00378  *  Actually write data into the file stream.
00379  *
00380  *  return bytes written : on success
00381  *                    -1 : on error
00382  *------------------------------------------------------------
00383 */
00384 int write_data_to_file( FILE * fp, char * filename, param_t * p )
00385 {
00386     double   dval;
00387     char   * outp, * inp, * endp;
00388     int      dsize, c, nbytes;
00389 
00390     if ( (dsize = mtype_size( p->mod_type )) < 1 )
00391     {
00392         fprintf(stderr,"** bad size %d for mod_type %d\n", dsize, p->mod_type);
00393         return -1;
00394     }
00395 
00396     if ( p->debug > 1 )
00397         fprintf(stderr,"-- dsize = %d\n", dsize);
00398 
00399     /* deal with characters separately */
00400     if ( p->mod_type == MOD_STR || p->mod_type == MOD_CHAR )
00401     {
00402         int remaining = p->length - p->data_len; /* note remainder (if any) */
00403 
00404         if ( (nbytes=fwrite(p->mod_data, 1, p->data_len, fp)) != p->data_len )
00405         {
00406             fprintf( stderr, "\nfailure: wrote only %d of %d bytes to '%s'\n",
00407                      nbytes, p->data_len, filename );
00408             fclose( fp );
00409             return -1;
00410         }
00411 
00412         /* and fill with 0 */
00413         for ( c = 0; c < remaining; c++ )
00414             fputc( '\0', fp );
00415 
00416         return p->length;
00417     }
00418 
00419     if ( p->debug > 1 ) fprintf(stderr,"++ values: ");
00420 
00421     /* now write numerical values into g_rep_output_data */
00422     outp = g_rep_output_data;
00423     inp  = p->mod_data;
00424     memset(outp, 0, p->length);
00425     for ( c = 0; (c+dsize) <= p->length; c += dsize, outp += dsize )
00426     {
00427         dval = strtod( inp, &endp );
00428 
00429         if ( endp && inp != endp )   /* then we read something in */
00430         {
00431             switch (p->mod_type)
00432             {
00433                 default:
00434                     fprintf(stderr,"** wdtf: bad type %d\n", p->mod_type);
00435                     return -1;
00436                 case MOD_U1:
00437                     *(unsigned char *)outp = (unsigned char)dval;
00438                     break;
00439                 case MOD_S1:
00440                     *(char *)outp = (char)dval;
00441                     break;
00442                 case MOD_U2:
00443                     *(unsigned short *)outp = (unsigned short)dval;
00444                     break;
00445                 case MOD_S2:
00446                     *(short *)outp = (short)dval;
00447                     break;
00448                 case MOD_U4:
00449                     *(unsigned long *)outp = (unsigned long)dval;
00450                     break;
00451                 case MOD_S4:
00452                     *(long *)outp = (long)dval;
00453                     break;
00454                 case MOD_F4:
00455                     *(float *)outp = (float)dval;
00456                     break;
00457                 case MOD_F8:
00458                     *(double *)outp = dval;
00459                     break;
00460             }
00461 
00462             if ( p->swap )
00463             {
00464                 if ( dsize == 2 )
00465                     swap_2( (void *)outp );
00466                 else if ( dsize == 4 )
00467                     swap_4( (void *)outp );
00468             }
00469 
00470             if ( p->debug > 1 ) fprintf(stderr," %f", dval);
00471         }
00472         else
00473             break;      /* done */
00474 
00475         inp = endp;     /* prepare to go after a new number */
00476     }
00477 
00478     if ( p->debug > 1 ) fputc('\n', stderr);
00479 
00480     /* now just write the data out */
00481     nbytes = fwrite(g_rep_output_data, 1, p->length, fp);
00482     if ( nbytes != p->length )
00483     {
00484         fprintf(stderr,"** wrote only %d of %d bytes of binary data\n",
00485                 nbytes, p->length);
00486         return nbytes;
00487     }
00488 
00489     return p->length;
00490 }
00491 
00492 int mtype_size( int type )
00493 {
00494     if ( type == MOD_STR  ) return 1;
00495     if ( type == MOD_CHAR ) return 1;
00496     if ( type == MOD_U1   ) return 1;
00497     if ( type == MOD_S1   ) return 1;
00498 
00499     if ( type == MOD_U2   ) return 2;
00500     if ( type == MOD_S2   ) return 2;
00501 
00502     if ( type == MOD_U4   ) return 4;
00503     if ( type == MOD_S4   ) return 4;
00504 
00505     if ( type == MOD_F4   ) return 4;
00506     if ( type == MOD_F8   ) return 8;
00507 
00508     return -1;
00509 }
00510 
00511 /*------------------------------------------------------------
00512  *  Read user arguments, and fill param_t struct.
00513  *
00514  *  - if modifying, verify arguments
00515  *------------------------------------------------------------
00516 */
00517 int
00518 set_params( param_t * p, int argc, char * argv[] )
00519 {
00520     int ac;
00521 
00522     if ( argc < 2 )
00523     {
00524         usage( argv[0], USE_SHORT );
00525         return -1;
00526     }
00527 
00528     if ( !p || !argv )
00529     {
00530         fprintf( stderr, "failure: bad params to set_params: "
00531                  "p = <%p>, ac = <%d>, av = <%p>\n",
00532                  p, argc, argv );
00533         return -1;
00534     }
00535 
00536     /* clear out param struct - this sets all default values */
00537     memset( p, 0, sizeof(*p) );
00538 
00539     for ( ac = 1; ac < argc; ac++ )
00540     {
00541         /* check for -help_ge before -help, to allow for only -h */
00542         if ( ! strncmp(argv[ac], "-help_ge", 8 ) )
00543         {
00544             usage( argv[0], USE_GE );
00545             return -1;
00546         }
00547         else if ( ! strncmp(argv[ac], "-help", 3 ) )
00548         {
00549             usage( argv[0], USE_LONG );
00550             return -1;
00551         }
00552         else if ( ! strncmp(argv[ac], "-hist", 3 ) )
00553         {
00554             usage( argv[0], USE_HISTORY );
00555             return -1;
00556         }
00557         else if ( ! strncmp(argv[ac], "-debug", 6 ) )
00558         {
00559             if ( (ac+1) >= argc )
00560             {
00561                 fputs( "missing option parameter: LEVEL\n"
00562                        "option usage: -debug LEVEL\n"
00563                        "    where LEVEL is the debug level (0,1 or 2)\n",
00564                        stderr );
00565                 return -1; 
00566             }
00567 
00568             p->debug = atoi(argv[++ac]);
00569             if ( (p->debug < 0) || (p->debug > 2) )
00570             {
00571                 fprintf( stderr, "invalid debug level <%d>\n", p->debug );
00572                 return -1;
00573             }
00574         }
00575         else if ( ! strncmp(argv[ac], "-disp_int2", 10 ) )
00576         {
00577             p->ndisp |= NDISP_INT2;
00578         }
00579         else if ( ! strncmp(argv[ac], "-disp_int4", 10 ) )
00580         {
00581             p->ndisp |= NDISP_INT4;
00582         }
00583         else if ( ! strncmp(argv[ac], "-disp_real4", 11 ) )
00584         {
00585             p->ndisp |= NDISP_REAL4;
00586         }
00587         else if ( ! strncmp(argv[ac], "-mod_data", 6 ) )
00588         {
00589             if ( (ac+1) >= argc )
00590             {
00591                 fputs( "missing option parameter: DATA\n"
00592                        "option usage: -mod_data DATA\n"
00593                        "    where DATA is the replacement string or numbers\n",
00594                        stderr );
00595                 return -1; 
00596             }
00597 
00598             ac++;
00599             p->mod_data = argv[ac];
00600         }
00601         else if ( ! strncmp(argv[ac], "-mod_type", 6 ) )
00602         {
00603             if ( (ac+1) >= argc )
00604             {
00605                 fputs( "missing option parameter: TYPE\n"
00606                        "option usage: -mod_type TYPE\n"
00607                        "    where TYPE is 'val' or 'str'\n",
00608                        stderr );
00609                 return -1;
00610             }
00611 
00612             ac++;
00613             if ( (p->mod_type = check_mod_type(argv[ac])) == MOD_INVALID )
00614             {
00615                 fputs( "option usage: -mod_type TYPE\n", stderr );
00616                 fputs( "              where TYPE is 'str' or 'val'\n", stderr );
00617                 return -1;
00618             }
00619         }
00620         else if ( ! strncmp(argv[ac], "-offset", 4 ) )
00621         {
00622             if ( (ac+1) >= argc )
00623             {
00624                 fputs( "missing option parameter: OFFSET\n"
00625                        "option usage: -offset OFFSET\n"
00626                        "    where OFFSET is the file offset\n",
00627                        stderr );
00628                 return -1;
00629             }
00630 
00631             p->offset = atoi(argv[++ac]);
00632             if ( p->offset < 0 )
00633             {
00634                 fprintf( stderr, "bad file OFFSET <%ld>\n", p->offset );
00635                 return -1;
00636             }
00637         }
00638         else if ( ! strncmp(argv[ac], "-length", 4 ) )
00639         {
00640             if ( (ac+1) >= argc )
00641             {
00642                 fputs( "missing option parameter: LENGTH\n"
00643                        "option usage: -length LENGTH\n"
00644                        "    where LENGTH is the length to display or modify\n",
00645                        stderr );
00646                 return -1;
00647             }
00648 
00649             p->length = atoi(argv[++ac]);
00650             if ( p->length < 0 )
00651             {
00652                 fprintf( stderr, "bad LENGTH <%d>\n", p->length );
00653                 return -1;
00654             }
00655         }
00656         else if ( ! strncmp(argv[ac], "-quiet", 2 ) )
00657         {
00658             p->quiet = 1;
00659         }
00660         else if ( ! strncmp(argv[ac], "-swap_bytes", 3 ) )
00661         {
00662             p->swap = 1;
00663         }
00664         else if ( ! strncmp(argv[ac], "-ver", 2 ) )
00665         {
00666             usage( argv[0], USE_VERSION );
00667             return 1;
00668         }
00669         else if ( ! strncmp(argv[ac], "-infiles", 4 ) )
00670         {
00671             if ( (ac+1) >= argc )
00672             {
00673                 fputs( "missing input files...\n"
00674                        "option usage: -infiles file1 file2 ...\n",
00675                        stderr );
00676                 return -1;
00677             }
00678 
00679             ac++;
00680             p->num_files = argc - ac;
00681             p->flist     = argv + ac;
00682 
00683             break;      /* input files finish the argument list */
00684         }
00685         /* continue with GE info displays */
00686         else if ( ! strncmp(argv[ac], "-ge_all", 7 ) )
00687         {
00688             p->ge_disp |= GE_ALL;
00689         }
00690         else if ( ! strncmp(argv[ac], "-ge_header", 7 ) )
00691         {
00692             p->ge_disp |= GE_HEADER;
00693         }
00694         else if ( ! strncmp(argv[ac], "-ge_extras", 7 ) )
00695         {
00696             p->ge_disp |= GE_EXTRAS;
00697         }
00698         else if ( ! strncmp(argv[ac], "-ge_off", 7 ) )
00699         {
00700             p->ge_disp |= GE_OFF;
00701         }
00702         /* allow both forms - uv17 means the run number */
00703         else if ( ! strncmp(argv[ac], "-ge_uv17", 7 ) ||
00704                   ! strncmp(argv[ac], "-ge_run", 7  )    )
00705         {
00706             p->ge_disp |= GE_UV17;
00707         }
00708         /* continue with GEMS 4.x info displays */
00709         else if ( ! strncmp(argv[ac], "-ge4_all", 7 ) )
00710         {
00711             p->ge4_disp |= GE4_DISP_ALL;
00712         }
00713         else if ( ! strncmp(argv[ac], "-ge4_image", 7 ) )
00714         {
00715             p->ge4_disp |= GE4_DISP_IMAGE;
00716         }
00717         else if ( ! strncmp(argv[ac], "-ge4_series", 8 ) )
00718         {
00719             p->ge4_disp |= GE4_DISP_SERIES;
00720         }
00721         else if ( ! strncmp(argv[ac], "-ge4_study", 8 ) )
00722         {
00723             p->ge4_disp |= GE4_DISP_STUDY;
00724         }
00725         /* finish with bad option */
00726         else
00727         {
00728             fprintf( stderr, "error: unknown option, <%s>\n", argv[ac] );
00729             return -1;
00730         }
00731     }
00732 
00733     if ( p->debug > 1 )
00734         disp_param_data( p );
00735 
00736     if ( p->num_files <= 0 )
00737     {
00738         fputs( "error: missing '-infiles' option\n", stderr );
00739         return -1;
00740     }
00741 
00742     /* if only displaying GE data, no further check are necessary */
00743     if ( p->ge_disp || p->ge4_disp )
00744         return 0;
00745 
00746     /* now do all other tests for displaying/modifying generic file data */
00747 
00748     if ( p->mod_data )
00749     {
00750         p->modify = 1;           /* so we plan to modify the data */
00751         p->data_len = strlen(p->mod_data);    /* note data length */
00752     }
00753     else
00754         p->modify = 0;                             /* be explicit */
00755 
00756     if ( p->length <= 0 )
00757     {
00758         fputs( "error: missing '-length' option\n", stderr );
00759         return -1;
00760     }
00761 
00762     if ( p->modify )
00763     {
00764         if ( p->length > MAX_STR_LEN )
00765         {
00766             fprintf( stderr, "failure: length <%d> exceeds maximum %d\n",
00767                  p->length, MAX_STR_LEN );
00768             return -1;
00769         }
00770 
00771         if ( p->mod_type == MOD_CHAR )
00772         {
00773             /* we are writing one char length times */
00774             memset( g_rep_output_data, *p->mod_data, p->length );
00775             p->mod_data = g_rep_output_data;
00776             p->data_len = p->length;
00777         }
00778         else if ( p->mod_type == MOD_STR && p->length < p->data_len )
00779         {
00780             fprintf( stderr, "failure: data length <%d> exceeds length <%d>\n",
00781                      p->data_len, p->length );
00782             return -1;
00783         }
00784     }
00785 
00786     return 0;
00787 }
00788 
00789 
00790 /*------------------------------------------------------------
00791  *  return appropriate MOD_ value, if one exists
00792  *------------------------------------------------------------
00793 */
00794 int check_mod_type( char * name )
00795 {
00796     /* character mods */
00797     if ( ! strncmp(name, "str", 3) )
00798         return MOD_STR; /* this is default */
00799     if ( ! strncmp(name, "val",  3) || ! strncmp(name, "char", 4) )
00800         return MOD_CHAR;
00801 
00802     /* integral mods */
00803     if ( ! strncmp(name, "uint1", 5) )
00804         return MOD_U1;
00805     if ( ! strncmp(name, "sint1", 5) )
00806         return MOD_S1;
00807     if ( ! strncmp(name, "uint2", 5) )
00808         return MOD_U2;
00809     if ( ! strncmp(name, "sint2", 5) )
00810         return MOD_S2;
00811     if ( ! strncmp(name, "uint4", 5) )
00812         return MOD_U4;
00813     if ( ! strncmp(name, "sint4", 5) )
00814         return MOD_S4;
00815 
00816     /* real mods */
00817     if ( ! strncmp(name, "float4", 6) )
00818         return MOD_F4;
00819     if ( ! strncmp(name, "float8", 6) )
00820         return MOD_F8;
00821 
00822     return MOD_INVALID;
00823 }
00824 
00825 
00826 /*------------------------------------------------------------
00827  *  Display usage information, depending on usage level:
00828  *  
00829  *  - USE_SHORT   : most basic usage info
00830  *  - USE_VERSION : display the current version info
00831  *  - USE_GE      : describe GE struct elements
00832  *  - USE_LONG    : complete help on program and options
00833  *------------------------------------------------------------
00834 */
00835 int usage( char * prog, int level )
00836 {
00837     if ( level == USE_SHORT )
00838     {
00839         printf( "usage: %s -help\n"
00840                 "usage: %s [options] file1 file2 ...\n",
00841                 prog, prog);
00842         return 0;
00843     }
00844     else if ( level == USE_VERSION )
00845     {
00846         printf( "%s, version %s, compiled: %s\n",
00847                 prog, VERSION, __DATE__ );
00848         return 0;
00849     }
00850     else if ( level == USE_HISTORY )
00851     {
00852         fputs( g_history, stdout );
00853         return 0;
00854     }
00855     else if ( level == USE_GE )
00856     {
00857         help_ge_structs( prog );
00858         return 0;
00859     }
00860     else if ( level != USE_LONG )
00861     {
00862         fprintf( stderr, "failure: bad usage level <%d>\n", level );
00863         return -1;
00864     }
00865 
00866     /* so we are in a USE_LONG case */
00867     help_full( prog );
00868 
00869     return 0;
00870 }
00871 
00872 /*------------------------------------------------------------
00873  *  Describe elements of each GE struct.
00874  *------------------------------------------------------------
00875 */
00876 int
00877 help_ge_structs( char * prog )
00878 {
00879     printf( "------------------------------------------------------------\n"
00880             "These are descriptions of the elements in the GE\n"
00881             "data structures used by '%s'.  Most elements\n"
00882             "correspond to a field in the image file header.\n"
00883             "\n"
00884             "These fields are shown when running '%s'\n"
00885             "with any of the options:\n"
00886             "   '-ge_header', '-ge_extras', or '-ge_all'.\n"
00887             /* taken from Ifile.c */
00888             "----------------------------------------\n"
00889             "ge_header_info struct:\n"
00890             "\n"
00891             "    good     : is this a valid GE image file\n"
00892             "    nx,ny    : dimensions of image in voxels\n"
00893             "    uv17     : run number (user variable 17)\n"
00894             "    dx,dy,dz : directional deltas - distances between voxels\n"
00895             "    zoff     : location of image in z direction\n"
00896             "    tr,te    : TR and TE timings\n"
00897             "    orients  : orientation string for image\n"
00898             "----------------------------------------\n"
00899             /* taken from mri_read.c */
00900             "ge_extras struct:\n"
00901             "\n"
00902             "    bpp      : bytes per pixel (file_size = nx * ny * bpp)\n"
00903             "    cflag    : compression flag (here, 1 means NOT compressed)\n"
00904             "    hdroff   : offset of image header (from beginning of file)\n"
00905             "    skip     : offset of image data   (from beginning of file)\n"
00906             "    swap     : is byte swapping performed?\n"
00907             "    xyzX     : coordinate box containing image\n"
00908             "------------------------------------------------------------\n"
00909             "\n", prog, prog
00910           );
00911 
00912     return 0;
00913 }
00914 
00915 /*------------------------------------------------------------
00916  *  Show detailed help.
00917  *------------------------------------------------------------
00918 */
00919 int
00920 help_full( char * prog )
00921 {
00922     printf(
00923         "\n"
00924         "%s - display or modify sections of a file\n"
00925         "\n"
00926         "    This program can be used to display or edit data in arbitrary\n"
00927         "    files.  If no '-mod_data' option is provided (with DATA), it\n"
00928         "    is assumed the user wishes only to display the specified data\n"
00929         "    (using both '-offset' and '-length', or using '-ge_XXX').\n"
00930         "\n"
00931         "  usage: %s [options] -infiles file1 file2 ...\n"
00932         "\n"
00933         "  examples:\n"
00934         "\n"
00935         "   ----- help examples -----\n"
00936         "\n"
00937         "   1. get detailed help:\n"
00938         "\n"
00939         "      %s -help\n"
00940         "\n"
00941         "   2. get descriptions of GE struct elements:\n"
00942         "\n"
00943         "      %s -help_ge\n"
00944         "\n"
00945         "   ----- GEMS 4.x and 5.x display examples -----\n"
00946         "\n"
00947         "   3. display GE header and extras info for file I.100:\n"
00948         "\n"
00949         "      %s -ge_all -infiles I.100\n"
00950         "\n"
00951         "   4. display GEMS 4.x series and image headers for file I.100:\n"
00952         "\n"
00953         "      %s -ge4_all -infiles I.100\n"
00954         "\n"
00955         "   5. display run numbers for every 100th I-file in this directory\n"
00956         "\n"
00957         "      %s -ge_uv17 -infiles I.?42\n"
00958         "      %s -ge_run  -infiles I.?42\n"
00959         "\n"
00960         "   ----- general value display examples -----\n"
00961         "\n"
00962         "   6. display the 32 characters located 100 bytes into each file:\n"
00963         "\n"
00964         "      %s -offset 100 -length 32 -infiles file1 file2\n"
00965         "\n"
00966         "   7. display the 8 4-byte reals located 100 bytes into each file:\n"
00967         "\n"
00968         "      %s -disp_real4 -offset 100 -length 32 -infiles file1 file2\n"
00969         "\n"
00970         "   ----- character modification examples -----\n"
00971         "\n"
00972         "   8. in each file, change the 8 characters at 2515 to 'hi there':\n"
00973         "\n"
00974         "      %s -mod_data \"hi there\" -offset 2515 -length 8 -infiles I.*\n"
00975         "\n"
00976         "   9. in each file, change the 21 characters at 2515 to all 'x's\n"
00977         "      (and print out extra debug info)\n"
00978         "\n"
00979         "      %s -debug 1 -mod_data x -mod_type val -offset 2515 \\\n"
00980         "                -length 21 -infiles I.*\n"
00981         "\n"
00982         "   ----- raw number modification examples -----\n"
00983         "\n"
00984         "  10. in each file, change the 3 short integers starting at position\n"
00985         "      2508 to '2 -419 17'\n"
00986         "\n"
00987         "      %s -mod_data '2 -419 17' -mod_type sint2 -offset 2508 \\\n"
00988         "                -length 6 -infiles I.*\n"
00989         "\n"
00990         "  11. in each file, change the 3 binary floats starting at position\n"
00991         "      2508 to '-83.4 2 17' (and set the next 8 bytes to zero by\n"
00992         "      setting the length to 20, instead of just 12).\n"
00993         "\n"
00994         "      %s -mod_data '-83.4 2 17' -mod_type float4 -offset 2508 \\\n"
00995         "                -length 20 -infiles I.*\n"
00996         "\n"
00997         "  12. in each file, change the 3 binary floats starting at position\n"
00998         "      2508 to '-83.4 2 17', and apply byte swapping\n"
00999         "\n"
01000         "      %s -mod_data '-83.4 2 17' -mod_type float4 -offset 2508 \\\n"
01001         "                -length 12 -swap_bytes -infiles I.*\n"
01002         "\n"
01003         "  notes:\n"
01004         "\n"
01005         "    o  Use of '-infiles' is required.\n"
01006         "    o  Use of '-length' or a GE information option is required.\n"
01007         "    o  As of this version, only modification with text is supported.\n"
01008         "       Editing binary data is coming soon to a workstation near you.\n"
01009         "\n"
01010         "  special options:\n"
01011         "\n"
01012         "    -help              : show this help information\n"
01013         "                       : e.g. -help\n"
01014         "\n"
01015         "    -version           : show version information\n"
01016         "                       : e.g. -version\n"
01017         "\n"
01018         "    -hist              : show the program's modification history\n"
01019         "\n"
01020         "    -debug LEVEL       : print extra info along the way\n"
01021         "                       : e.g. -debug 1\n"
01022         "                       : default is 0, max is 2\n"
01023         "\n"
01024         "  required 'options':\n"
01025         "\n"
01026         "    -infiles f1 f2 ... : specify input files to print from or modify\n"
01027         "                       : e.g. -infiles file1\n"
01028         "                       : e.g. -infiles I.*\n"
01029         "\n"
01030         "          Note that '-infiles' should be the final option.  This is\n"
01031         "          to allow the user an arbitrary number of input files.\n"
01032         "\n"
01033         "  GE info options:\n"
01034         "\n"
01035         "      -ge_all          : display GE header and extras info\n"
01036         "      -ge_header       : display GE header info\n"
01037         "      -ge_extras       : display extra GE image info\n"
01038         "      -ge_uv17         : display the value of uv17 (the run #)\n"
01039         "      -ge_run          : (same as -ge_uv17)\n"
01040         "      -ge_off          : display file offsets for various fields\n"
01041         "\n"
01042         "  GEMS 4.x info options:\n"
01043         "\n"
01044         "      -ge4_all         : display GEMS 4.x series and image headers\n"
01045         "      -ge4_image       : display GEMS 4.x image header\n"
01046         "      -ge4_series      : display GEMS 4.x series header\n"
01047         "      -ge4_study       : display GEMS 4.x study header\n"
01048         "\n"
01049         "  raw ascii options:\n"
01050         "\n"
01051         "    -length LENGTH     : specify the number of bytes to print/modify\n"
01052         "                       : e.g. -length 17\n"
01053         "\n"
01054         "          This includes numbers after the conversion to binary.  So\n"
01055         "          if -mod_data is '2 -63 186', and -mod_type is 'sint2' (or\n"
01056         "          signed shorts), then 6 bytes will be written (2 bytes for\n"
01057         "          each of 3 short integers).\n"
01058         "\n"
01059         "       ** Note that if the -length argument is MORE than what is\n"
01060         "          needed to write the numbers out, the remaind of the length\n"
01061         "          bytes will be written with zeros.  If '17' is given for\n"
01062         "          the length, and 3 short integers are given as data, there \n"
01063         "          will be 11 bytes of 0 written after the 6 bytes of data.\n"
01064         "\n"
01065         "    -mod_data DATA     : specify a string to change the data to\n"
01066         "                       : e.g. -mod_data hello\n"
01067         "                       : e.g. -mod_data '2 -17.4 649'\n"
01068         "                       : e.g. -mod_data \"change to this string\"\n"
01069         "\n"
01070         "          This is the data that will be writting into the modified\n"
01071         "          file.  If the -mod_type is 'str' or 'char', then the\n"
01072         "          output data will be those characters.  If the -mod_type\n"
01073         "          is any other (i.e. a binary numerical format), then the\n"
01074         "          output will be the -mod_data, converted from numerical\n"
01075         "          text to binary.\n"
01076         "\n"
01077         "       ** Note that a list of numbers must be contained in quotes,\n"
01078         "          so that it will be processed as a single parameter.\n"
01079         "\n"
01080         "    -mod_type TYPE     : specify the data type to write to the file\n"
01081         "                       : e.g. -mod_type string\n"
01082         "                       : e.g. -mod_type sint2\n"
01083         "                       : e.g. -mod_type float4\n"
01084         "                       : default is 'str'\n"
01085         "\n"
01086         "        TYPE can be one of:\n"
01087         "\n"
01088         "          str       : perform a string substitution\n"
01089         "          char, val : perform a (repeated?) character substitution\n"
01090         "          uint1     : single byte unsigned int   (binary write)\n"
01091         "          sint1     : single byte   signed int   (binary write)\n"
01092         "          uint2     : two    byte unsigned int   (binary write)\n"
01093         "          sint2     : two    byte   signed int   (binary write)\n"
01094         "          uint4     : four   byte unsigned int   (binary write)\n"
01095         "          sint4     : four   byte   signed int   (binary write)\n"
01096         "          float4    : four   byte floating point (binary write)\n"
01097         "          float8    : eight  byte floating point (binary write)\n"
01098         "\n"
01099         "          If 'str' is used, which is the default action, the data is\n"
01100         "          replaced by the contents of the string DATA (from the\n"
01101         "          '-mod_data' option).\n"
01102         "\n"
01103         "          If 'char' is used, then LENGTH bytes are replaced by the\n"
01104         "          first character of DATA, repeated LENGTH times.\n"
01105         "\n"
01106         "          For any of the others, the list of numbers found in the\n"
01107         "          -mod_data option will be written in the supplied binary\n"
01108         "          format.  LENGTH must be large enough to accomodate this\n"
01109         "          list.  And if LENGTH is higher, the output will be padded\n"
01110         "          with zeros, to fill to the requesed length.\n"
01111         "\n"
01112         "    -offset OFFSET     : use this offset into each file\n"
01113         "                       : e.g. -offset 100\n"
01114         "                       : default is 0\n"
01115         "\n"
01116         "          This is the offset into each file for the data to be\n"
01117         "          read or modified.\n"
01118         "\n"
01119         "    -quiet             : do not output header information\n"
01120         "\n"
01121         "  numeric options:\n"
01122         "\n"
01123         "    -disp_int2         : display 2-byte integers\n"
01124         "                       : e.g. -disp_int2\n"
01125         "\n"
01126         "    -disp_int4         : display 4-byte integers\n"
01127         "                       : e.g. -disp_int4\n"
01128         "\n"
01129         "    -disp_real4        : display 4-byte real numbers\n"
01130         "                       : e.g. -disp_real4\n"
01131         "\n"
01132         "    -swap_bytes        : use byte-swapping on numbers\n"
01133         "                       : e.g. -swap_bytes\n"
01134         "\n"
01135         "          If this option is used, then byte swapping is done on any\n"
01136         "          multi-byte numbers read from or written to the file.\n"
01137         "\n"
01138         "  - R Reynolds, version: %s, compiled: %s\n"
01139         "\n",
01140         prog, prog,
01141         prog, prog, prog, prog, prog, prog, prog, prog, prog,
01142         prog, prog, prog, prog,
01143         VERSION, __DATE__
01144         );
01145 
01146     return 0;
01147 }
01148 
01149 /*------------------------------------------------------------
01150  * Reverse the order of the 4 bytes at this address.
01151  *------------------------------------------------------------
01152 */
01153 static int
01154 swap_4( void * ptr )            /* destructive */
01155 {
01156    unsigned char * addr = ptr;
01157 
01158    addr[0] ^= addr[3]; addr[3] ^= addr[0]; addr[0] ^= addr[3];
01159    addr[1] ^= addr[2]; addr[2] ^= addr[1]; addr[1] ^= addr[2];
01160 
01161    return 0;
01162 }
01163 
01164 /*------------------------------------------------------------
01165  * Reverse the order of the 2 bytes at this address.
01166  *------------------------------------------------------------
01167 */
01168 static int
01169 swap_2( void * ptr )            /* destructive */
01170 {
01171    unsigned char * addr = ptr;
01172 
01173    addr[0] ^= addr[1]; addr[1] ^= addr[0]; addr[0] ^= addr[1];
01174 
01175    return 0;
01176 }
01177 
01178 /******************************************************************/
01179 /*** Return info from a GEMS IMGF file into user-supplied struct **/
01180 
01181 /* stolen from Ifile.c and modified ... */
01182 
01183 int
01184 read_ge_header( char *pathname , ge_header_info *hi, ge_extras *E, ge_off *off )
01185 {
01186    FILE *imfile ;
01187    int  length , skip , swap=0 ;
01188    char orients[8] , str[8] ;
01189    int nx , ny , bpp , cflag , hdroff ;
01190         float uv17 = -1.0;
01191         
01192    if( hi == NULL ) return -1;            /* bad */
01193    hi->good = 0 ;                       /* not good yet */
01194    if( pathname    == NULL ||
01195        pathname[0] == '\0'   ) return -1; /* bad */
01196 
01197    length = THD_filesize( pathname ) ;
01198    if( length < 1024 ) return -1;         /* bad */
01199 
01200    imfile = fopen( pathname , "r" ) ;
01201    if( imfile == NULL ) return -1;        /* bad */
01202 
01203    strcpy(str,"JUNK") ;     /* initialize string */
01204    fread(str,1,4,imfile) ;  /* check for "IMGF" at start of file */
01205 
01206    if( str[0]!='I' || str[1]!='M' || str[2]!='G' || str[3]!='F' ){ /* bad */
01207       fclose(imfile) ; return -2;
01208    }
01209 
01210    /*-- read next 5 ints (after the "IMGF" string) --*/
01211 
01212    fread( &skip , 4,1, imfile ) ; /* offset into file of image data */
01213    fread( &nx   , 4,1, imfile ) ; /* x-size */
01214    fread( &ny   , 4,1, imfile ) ; /* y-size */
01215    fread( &bpp  , 4,1, imfile ) ; /* bits per pixel (should be 16) */
01216    fread( &cflag, 4,1, imfile ) ; /* compression flag (1=uncompressed)*/
01217 
01218         /*-- check if nx is funny --*/
01219 
01220    if( nx < 0 || nx > 8192 ){      /* have to byte swap these 5 ints */
01221      swap = 1 ;                    /* flag to swap data, too */
01222      swap_4(&skip); swap_4(&nx); swap_4(&ny); swap_4(&bpp); swap_4(&cflag);
01223    } else {
01224      swap = 0 ;  /* data is ordered for this CPU */
01225    }
01226    if( nx < 0 || nx > 8192 || ny < 0 || ny > 8192 ){  /* bad */
01227       fclose(imfile) ; return -1;
01228    }
01229 
01230    hi->nx = nx ;
01231    hi->ny = ny ;
01232 
01233    off->nx =  8;
01234    off->ny = 12;
01235 
01236    if( skip+2*nx*ny >  length ||               /* file is too short */
01237        skip         <= 0      ||               /* bizarre  */
01238        cflag        != 1      ||               /* data is compressed */
01239        bpp          != 16        ){
01240       fclose(imfile); return -1;    /* data is not shorts */
01241    }
01242 
01243    /*-- try to read image header data as well --*/
01244 
01245    fseek( imfile , 148L , SEEK_SET ) ; /* magic GEMS offset */
01246    fread( &hdroff , 4,1 , imfile ) ;   /* location of image header */
01247    if( swap ) swap_4(&hdroff) ;
01248 
01249    if( hdroff > 0 && hdroff+256 < length ){   /* can read from image header */
01250        float dx,dy,dz, xyz[9], zz ; int itr, ii,jj,kk ;
01251 
01252        /*-- get voxel grid sizes --*/
01253 
01254        fseek( imfile , hdroff+26 , SEEK_SET ) ;    /* dz */
01255        fread( &dz , 4,1 , imfile ) ;
01256 
01257        fseek( imfile , hdroff+50 , SEEK_SET ) ;    /* dx and dy */
01258        fread( &dx , 4,1 , imfile ) ;
01259        fread( &dy , 4,1 , imfile ) ;
01260 
01261        off->dx = hdroff+50;
01262        off->dy = hdroff+54;
01263        off->dz = hdroff+26;
01264 
01265        if( swap ){ swap_4(&dx); swap_4(&dy); swap_4(&dz); }
01266 
01267        hi->dx = dx ; hi->dy = dy ; hi->dz = dz ;
01268 
01269        /* grid orientation: from 3 sets of LPI corner coordinates: */
01270        /*   xyz[0..2] = top left hand corner of image     (TLHC)   */
01271        /*   xyz[3..5] = top right hand corner of image    (TRHC)   */
01272        /*   xyz[6..8] = bottom right hand corner of image (BRHC)   */
01273        /* GEMS coordinate orientation here is LPI                  */
01274 
01275        off->xyz = hdroff+154;
01276        fseek( imfile , hdroff+154 , SEEK_SET ) ;  /* another magic number */
01277        fread( xyz , 4,9 , imfile ) ;
01278        if( swap ){
01279           swap_4(xyz+0); swap_4(xyz+1); swap_4(xyz+2);
01280           swap_4(xyz+3); swap_4(xyz+4); swap_4(xyz+5);
01281           swap_4(xyz+6); swap_4(xyz+7); swap_4(xyz+8);
01282        }
01283 
01284        /* x-axis orientation */
01285        /* ii determines which spatial direction is x-axis  */
01286        /* and is the direction that has the biggest change */
01287        /* between the TLHC and TRHC                        */
01288 
01289        dx = fabs(xyz[3]-xyz[0]) ; ii = 1 ;
01290        dy = fabs(xyz[4]-xyz[1]) ; if( dy > dx ){ ii=2; dx=dy; }
01291        dz = fabs(xyz[5]-xyz[2]) ; if( dz > dx ){ ii=3;        }
01292        dx = xyz[ii+2]-xyz[ii-1] ; if( dx < 0. ){ ii = -ii;    }
01293        switch( ii ){
01294         case  1: orients[0]= 'L'; orients[1]= 'R'; break;
01295         case -1: orients[0]= 'R'; orients[1]= 'L'; break;
01296         case  2: orients[0]= 'P'; orients[1]= 'A'; break;
01297         case -2: orients[0]= 'A'; orients[1]= 'P'; break;
01298         case  3: orients[0]= 'I'; orients[1]= 'S'; break;
01299         case -3: orients[0]= 'S'; orients[1]= 'I'; break;
01300         default: orients[0]='\0'; orients[1]='\0'; break;
01301        }
01302 
01303        /* y-axis orientation */
01304        /* jj determines which spatial direction is y-axis  */
01305        /* and is the direction that has the biggest change */
01306        /* between the BRHC and TRHC                        */
01307 
01308        dx = fabs(xyz[6]-xyz[3]) ; jj = 1 ;
01309        dy = fabs(xyz[7]-xyz[4]) ; if( dy > dx ){ jj=2; dx=dy; }
01310        dz = fabs(xyz[8]-xyz[5]) ; if( dz > dx ){ jj=3;        }
01311        dx = xyz[jj+5]-xyz[jj+2] ; if( dx < 0. ){ jj = -jj;    }
01312        switch( jj ){
01313          case  1: orients[2] = 'L'; orients[3] = 'R'; break;
01314          case -1: orients[2] = 'R'; orients[3] = 'L'; break;
01315          case  2: orients[2] = 'P'; orients[3] = 'A'; break;
01316          case -2: orients[2] = 'A'; orients[3] = 'P'; break;
01317          case  3: orients[2] = 'I'; orients[3] = 'S'; break;
01318          case -3: orients[2] = 'S'; orients[3] = 'I'; break;
01319          default: orients[2] ='\0'; orients[3] ='\0'; break;
01320        }
01321 
01322        orients[4] = '\0' ;   /* terminate orientation string */
01323 
01324        kk = 6 - abs(ii)-abs(jj) ;   /* which spatial direction is z-axis   */
01325                                     /* where 1=LR, 2=PA, 3=IS               */
01326                                     /* (can't tell orientation from 1 slice) */
01327 
01328        zz = xyz[kk-1] ;             /* z-coordinate of this slice */
01329 
01330        hi->zoff = zz ;
01331        strcpy(hi->orients,orients) ;
01332 
01333        /*-- get TR in seconds --*/
01334 
01335        off->tr = hdroff+194;
01336        fseek( imfile , hdroff+194 , SEEK_SET ) ;
01337        fread( &itr , 4,1 , imfile ) ; /* note itr is an int */
01338        if( swap ) swap_4(&itr) ;
01339        hi->tr = 1.0e-6 * itr ;        /* itr is in microsec */
01340 
01341        /*-- get TE in milliseconds --*/
01342 
01343        off->te = hdroff+202;
01344        fseek( imfile , hdroff+202 , SEEK_SET ) ;
01345        fread( &itr , 4,1 , imfile ) ; /* itr is an int, in microsec */
01346        if( swap ) swap_4(&itr) ;
01347        hi->te = 1.0e-6 * itr ;
01348 
01349        /* zmodify: get User Variable 17, a likely indicator of a new scan,
01350         * info by S. Marrett, location from S. Inati's matlab function
01351         * GE_readHeaderImage.m
01352         */
01353 
01354         off->uv17 = hdroff+272+202;
01355         /* printf ("\nuv17 = \n"); */
01356         fseek ( imfile , hdroff+272+202, SEEK_SET ) ;
01357         fread( &uv17 , 4, 1 , imfile ) ;
01358         if( swap ) swap_4(&uv17) ;
01359         /* printf ("%d ", (int)uv17);  */
01360         hi->uv17 = (int)uv17; 
01361         /* printf ("\n"); */
01362         
01363         hi->good = 1 ;                  /* this is a good file */
01364 
01365         E->bpp    = bpp;                /* store the ge_extra info */
01366         E->cflag  = cflag;
01367         E->hdroff = hdroff;
01368         E->skip   = skip;
01369         E->swap   = swap;
01370 
01371         memcpy( E->xyz, xyz, sizeof(xyz) );
01372     } /* end of actually reading image header */
01373 
01374     fclose(imfile);
01375     return 0;
01376 }
01377 
01378 /*------------------------------------------------------------
01379  *  Return the size of the file.
01380  *------------------------------------------------------------
01381 */
01382 unsigned long
01383 THD_filesize ( char * pathname )
01384 {
01385     struct stat buf;
01386 
01387     if ( pathname == NULL || *pathname == '\0' )
01388         return -1;
01389 
01390     if ( stat( pathname, &buf ) != 0 )
01391         return -1;
01392 
01393     return (unsigned long)buf.st_size;
01394 }
01395 
01396 /*------------------------------------------------------------
01397  *  Just output raw numbers from the starting location,
01398  *  swapping bytes (if requested).
01399  *------------------------------------------------------------
01400 */
01401 int
01402 disp_numeric_data( char * data, param_t * p, FILE * fp )
01403 {
01404     int c;
01405 
01406     if ( data == NULL || fp == NULL )
01407     {
01408         fprintf( stderr, "** error: bad params to DND '%p,%p'\n", data, fp );
01409         return -1;
01410     }
01411 
01412     if ( p->length <= 0 || p->ndisp == 0 )
01413         return 0;
01414 
01415     /* print out shorts */
01416     if ( p->ndisp & NDISP_INT2 )
01417     {
01418         short * sp = (short *)data;
01419 
01420         fprintf( fp, "0x%4x : ", (unsigned int)p->offset );
01421         for ( c = 0; c < p->length/2; c++, sp++ )
01422         {
01423             if ( p->swap )
01424                 swap_2( sp );
01425             fprintf( fp, "%d ", *sp );
01426         }
01427         fputc( '\n', fp );
01428     }
01429 
01430     /* print out ints */
01431     if ( p->ndisp & NDISP_INT4 )
01432     {
01433         int * ip = (int *)data;
01434 
01435         fprintf( fp, "0x%4x : ", (unsigned int)p->offset );
01436         for ( c = 0; c < p->length/4; c++, ip++ )
01437         {
01438             if ( p->swap )
01439                 swap_4( ip );
01440             fprintf( fp, "%d ", *ip );
01441         }
01442         fputc( '\n', fp );
01443     }
01444 
01445     /* print out floats */
01446     if ( p->ndisp & NDISP_REAL4 )
01447     {
01448         float * rp = (float *)data;
01449 
01450         fprintf( fp, "0x%4x : ", (unsigned int)p->offset );
01451         for ( c = 0; c < p->length/4; c++, rp++ )
01452         {
01453             if ( p->swap )
01454                 swap_4( rp );
01455             fprintf( fp, "%f ", *rp );
01456         }
01457         fputc( '\n', fp );
01458     }
01459 
01460     return 0;
01461 }
01462 
01463 
01464 /*------------------------------------------------------------
01465  *  Display the contents of the param_t struct.
01466  *------------------------------------------------------------
01467 */
01468 int
01469 disp_param_data( param_t * p )
01470 {
01471     if ( ! p )
01472         return -1;
01473 
01474     printf( "num_files, flist         : %d, %p\n"
01475             "debug, data_len          : %d, %d\n"
01476             "ge_disp, ge4_disp, ndisp : 0x%x, 0x%x, 0x%x\n"
01477             "\n"
01478             "swap, modify, mod_type   : %d, %d, %d\n"
01479             "offset, length, quiet    : %ld, %d, %d\n"
01480             "mod_data                 : %s\n"
01481             "\n",
01482             p->num_files, p->flist, p->debug, p->data_len,
01483             p->ge_disp, p->ge4_disp, p->ndisp, p->swap, p->modify,
01484             p->mod_type, p->offset, p->length, p->quiet,
01485             CHECK_NULL_STR(p->mod_data)
01486           );
01487 
01488     if ( p->debug > 1 )
01489     {
01490         int c;
01491 
01492         printf( "file list: " );
01493         for ( c = 0; c < p->num_files; c ++ )
01494             printf( "'%s' ", p->flist[c] );
01495         printf( "\n" );
01496     }
01497 
01498     return 0;
01499 }
01500 
01501 
01502 /*------------------------------------------------------------
01503  *  Display the contents of the ge_extras struct.
01504  *------------------------------------------------------------
01505 */
01506 int
01507 r_idisp_ge_extras( char * info, ge_extras * E )
01508 {
01509     if ( info )
01510         fputs( info, stdout );
01511 
01512     if ( E == NULL )
01513     {
01514         printf( "r_idisp_ge_extras: E == NULL" );
01515         return -1;
01516     }
01517 
01518     printf( " ge_extras at %p :\n"
01519             "    bpp              = %d\n"
01520             "    cflag            = %d\n"
01521             "    hdroff           = %d\n"
01522             "    skip             = %d\n"
01523             "    swap             = %d\n"
01524             "    (xyz0,xyz1,xyz2) = (%f,%f,%f)\n"
01525             "    (xyz3,xyz4,xyz5) = (%f,%f,%f)\n"
01526             "    (xyz6,xyz7,xyz8) = (%f,%f,%f)\n",
01527             E, E->bpp, E->cflag, E->hdroff, E->skip, E->swap,
01528             E->xyz[0], E->xyz[1], E->xyz[2],
01529             E->xyz[3], E->xyz[4], E->xyz[5],
01530             E->xyz[6], E->xyz[7], E->xyz[8]
01531           );
01532     return 0;
01533 }
01534 
01535 /*------------------------------------------------------------
01536  *  Display the contents of the ge_header_info struct.
01537  *------------------------------------------------------------
01538 */
01539 int
01540 r_idisp_ge_header_info( char * info, ge_header_info * I )
01541 {
01542     if ( info )
01543         fputs( info, stdout );
01544 
01545     if ( I == NULL )
01546     {
01547         printf( "r_idisp_ge_header_info: I == NULL" );
01548         return -1;
01549     }
01550 
01551     printf( " ge_header_info at %p :\n"
01552             "    good        = %d\n"
01553             "    (nx,ny)     = (%d,%d)\n"
01554             "    uv17        = %d\n"
01555             "    (dx,dy,dz)  = (%f,%f,%f)\n"
01556             "    zoff        = %f\n"
01557             "    (tr,te)     = (%f,%f)\n"
01558             "    orients     = %8s\n",
01559             I, I->good, I->nx, I->ny, I->uv17,
01560             I->dx, I->dy, I->dz, I->zoff, I->tr, I->te,
01561             CHECK_NULL_STR(I->orients)
01562           );
01563 
01564     return 0;
01565 }
01566 
01567 
01568 /*------------------------------------------------------------
01569  *  Display the contents of the ge_header_info struct.
01570  *------------------------------------------------------------
01571 */
01572 int
01573 disp_ge_offsets( char * info, ge_off * D )
01574 {
01575     if ( info )
01576         fputs( info, stdout );
01577 
01578     if ( D == NULL )
01579     {
01580         printf( "disp_ge_offsets: D == NULL" );
01581         return -1;
01582     }
01583 
01584     printf( " ge_off at %p :\n"
01585             "    nx, ny, uv17 = %d, %d, %d\n"
01586             "    dx, dy, dz   = %d, %d, %d\n"
01587             "    tr, te, xyz  = %d, %d, %d\n",
01588             D, D->nx, D->ny, D->uv17,
01589             D->dx, D->dy, D->dz,
01590             D->tr, D->te, D->xyz
01591           );
01592 
01593     return 0;
01594 }
01595 
 

Powered by Plone

This site conforms to the following standards: