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  

ge4_header.c

Go to the documentation of this file.
00001 
00002 /* ----------------------------------------------------------------------
00003  * This is an interface for processing GEMS 4.x image files
00004  * (see ge4_header.h for structure contents).
00005  * ----------------------------------------------------------------------
00006  * int ge4_read_header( char * filename, ge4_header * H )
00007  *
00008  *     The basic point is to pass an empty ge4_header structure in,
00009  *     along with a file name.  This function fills the structure.
00010  *
00011  *     One exception: if H->image is non-null, this function will
00012  *                    read the image into that location.
00013  *
00014  *     - returns 0 on success
00015  *
00016  * R. Reynolds  2003 April 29
00017  * ----------------------------------------------------------------------
00018 */
00019 
00020 /* ----------------------------------------------------------------------
00021  * history:
00022  *
00023  * June 12, 2003
00024  *   - fixed static warnings
00025  *
00026  * June 03, 2003
00027  *   - added doxygen style header (for ge4_read_header())
00028  *   - added get_image param to ge4_read_header()
00029  *   - swap bytes in image
00030  *   - added local static for swap_[24]()
00031  * ----------------------------------------------------------------------
00032 */
00033 
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037 
00038 #include "ge4_header.h"
00039 
00040 
00041 /* comes from either Imon.o or libmri.a */
00042 extern unsigned long THD_filesize ( char * pathname );
00043 
00044 /* local protos */
00045 static int swap_2      ( void * ptr );
00046 static int swap_4      ( void * ptr );
00047 static int swap_2_multi( void * ptr, int num_shorts );
00048 
00049 /* ---------------------------------------------------------------------- */
00050 /* series header value descriptions - for display */
00051 
00052 static char * g_ge4_sl_im_modes[] =
00053                         { "2D single", "2D multiple", "3D volume", "cine",
00054                           "spectroscopy" };
00055 static char * g_ge4_sl_pulse_seqs[] =
00056                         { "memp", "ir", "ps", "rm", "rmge", "gre", "vemp",
00057                           "mpgr", "mpgrv", "mpirs", "mpiri", "3d/gre",
00058                           "cine/gre", "spgr", "sspf", "cin/spgr", "3d/spgr",
00059                           "fse", "fve", "fspr", "fgr", "fmpspgr", "fmpgr",
00060                           "fmpir", "probe.s", "probe.p" };
00061 static char * g_ge4_sl_orient[] = { "supine", "prone", "Lt", "Rt" };
00062 
00063 /* ---------------------------------------------------------------------- */
00064 
00065 /*!  Validate and read header data from a GEMS 4.x formatted file.
00066 
00067   \param filename is the name of the file to try to read
00068   
00069   \param H is the address of a ge4_header struct to be initialized and filled
00070 
00071   \param get_image specifies whether to allocate for and read in the image
00072 
00073   \return   0 : on success
00074           < 0 : on error
00075 
00076 */
00077 int ge4_read_header( ge4_header * H, char * filename, int get_image )
00078 {
00079     ge4_image_t  * ih;
00080     ge4_series_t * sh;
00081     ge4_study_t  * st;
00082     FILE         * fp;
00083     int            file_len;
00084     int            rres = 0;            /* read result */
00085 
00086     if ( filename == NULL || H == NULL )
00087     {
00088         fprintf( stderr, "** rg4h : bad params: %p, %p\n", filename, H );
00089         return -1;
00090     }
00091 
00092     file_len = THD_filesize( filename );
00093 
00094     /* file size must be fixed at 145408 bytes (142 KB) */
00095     if ( file_len != (GE4_HEADER_LENGTH + GE4_IMAGE_SIZE) )
00096         return 1;
00097 
00098     /* clear structure */
00099     memset( H, 0, sizeof(ge4_header) );
00100 
00101     if ( (fp = fopen( filename, "r" )) == NULL )
00102     {
00103         fprintf( stderr, "ge4_read_header: failed to open '%s' for reading\n",
00104                  filename);
00105         return -1;
00106     }
00107 
00108     /* quickly scan and validate titles */
00109 
00110     sh = &H->ser_h;     /* set helper pointer */
00111     ih = &H->im_h;      /* set helper pointer */
00112     st = &H->std_h;     /* set helper pointer */
00113 
00114     fseek( fp, GE4_OFF_STDY_TITLE, SEEK_SET );
00115     rres |= (1 - fread( st->title, GE4_L_STDY_TITLE, 1, fp ));
00116 
00117     fseek( fp, GE4_OFF_SER_TITLE, SEEK_SET );
00118     rres |= (1 - fread( sh->title, GE4_L_SER_TITLE, 1, fp ));
00119 
00120     fseek( fp, GE4_OFF_IMG_TITLE, SEEK_SET );
00121     rres |= (1 - fread( ih->title, GE4_L_IM_TITLE, 1, fp ));
00122 
00123     /* if read failure or bad title fields, we're outta' here */
00124     if ( rres                                                     ||
00125          strncmp( st->title, GE4_STUDY_TITLE,  GE4_L_STDY_TITLE ) ||
00126          strncmp( sh->title, GE4_SERIES_TITLE, GE4_L_SER_TITLE  ) ||
00127          strncmp( ih->title, GE4_IMAGE_TITLE,  GE4_L_IM_TITLE   )
00128        )
00129         return 1;
00130 
00131 
00132     /* study header fields */
00133 
00134     fseek( fp, GE4_OFF_STDY_NUM, SEEK_SET );
00135     rres |= (1 - fread( st->num, GE4_L_STDY_NUM, 1, fp ));
00136 
00137     fseek( fp, GE4_OFF_STDY_DATE, SEEK_SET );
00138     rres |= (1 - fread( st->date, GE4_L_STDY_DATE, 1, fp ));
00139 
00140     fseek( fp, GE4_OFF_STDY_TIME, SEEK_SET );
00141     rres |= (1 - fread( st->time, GE4_L_STDY_TIME, 1, fp ));
00142 
00143     fseek( fp, GE4_OFF_STDY_PAT_NAME, SEEK_SET );
00144     rres |= (1 - fread( st->pat_name, GE4_L_STDY_PAT_NAME, 1, fp ));
00145 
00146     fseek( fp, GE4_OFF_STDY_PAT_ID, SEEK_SET );
00147     rres |= (1 - fread( st->pat_id, GE4_L_STDY_PAT_ID, 1, fp ));
00148 
00149     fseek( fp, GE4_OFF_STDY_AGE, SEEK_SET );
00150     rres |= (1 - fread( st->age, GE4_L_STDY_AGE, 1, fp ));
00151 
00152     fseek( fp, GE4_OFF_STDY_SEX, SEEK_SET );
00153     rres |= (1 - fread( &st->sex, 1, 1, fp ));
00154 
00155     /* series header fields */
00156 
00157     fseek( fp, GE4_OFF_SER_SERIES_NUM, SEEK_SET );
00158     rres |= (1 - fread( sh->series_num, GE4_L_SER_SER_NUM, 1, fp ));
00159 
00160     fseek( fp, GE4_OFF_SER_PLANE_TYPE, SEEK_SET );
00161     rres |= (1 - fread( &sh->plane_type, sizeof(sh->plane_type), 1, fp ));
00162 
00163     fseek( fp, GE4_OFF_SER_PLANE_DESC, SEEK_SET );
00164     rres |= (1 - fread( sh->plane_desc, GE4_L_SER_PL_DESC, 1, fp ));
00165 
00166     fseek( fp, GE4_OFF_SER_IM_MODE, SEEK_SET );
00167     rres |= (1 - fread( &sh->im_mode, sizeof(sh->im_mode), 1, fp ));
00168 
00169     fseek( fp, GE4_OFF_SER_PULSE_SEQ, SEEK_SET );
00170     rres |= (1 - fread( &sh->pulse_seq, sizeof(sh->pulse_seq), 1, fp ));
00171 
00172     fseek( fp, GE4_OFF_SER_FOV, SEEK_SET );
00173     rres |= (1 - fread( &sh->fov, sizeof(sh->fov), 1, fp ));
00174 
00175     fseek( fp, GE4_OFF_SER_CENTER, SEEK_SET );
00176     rres |= (1 - fread( sh->center, sizeof(sh->center), 1, fp ));
00177 
00178     fseek( fp, GE4_OFF_SER_ORIENT, SEEK_SET );
00179     rres |= (1 - fread( &sh->orient, sizeof(sh->orient), 1, fp ));
00180 
00181     fseek( fp, GE4_OFF_SER_SCAN_MAT_X, SEEK_SET );
00182     rres |= (1 - fread( &sh->scan_mat_x, sizeof(sh->scan_mat_x), 1, fp ));
00183 
00184     fseek( fp, GE4_OFF_SER_SCAN_MAT_Y, SEEK_SET );
00185     rres |= (1 - fread( &sh->scan_mat_y, sizeof(sh->scan_mat_y), 1, fp ));
00186 
00187     fseek( fp, GE4_OFF_SER_IM_MAT, SEEK_SET );
00188     rres |= (1 - fread( &sh->im_mat, sizeof(sh->im_mat), 1, fp ));
00189 
00190 
00191     /* image header fields */
00192 
00193     fseek( fp, GE4_OFF_IMG_IM_NUM, SEEK_SET );
00194     rres |= (1 - fread( ih->im_num, GE4_L_IM_NUM, 1, fp ));
00195 
00196     fseek( fp, GE4_OFF_IMG_IM_LOCN, SEEK_SET );
00197     rres |= (1 - fread( &ih->im_loc, sizeof(ih->im_loc), 1, fp ));
00198 
00199     fseek( fp, GE4_OFF_IMG_TABLE_POSN, SEEK_SET );
00200     rres |= (1 - fread( &ih->table_posn, sizeof(ih->table_posn), 1, fp ));
00201 
00202     fseek( fp, GE4_OFF_IMG_IM_THICK, SEEK_SET );
00203     rres |= (1 - fread( &ih->im_thickness, sizeof(ih->im_thickness), 1, fp ));
00204 
00205     fseek( fp, GE4_OFF_IMG_IM_SPACING, SEEK_SET );
00206     rres |= (1 - fread( &ih->im_spacing, sizeof(ih->im_spacing), 1, fp ));
00207 
00208     fseek( fp, GE4_OFF_IMG_TR, SEEK_SET );
00209     rres |= (1 - fread( &ih->tr, sizeof(ih->tr), 1, fp ));
00210 
00211     fseek( fp, GE4_OFF_IMG_TE, SEEK_SET );
00212     rres |= (1 - fread( &ih->te, sizeof(ih->te), 1, fp ));
00213 
00214     fseek( fp, GE4_OFF_IMG_TI, SEEK_SET );
00215     rres |= (1 - fread( &ih->ti, sizeof(ih->ti), 1, fp ));
00216 
00217     fseek( fp, GE4_OFF_IMG_NUM_ECHOS, SEEK_SET );
00218     rres |= (1 - fread( &ih->num_echoes, sizeof(ih->num_echoes), 1, fp ));
00219 
00220     fseek( fp, GE4_OFF_IMG_ECHO_NUM, SEEK_SET );
00221     rres |= (1 - fread( &ih->echo_num, sizeof(ih->echo_num), 1, fp ));
00222 
00223     fseek( fp, GE4_OFF_IMG_NEX_INT, SEEK_SET );
00224     rres |= (1 - fread( &ih->iNEX, sizeof(ih->iNEX), 1, fp ));
00225 
00226     fseek( fp, GE4_OFF_IMG_NEX_REAL, SEEK_SET );
00227     rres |= (1 - fread( &ih->fNEX, sizeof(ih->fNEX), 1, fp ));
00228 
00229     fseek( fp, GE4_OFF_IMG_FLIP_ANGLE, SEEK_SET );
00230     rres |= (1 - fread( &ih->flip_angle, sizeof(ih->flip_angle), 1, fp ));
00231 
00232     if ( rres )
00233     {
00234         fprintf( stderr, "** failed to read ge4 header for '%s'\n", filename );
00235         return -1;
00236     }
00237 
00238     if ( ge4_validate_header( H ) )
00239         return 1;
00240 
00241     if ( get_image )
00242     {
00243         if ( (H->image = (short *)malloc( GE4_IMAGE_SIZE )) == NULL )
00244         {
00245             fprintf( stderr, "** failed to allocate %d bytes for image\n",
00246                      GE4_IMAGE_SIZE );
00247             return -1;
00248         }
00249 
00250         fseek( fp, GE4_HEADER_LENGTH, SEEK_SET );
00251         rres = fread( H->image, GE4_IMAGE_SIZE, 1, fp );
00252 
00253         if ( rres != 1 )
00254         {
00255             fprintf( stderr, "** failed to read ge4 image for file '%s'\n",
00256                      filename );
00257             free( H->image );
00258             return -1;
00259         }
00260 
00261         H->im_bytes = GE4_IMAGE_SIZE;          /* note it for "outsiders" */
00262 
00263         if ( H->swap )
00264             swap_2_multi( H->image, GE4_IMAGE_SIZE/2 );
00265     }
00266 
00267     return 0;
00268 }
00269 
00270 
00271 /*------------------------------------------------------------
00272  *  Check for valid data in the header.
00273  *
00274  *  If values are out of range, try byte swapping.
00275  *
00276  *  series header:
00277  *      plane_type      : in {0..4}
00278  *      image_mode      : in {0..4}
00279  *      pulse_seq       : in {0..25}
00280  *
00281  *  return    0 : valid
00282  *         else : invalid
00283  *------------------------------------------------------------
00284 */
00285 int ge4_validate_header( ge4_header * h )
00286 {
00287     ge4_series_t * s;
00288     ge4_image_t  * im;
00289 
00290     if ( h == NULL )
00291         return -1;
00292 
00293     s  = &h->ser_h;
00294     im = &h->im_h;
00295 
00296     /* note that titles have already been validated */
00297 
00298     if ( (s->plane_type < 0) || (s->plane_type > 4) ||
00299          (s->im_mode    < 0) || (s->im_mode    > 4) ||
00300          (s->pulse_seq  < 0) || (s->pulse_seq  > 25) )
00301     {
00302         ge4_swap_all_bytes( h );
00303     }
00304 
00305     /* if these are still off, we are hosed... */
00306     if ( (s->plane_type < 0) || (s->plane_type > 4) ||
00307          (s->im_mode    < 0) || (s->im_mode    > 4) ||
00308          (s->pulse_seq  < 0) || (s->pulse_seq  > 25) )
00309     {
00310         return -1;
00311     }
00312 
00313     return 0;
00314 }
00315 
00316 
00317 /*------------------------------------------------------------
00318  *  Swap all numeric fields in ge4_header sub-structs.
00319  *------------------------------------------------------------
00320 */
00321 int ge4_swap_all_bytes( ge4_header * h )
00322 {
00323     if ( h == NULL )
00324     {
00325         fprintf( stderr, "** ge4_SAB : no header!\n" );
00326         return -1;
00327     }
00328 
00329     h->swap = 1;                /* note that we have swapped */
00330 
00331     /* series header */
00332 
00333     swap_2( &h->ser_h.plane_type );
00334     swap_2( &h->ser_h.im_mode );
00335     swap_2( &h->ser_h.pulse_seq );
00336 
00337     swap_4( &h->ser_h.fov );
00338     swap_4( &h->ser_h.center[0] );
00339     swap_4( &h->ser_h.center[1] );
00340     swap_4( &h->ser_h.center[2] );
00341 
00342     swap_2( &h->ser_h.orient );
00343     swap_2( &h->ser_h.scan_mat_x );
00344     swap_2( &h->ser_h.scan_mat_y );
00345     swap_2( &h->ser_h.im_mat );
00346 
00347     /* image header */
00348 
00349     swap_4( &h->im_h.im_loc );
00350     swap_4( &h->im_h.table_posn );
00351     swap_4( &h->im_h.im_thickness );
00352     swap_4( &h->im_h.im_spacing );
00353 
00354     swap_4( &h->im_h.tr );
00355     swap_4( &h->im_h.te );
00356     swap_4( &h->im_h.ti );
00357 
00358     swap_2( &h->im_h.num_echoes );
00359     swap_2( &h->im_h.echo_num );
00360 
00361     swap_2( &h->im_h.iNEX );
00362     swap_4( &h->im_h.fNEX );
00363 
00364     swap_2( &h->im_h.flip_angle );
00365 
00366     return 0;
00367 }
00368 
00369 
00370 /*------------------------------------------------------------
00371  *  Display the contents of the ge4_image_t struct.
00372  *------------------------------------------------------------
00373 */
00374 int idisp_ge4_study_header( char * info, ge4_study_t * st )
00375 {
00376     if ( info )
00377         fputs( info, stdout );
00378 
00379     if ( st == NULL )
00380     {
00381         printf( "r_idisp_ge4_study_t: st == NULL" );
00382         return -1;
00383     }
00384 
00385     printf( " ge4_study_t at %p :\n"
00386             "    title                    = %s\n"
00387             "    num                      = %s\n"
00388             "    date                     = %s\n"
00389             "    time                     = %s\n"
00390             "    pat_name                 = %s\n"
00391             "    pat_id                   = %s\n"
00392             "    age                      = %s\n"
00393             "    sex                      = %c\n",
00394             st, st->title, st->num, st->date, st->time,
00395             st->pat_name, st->pat_id, st->age, st->sex
00396             );
00397 
00398     return 0;
00399 }
00400 
00401 
00402 /*------------------------------------------------------------
00403  *  Display the contents of the ge4_image_t struct.
00404  *------------------------------------------------------------
00405 */
00406 int idisp_ge4_image_header( char * info, ge4_image_t * im )
00407 {
00408     if ( info )
00409         fputs( info, stdout );
00410 
00411     if ( im == NULL )
00412     {
00413         printf( "r_idisp_ge4_image_t: im == NULL" );
00414         return -1;
00415     }
00416 
00417     printf( " ge4_image_t at %p :\n"
00418             "    title                    = %s\n"
00419             "    im_num                   = %s\n"
00420             "    im_loc                   = %.3f\n"
00421             "    table_posn               = %.3f\n"
00422             "    im_thickness             = %.3f\n"
00423             "    im_spacing               = %.3f\n"
00424             "    tr (in ms)               = %.3f\n"
00425             "    te (in ms)               = %.3f\n"
00426             "    ti (in ms)               = %.3f\n"
00427             "    num_echoes               = %d\n"
00428             "    echo_num                 = %d\n"
00429             "    iNEX                     = %d\n"
00430             "    fNEX                     = %.3f\n"
00431             "    flip_angle               = %d\n",
00432             im, im->title, im->im_num, im->im_loc, im->table_posn,
00433             im->im_thickness, im->im_spacing, im->tr, im->te, im->ti,
00434             im->num_echoes, im->echo_num, im->iNEX, im->fNEX, im->flip_angle
00435             );
00436 
00437     return 0;
00438 }
00439 
00440 
00441 /*------------------------------------------------------------
00442  *  Display the contents of the ge4_series_t struct.
00443  *------------------------------------------------------------
00444 */
00445 int idisp_ge4_series_header( char * info, ge4_series_t * s )
00446 {
00447     if ( info )
00448         fputs( info, stdout );
00449 
00450     if ( s == NULL )
00451     {
00452         printf( "r_idisp_ge4_series_t: s == NULL" );
00453         return -1;
00454     }
00455 
00456     printf( " ge4_series_t at %p :\n"
00457             "    title                    = %s\n"
00458             "    series_num               = %s\n"
00459             "    plane_type, plane_desc   = %d, %s\n"
00460             "    image_mode               = %d (%s)\n"
00461             "    pulse_seq                = %d (%s)\n"
00462             "    FOV (in mm)              = %.3f\n"
00463             "    center[0], c[1], c[2]    = %.3f, %.3f, %.3f\n"
00464             "    orient                   = %d (%s)\n"
00465             "    scan_mat_x, scan_mat_y   = %d, %d\n"
00466             "    im_mat                   = %d\n",
00467             s, s->title, s->series_num, s->plane_type, s->plane_desc,
00468             s->im_mode, GE4M_IND2STR(s->im_mode, g_ge4_sl_im_modes),
00469             s->pulse_seq, GE4M_IND2STR(s->pulse_seq, g_ge4_sl_pulse_seqs),
00470             s->fov, s->center[0], s->center[1], s->center[2],
00471             s->orient, GE4M_IND2STR(s->orient,g_ge4_sl_orient),
00472             s->scan_mat_x, s->scan_mat_y, s->im_mat
00473             );
00474 
00475     return 0;
00476 }
00477 
00478 
00479 /*------------------------------------------------------------
00480  *  Swap multiple byte pairs.
00481  *------------------------------------------------------------
00482 */
00483 static int swap_2_multi( void * ptr, int num_shorts )
00484 {
00485     unsigned char * cp0, * cp1;
00486     unsigned char   tmpc;
00487     int             index;
00488 
00489     if ( ptr == NULL ) return -1;
00490 
00491     cp0 = (unsigned char *)ptr;
00492     cp1 = cp0 + 1;
00493 
00494     for ( index = 0; index < num_shorts; index++ )
00495     {
00496         tmpc = *cp0;
00497         *cp0 = *cp1;
00498         *cp1 = tmpc;
00499 
00500         cp0 += 2;
00501         cp1 += 2;
00502     }
00503 
00504     return 0;
00505 }
00506 
00507 
00508 /*------------------------------------------------------------
00509  * Reverse the order of the 4 bytes at this address.
00510  *------------------------------------------------------------
00511 */
00512 static int swap_4( void * ptr )         /* destructive */
00513 {
00514    unsigned char * addr = ptr;
00515 
00516    addr[0] ^= addr[3]; addr[3] ^= addr[0]; addr[0] ^= addr[3];
00517    addr[1] ^= addr[2]; addr[2] ^= addr[1]; addr[1] ^= addr[2];
00518 
00519    return 0;
00520 }
00521 
00522 /*------------------------------------------------------------
00523  * Reverse the order of the 2 bytes at this address.
00524  *------------------------------------------------------------
00525 */
00526 static int swap_2( void * ptr )         /* destructive */
00527 {
00528    unsigned char * addr = ptr;
00529 
00530    addr[0] ^= addr[1]; addr[1] ^= addr[0]; addr[0] ^= addr[1];
00531 
00532    return 0;
00533 }
00534 
00535 
 

Powered by Plone

This site conforms to the following standards: