Subject: Medical Image Format FAQ, Part 5/8
Date: 8 Aug 1997 05:28:54 -0400
Summary: This posting contains answers to the most Frequently Asked
. Question on alt.image.medical - how do I convert from image
. format X from vendor Y to something I can use ? In addition
. it contains information about various standard formats.

Archive-name: medical-image-faq/part5
Posting-Frequency: monthly
Mon Aug  4 17:09:50 CDT 1997
Version: 3.16

    3.4 Proprietary Workstations

.3.4.1 ISG Workstations

.      3.4.1.1 Gyroview


..      The Philips Gyroview workstation is a high-resolution
..      graphical workstation for MR images from Gyroscan
..      scanners, that can also handle CT images and other
..      modalities, and has an optional package for three
..      dimensional processing of images. It is based on a Sun
..      SPARC system with proprietary graphics hardware. The
..      software is actually written by ISG in Canada. The image
..      format is an ACR/NEMA based format with various private
..      tags defined, and a proprietary scheme of image
..      compression that has me stumped. I am told by some that
..      there is no means of telling the Gyroview not to compress
..      the images.


..     I use compress in the sense that includes packing four 12
..     bit words into three 16 bit big-endian words, which
..     appears to be part of the scheme in use. Unfortunately,
..     some form of perimeter encoding is also in use, and I just
..     can't figure it out :( Some people have had more luck
..     using "the export utility of the Gyroview" to produce just
..     12 bit packed images without the perimeter encoding. I
..     don't know whether this is a standard feature of the
..     workstation or not. Others have suggested looking in the
..     "/isg/3dmr/DataRoot/tscript/" directory for hints.


..      Despite prolonged exchanges of email it seems that the
..      formal decision is not to release the format. Customers
..      may contact ISG at harry@isgtec.com(Harry Visser) to
..      bitch about this and then give up and ask for information
..      on how to obtain a software package called the External
..      Developers Tool which contains a tool called xdimage
..      which can only be used on ISG's proprietary hardware.
..      This is free to customers. It does however only export to
..      (and import from) a flat file format and ascii
..      description, not an ACR/NEMA style file with uncompressed
..      pixel data :(.


..      I would still prefer to know the format, as people keep
..      asking (these machines were pretty popular I gather), and
..      if anyone has any hints about the data format, I would
..      appreciate them. Here follows part of a reply to one of
..      these people when I made an unsuccesful attempt to figure
..      this out:


..      Firstly, I presume this file is generated by a Philips
..      Gyroview workstation judging by ...


(0008,0070) LO Manufacturer  VR=<LO>  VL=<8>  <GYROVIEW>


..      The file says it is an MRI image ...


(0008,0060) CS Modality  VR=<CS>  VL=<2>  <MR>


..      and yet it is missing many of the mri attributes normally
..      present. Also it includes some CT specific attributes,
..      notably ...


(0018,1120) DS GantryDetectorTilt  VR=<DS>  VL=<2>  < 0>


..      which is pretty weird. I presume that this format is
..      generated by something purely for the purposes of 3D
..      reconstruction and only the attributes needed for that
..      have been preserved.


..      The image appears to be 512*512 ...


(0028,0010) US Rows     VR=<US>  VL=<2>  [200]
(0028,0011) US Columns  VR=<US>  VL=<2>  [200]


..      As far as the compression format is concerned ...


(0028,0060) CS CompressionCode  VR=<CS>  VL=<2>  < 2>


..      is not in itself a valid ACR/NEMA value, and hence some
..      proprietary variation is in use. The most important clue
..      is ...


(0028,0040) CS ImageFormat  VR=<CS>  VL=<4>  <CIRC>


..      which is also not valid ACR/NEMA (only RECT is
..      permitted). From this I conclude that some sort of
..      'circular' perimeter encoding scheme is in use that only
..      sends the meaningful central pixels in each row and
..      leaves out the background. This is substantiated by the
..      fact that the image pixel data seems to be preceded by a
..      table of 257 long words in ascending order, each value
..      separated by relatively low values (80-100 or so). I
..      suspect that these are pointers into the data to the
..      start of each row...


% od -x I011_1_001 +1404 | more
0001404  0000 0202 0000 0252 0000 02a2 0000 02f2
0001424  0000 0342 0000 0392 0000 03e2 0000 0432
0001444  0000 0482 0000 04d2 0000 0522 0000 0572
0001464  0000 05c2 0000 0612 0000 0662 0000 06b3
0001504  0000 0705 0000 0757 0000 07ab 0000 0800
0001524  0000 0857 0000 08ae 0000 0905 0000 095e ...

[0000] 000514 -> 000514
[0001] 000594 -> 000080
[0002] 000674 -> 000080
[0003] 000754 -> 000080
[0004] 000834 -> 000080
[0005] 000914 -> 000080

 ...

[0155] 015322 -> 000103
[0156] 015425 -> 000103
[0157] 015527 -> 000102
[0158] 015629 -> 000102

 ...

[0254] 024484 -> 000080
[0255] 024564 -> 000080
[0256] 024564 -> 000000


..      The first of these values seems to be a pointer in two
..      byte word units past the table, the entries for a series
..      of rows, then a final "257th" value that is the same as
..      the preceding with a difference of zero, possibly
..      flagging the end of the table.


..      What confuses me is the fact that there are 256 or so
..      entries rather than 512 (number of rows), and that the
..      difference values are relatively small for 512 columns.
..      Perhaps each entry applies to two successive rows though
..      this seems rather peculiar.


..      Furthermore, if it is true that the units are two byte
..      words, then the last pointer value is much lower than the
..      number of remaining bytes in the image pixel data
..      attribute, so what are all the other bytes for ?


..      The other thing that is going to make extraction
..      difficult is the fact that the data are supposed to be 12
..      bits packed into 16 bit words ...


(0028,0100) US BitsAllocated  VR=<US>  VL=<2>  [c]
(0028,0101) US BitsStored     VR=<US>  VL=<2>  [c]
(0028,0102) US HighBit        VR=<US>  VL=<2>  [b]


..      Hence 3 two byte words are used to store 4 12 bit pixels.
..      It may not be easy to figure out in what order this
..      packing is performed. The ACR/NEMA standard has an
..      example of its intent in this case, but the byte order
..      was never specified for this standard, which had a 16 bit
..      hardware data path and was not originally intended for
..      offline data storage in bytes, so there are a number of
..      possible permutations to deal with :(


..      Finally I don't know what to make of the "private" tags
..      ...


Unrecognized (0029,0010)  VR=<LT>  VL=<a> <ISG shadow>
Unrecognized (0029,1070)  VR=<LT>  VL=<6> < 49128>
Unrecognized (0029,1080)  VR=<LT>  VL=<6> <123432>
Unrecognized (0029,1090)  VR=<LT>  VL=<2> < 0>


..      which presumably have some significance or they wouldn't
..      be there !

.3.4.1 GE Workstations

.      3.4.2.1 GE Advantage Windows


..      The GE Advantage Windows workstation uses the same header
..      layout as the Genesis CT and MR systems. One very
..      important proviso though is that the same C header file
..      to describe the layout was compiled on the sparc (sun4)
..      rather than Genesis (sun3) architecture, and hence,
..      unlike the Genesis files, 32 bit integers (include dates
..      and times) and 32 bit floats are aligned on 4 byte
..      boundaries and 64 bit floats are aligned on 8 bit
..      boundaries. In other words the sequence of fields is the
..      same but the offsets are different. Very annoying. For
..      details see the GE MR Signa 5.x - Genesis description.
..      For details of the sun data types, see Sun.


..      The order of the headers is the same as on the archives
..      (DAT, WORM or OD), ie. not the same as the ximg layout.
..      Furthermore, the lengths are slightly different from
..      Genesis, due to the word alignement business, and also
..      different for CT as opposed to MR (different length of
..      the image header), so finding the file header (pixel data
..      header) can be a bit of a chore. The offsets from the
..      start of the file for each are as follows:


..      For CT:

...    0 Suite header
...  116 Exam header
... 1156 Series header
... 2184 Image header
... 3240 File (Pixel Data) header

..      For MR:

...    0 Suite header
...  116 Exam header
... 1156 Series header
... 2184 Image header
... 3228 File (Pixel Data) header



..      Identifying the files is a nuisance because the "IMGF"
..      string doesn't appear until offset 3240 dec for the CT
..      and offset 3228 dec for the MR, unlike the Genesis ximg
..      form.


..      Also, even though the headers are in the "archive" order,
..      the 4 byte pixel data length field that is prepended to
..      the image pixel data itself in the archives, is NOT
..      present on Advantage Windows, just as it is absent from
..      Genesis ximg files. In other words you do not have to add
..      4 to the file header length field to find the start of
..      the pixel data. Obviously you do have to add the offset
..      of the file header itself though ! Don't forget to add
..      this to the offset of the unpack tables also. The pixel
..      data itself is compressed the same way as Genesis.


..      It is recommended that you use the readily available
..      Genesis documentation if trying to extract information
..      from the headers, or use the "ximg -h" command on a
..      Genesis system to generate a C header. For the truly
..      masochistic, or desperately impatient, here is a summary
..      of the some of the fields for Advantage Windows as were
..      described for Genesis CT and MR, with the corrections for
..      word alignment applied:


.exam header:

..0   - char[4]  - suite ID
..8   - u_short  - exam number
..88  - char[13] - patient ID
..101 - char[25] - patient name
..126 - short    - patient age
..130 - short    - patient sex
..309 - char[3]  - exam type - "MR" or "CT"

.series header:

..10  - short    - series number
..84  - char[3]  - anatomical reference
..92  - char[25] - scan protocol name

.image header - common to CT and MR:

..12  - short    - image number
..28  - float    - slice thickness mm
..32  - short    - matrix size - X
..34  - short    - matrix size - Y
..36  - float    - display field of view - X (mm)
..40  - float    - display field of view - Y (mm)
..44  - float    - image dimension - X
..48  - float    - image dimension - Y
..52  - float    - pixel size - X
..56  - float    - pixel size - Y
..60  - char[14] - pixel data ID
..74  - char[17] - iv contrast agent
..91  - char[17] - oral contrast agent

..132 - float    - image location
..136 - float    - image centre R mm (ie. X +ve to right)
..140 - float    - image centre A mm (ie. Y +ve to anterior)
..144 - float    - image centre S mm (ie. Z +ve to superior)
..160 - float    - image TLHC R mm (ie. X +ve to right)
..164 - float    - image TLHC A mm (ie. Y +ve to anterior)
..168 - float    - image TLHC S mm (ie. Z +ve to superior)
..172 - float    - image TRHC R mm (ie. X +ve to right)
..176 - float    - image TRHC A mm (ie. Y +ve to anterior)
..180 - float    - image TRHC S mm (ie. Z +ve to superior)
..184 - float    - image BRHC R mm (ie. X +ve to right)
..188 - float    - image BRHC A mm (ie. Y +ve to anterior)
..192 - float    - image BRHC S mm (ie. Z +ve to superior)

.image header - for MR (1044 bytes long):

..200 - int      - repetition time(usec)
..204 - int      - inversion time(usec)
..208 - int      - echo time(usec)
..216 - short    - number of echoes
..218 - short    - echo number
..224 - float    - NEX
..320 - char[33] - pulse sequence name
..376 - char[17] - coil name
..660 - short    - ETL for FSE

.image header - for CT (1056 bytes long):

..200 - float    - table start Location
..204 - float    - table end Location
..208 - float    - table speed (mm/sec)
..212 - float    - table height
..232 - float    - gantry tilt (degrees)

    3.5 Other Proprietary Formats

.3.5.1 Analyze From Mayo

.      This very popular software package is produced by the Biomedical
.      Imaging Resource group at the Mayo Clinic/Foundation. I have
.      always thought they should give it away but they don't, it is
.      moderately expensive, though less so than some other
.      alternatives. If you want to test or buy it try contacting Denny
.      Hanson dph@mayo.edu who is extremely helpful. See also the web
.      site at ANALYZE from Mayo.


.      Anyway, importing images into Analyze is a drag and you have to
.      convert your files to their format, but it isn't very difficult.
.      I hear that some other programs also use their format but haven't
.      encountered them myself. Anyway, the package is sufficiently
.      commonly used that it seems appropriate to include the format
.      here.


.      This information is included verbatim from what was sent to me by
.      Ellis Workman elw@mayo.edu and if you have problems I am sure he
.      will be able to help. I haven't tested it because I can't afford
.      to buy a copy myself :( That's a hint, Denny.


ANALYZE IMAGE FILE FORMAT

ANALYZE image file sets consist of at least 2 files:
.- an image file
.- a header file
.- a color lookup file   * optional

For the Analyze image file set "foo" there are two files:
.foo.img & foo.hdr  (optionally foo.lkup)

The ANALYZE programs refer to this file set as a single entity.

       The Image File (foo.img)

The format of the image file is very simple; containging usually
uncompressed voxel data for the images in one of the several
possible voxel formats:
.- 1 bit  packed binary (slices begin on byte boundaries)
.- 8 bit  (unsigned char) gray scale unless .lkup file present
.- 16 bit signed short
.- 32 bit signed integers or float
.- 24 bit RGB, 8 bits per channel

The header file is a 'C' structure which describes the dimensions
and properties of the voxel data.  This structure follows:


/*
 *
 * (c) Copyright, 1986-1995
 * Biomedical Imaging Resource
 * Mayo Foundation
 *
 * dbh.h
 *
 *
 * database sub-definitions
 */

struct header_key                       /*      header_key       */
    {                                           /* off + size*/
.int sizeof_hdr;                         /* 0 + 4     */
.char data_type[10];                     /* 4 + 10    */
.char db_name[18];                       /* 14 + 18   */
.int extents;                            /* 32 + 4    */
.short int session_error;                /* 36 + 2    */
.char regular;                           /* 38 + 1    */
.char hkey_un0;                          /* 39 + 1    */
    };                                          /* total=40  */

struct image_dimension                  /*      image_dimension  */
    {                                           /* off + size*/
.short int dim[8];                       /* 0 + 16    */
.char vox_units[4];                      /* 16 + 4    */
.char cal_units[8];                      /* 20 + 4    */
.short int unused1;                      /* 24 + 2    */
.short int datatype;                     /* 30 + 2    */
.short int bitpix;                       /* 32 + 2    */
.short int dim_un0;                      /* 34 + 2    */
.float pixdim[8];                        /* 36 + 32   */
.../*
....pixdim[] specifies the voxel dimensions:
....pixdim[1] - voxel width
....pixdim[2] - voxel height
....pixdim[3] - interslice distance
.......etc
...*/
.float vox_offset;                       /* 68 + 4    */
.float funused1;                         /* 72 + 4    */
.float funused2;                         /* 76 + 4    */
.float funused3;                         /* 80 + 4    */
.float cal_max;                          /* 84 + 4    */
.float cal_min;                          /* 88 + 4    */
.int compressed;                         /* 92 + 4    */
.int verified;                           /* 96 + 4    */
.int glmax, glmin;                       /* 100 + 8   */
    };                                          /* total=108 */

struct data_history                     /*      data_history     */
    {                                           /* off + size*/
.char descrip[80];                       /* 0 + 80    */
.char aux_file[24];                      /* 80 + 24   */
.char orient;                            /* 104 + 1   */
.char originator[10];                    /* 105 + 10  */
.char generated[10];                     /* 115 + 10  */
.char scannum[10];                       /* 125 + 10  */
.char patient_id[10];                    /* 135 + 10  */
.char exp_date[10];                      /* 145 + 10  */
.char exp_time[10];                      /* 155 + 10  */
.char hist_un0[3];                       /* 165 + 3   */
.int views;                              /* 168 + 4   */
.int vols_added;                         /* 172 + 4   */
.int start_field;                        /* 176 + 4   */
.int field_skip;                         /* 180 + 4   */
.int omax,omin;                          /* 184 + 8   */
.int smax,smin;                          /* 192 + 8   */
    };                                          /* total=200 */

struct dsr                              /*      dsr              */
    {                                           /* off + size*/
.struct header_key hk;                   /* 0 + 40    */
.struct image_dimension dime;            /* 40 + 108  */
.struct data_history hist;               /* 148 + 200 */
    };                                          /* total=348 */


Comments:
.struct header_key
..int sizeof_header   /* must indicate size of header file */
..int extants;        /* should be 16384 */
..char regular;       /* 'r' */


.struct image_dimension struct decribes the organization and
.side of images. These elements enable IO routines to reference
.images by volume and slice number.

..short int dim[]  /* array of image dimensions */
...dim[0]        /* number of dimensions; usually 4 */
...dim[1]        /* image width */
...dim[2]        /* image height */
...dim[3]        /* volume depth */
...dim[4]        /* volumes in file */

..char vox_units[4] /* labels voxerl spatial unit */
..char cal_units[4] /* labels voxel calibration unit */
..short int datatype /* Acceptable values are */

#define DT_NONE                         0
#define DT_UNKNOWN                      0
#define DT_BINARY                       1
#define DT_UNSIGNED_CHAR        2
#define DT_SIGNED_SHORT         4
#define DT_SIGNED_INT           8
#define DT_FLOAT                        16
#define DT_COMPLEX                      32
#define DT_DOUBLE                       64
#define DT_RGB                          128
#define DT_ALL                          255

..short int bitpix     /* bits per pixel */
..float pixdim[]  /* parallel array to dim giving voxel
..dimensions
....   in each dimension */
... pixdim[1]  /* voxel width */
... pixdim[2]  /* voxel height */
... pixdim[3]  /* voxel depth or slice thickness */

..float vox_offset; /* byte offset in the .img file at which
....     voxels start. If value is negative
....     specifies that the absolute value
....     is applied for every image in the file. */

..float calibrated Max & Min /* specify range of calibration
..values */
..int glmax, glmin    /* the max and min values for entire data
..set */


The data_history substructure is not required, but the 'orient' element
is used to indicate individual slice orientation and determines whether
the ANALYZE 'Movie' program will attempt to flip the images before
displaying a movie sequence.
.orient:
...0 - transverse unflipped
...1 - coronal unflipped
...2 - sagittal unflipped
...3 - transverse flipped
...4 - coronal flipped
...5 - sagittal flipped



The following 'C' program creates an Analyze .hdr file.


/*
 * (c) Copyright, 1986-1994
 * Biomedical Imaging Resource
 * Mayo Foundation
 *
 *
 */

#include
#include "dbh.h"

main(argc,argv) /* file x y z t datatype max min */
int argc;
char **argv;
{
    int i;
    struct dsr hdr;
    FILE *fp;
    static char DataTypes[9][12] = {"UNKNOWN", "BINARY", "CHAR", "SHORT",
    "INT",
....    "FLOAT", "COMPLEX", "DOUBLE", "RGB"};

    static int DataTypeSizes[9] = {0,1,8,16,32,32,64,64,24};

    if(argc != 9)
    {
.usage();
.exit(0);
    }
    memset(&hdr,0, sizeof(struct dsr));
    for(i=0;i<8;i++)
.hdr.dime.pixdim[i]=0.0;

    hdr.dime.vox_offset = 0.0;
    hdr.dime.roi_scale   = 1.0;
    hdr.dime.funused1    = 0.0;
    hdr.dime.funused2    = 0.0;
    hdr.dime.cal_max     = 0.0;
    hdr.dime.cal_min     = 0.0;


    hdr.dime.datatype = -1;

    for(i=1;i<=8;i++)
.if(!strcmp(argv[6],DataTypes[i]))
.{
..hdr.dime.datatype = (1<<(i-1));
..hdr.dime.bitpix = DataTypeSizes[i];
..break;
.}

    if(hdr.dime.datatype <= 0)
    {
.printf(" is an unacceptable datatype \n\n", argv[6]);
.usage();
.exit(0);
    }

    if((fp=fopen(argv[1],"w"))==0)
    {
.printf("unable to create: %s\n",argv[1]);
.exit(0);
    }

    hdr.dime.dim[0] = 4;  /* all Analyze images are taken as 4 dimensional */
    hdr.hk.regular = 'r';
    hdr.hk.sizeof_hdr = sizeof(struct dsr);

    hdr.dime.dim[1] = atoi(argv[2]);  /* slice width  in pixels */
    hdr.dime.dim[2] = atoi(argv[3]);  /* slice height in pixels */
    hdr.dime.dim[3] = atoi(argv[4]);  /* volume depth in slices */
    hdr.dime.dim[4] = atoi(argv[5]);  /* number of volumes per file */

    hdr.dime.glmax  = atoi(argv[7]);  /* maximum voxel value  */
    hdr.dime.glmin  = atoi(argv[8]);  /* minimum voxel value */

/*      Set the voxel dimension fields:
       A value of 0.0 for these fields implies that the value is unknown.
. Change these values to what is appropriate for your data
. or pass additional command line arguments     */

    hdr.dime.pixdim[1] = 0.0; /* voxel x dimension */
    hdr.dime.pixdim[2] = 0.0; /* voxel y dimension */
    hdr.dime.pixdim[3] = 0.0; /* pixel z dimension, slice thickness */

/*   Assume zero offset in .img file, byte at which pixel
       data starts in the image file */

    hdr.dime.vox_offset = 0.0;

/*   Planar Orientation;    */
/*   Movie flag OFF: 0 = transverse, 1 = coronal, 2 = sagittal
     Movie flag ON:  3 = transverse, 4 = coronal, 5 = sagittal  */

    hdr.hist.orient     = 0;

/*   up to 3 characters for the voxels units label; i.e.
.mm., um., cm.               */

    strcpy(hdr.dime.vox_units," ");

/*   up to 7 characters for the calibration units label; i.e. HU */

    strcpy(hdr.dime.cal_units," ");

/*     Calibration maximum and minimum values;
       values of 0.0 for both fields imply that no
       calibration max and min values are used    */

    hdr.dime.cal_max = 0.0;
    hdr.dime.cal_min = 0.0;

    fwrite(&hdr,sizeof(struct dsr),1,fp);
    fclose(fp);
}

usage()
{
   printf("usage:  make_hdr name.hdr x y z t datatype max min \n\n");
   printf("  name.hdr = the name of the header file\n");
   printf("  x = width, y = height,  z = depth,  t = number of volumes\n");
   printf("  acceptable datatype values are: BINARY, CHAR, SHORT,\n");
   printf("                 INT, FLOAT, COMPLEX, DOUBLE, and RGB\n");
   printf("  max = maximum voxel value,  min = minimum voxel value\n");
}


The following program displays information in an Analyze header file.

#include
#include "dbh.h"

void ShowHdr(char *, struct dsr *);
void swap_long(unsigned char *);
void swap_short(unsigned char *);

main(argc,argv)
int argc;
char **argv;
    {
    struct dsr hdr;
    int size;
    double cmax, cmin;
    FILE *fp;

.if((fp=fopen(argv[1],"r"))==NULL)
    {
.fprintf(stderr,"Can't open:\n", argv[1]);
.exit(0);
    }
    fread(&hdr,1,sizeof(struct dsr),fp);

.if(hdr.dime.dim[0]  15)
..swap_hdr(&hdr);

     ShowHdr(argv[1], &hdr);


     }




void ShowHdr(fileName,hdr)
struct dsr *hdr;
char *fileName;
{
int i;
char string[128];
printf("Analyze Header Dump of:  \n", fileName);
/* Header Key */
printf("sizeof_hdr:  \n", hdr->hk.sizeof_hdr);
printf("data_type:   \n", hdr->hk.data_type);
printf("db_name:     \n", hdr->hk.db_name);
printf("extents:     \n", hdr->hk.extents);
printf("session_error:  \n", hdr->hk.session_error);
printf("regular:   \n", hdr->hk.regular);
printf("hkey_un0:  \n", hdr->hk.hkey_un0);

/* Image Dimension */
for(i=0;i<8;i++)
.printf("dim[%d]:  \n", i, hdr->dime.dim[i]);

.strncpy(string,hdr->dime.vox_units,4);
.printf("vox_units:   \n", string);

.strncpy(string,hdr->dime.cal_units,8);
.printf("cal_units:  \n", string);
.printf("unused1:    \n", hdr->dime.unused1);
.printf("datatype:   \n", hdr->dime.datatype);
.printf("bitpix:     \n", hdr->dime.bitpix);

for(i=0;i<8;i++)
.printf("pixdim[%d]:  \n",i, hdr->dime.pixdim[i]);

printf("vox_offset:  \n",  hdr->dime.vox_offset);
printf("funused1:    \n", hdr->dime.funused1);
printf("funused2:    \n", hdr->dime.funused2);
printf("funused3:    \n", hdr->dime.funused3);
printf("cal_max:     \n", hdr->dime.cal_max);
printf("cal_min:     \n", hdr->dime.cal_min);
printf("compressed:  \n", hdr->dime.compressed);
printf("verified:    \n", hdr->dime.verified);
printf("glmax:       \n", hdr->dime.glmax);
printf("glmin:       \n", hdr->dime.glmin);

/* Data History */
strncpy(string,hdr->hist.descrip,80);
printf("descrip:   \n", string);
strncpy(string,hdr->hist.aux_file,24);
printf("aux_file:  \n", string);
printf("orient:    \n", hdr->hist.orient);

strncpy(string,hdr->hist.originator,10);
printf("originator:  \n", string);

strncpy(string,hdr->hist.generated,10);
printf("generated:  \n", string);


strncpy(string,hdr->hist.scannum,10);
printf("scannum:  \n", string);

strncpy(string,hdr->hist.patient_id,10);
printf("patient_id:  \n", string);

strncpy(string,hdr->hist.exp_date,10);
printf("exp_date:  \n", string);

strncpy(string,hdr->hist.exp_time,10);
printf("exp_time:  \n", string);

strncpy(string,hdr->hist.hist_un0,10);
printf("hist_un0:  \n", string);

printf("views:       \n", hdr->hist.views);
printf("vols_added:  \n", hdr->hist.vols_added);
printf("start_field: \n", hdr->hist.start_field);
printf("field_skip:  \n", hdr->hist.field_skip);
printf("omax:  \n", hdr->hist.omax);
printf("omin:  \n", hdr->hist.omin);
printf("smin:  \n", hdr->hist.smax);
printf("smin:  \n", hdr->hist.smin);

}


swap_hdr(pntr)
struct dsr *pntr;
.{
.swap_long(&pntr->hk.sizeof_hdr) ;
.swap_long(&pntr->hk.extents) ;
.swap_short(&pntr->hk.session_error) ;
.swap_short(&pntr->dime.dim[0]) ;
.swap_short(&pntr->dime.dim[1]) ;
.swap_short(&pntr->dime.dim[2]) ;
.swap_short(&pntr->dime.dim[3]) ;
.swap_short(&pntr->dime.dim[4]) ;
.swap_short(&pntr->dime.dim[5]) ;
.swap_short(&pntr->dime.dim[6]) ;
.swap_short(&pntr->dime.dim[7]) ;
.swap_short(&pntr->dime.unused1) ;
.swap_short(&pntr->dime.datatype) ;
.swap_short(&pntr->dime.bitpix) ;
.swap_long(&pntr->dime.pixdim[0]) ;
.swap_long(&pntr->dime.pixdim[1]) ;
.swap_long(&pntr->dime.pixdim[2]) ;
.swap_long(&pntr->dime.pixdim[3]) ;
.swap_long(&pntr->dime.pixdim[4]) ;
.swap_long(&pntr->dime.pixdim[5]) ;
.swap_long(&pntr->dime.pixdim[6]) ;
.swap_long(&pntr->dime.pixdim[7]) ;
.swap_long(&pntr->dime.vox_offset) ;
.swap_long(&pntr->dime.funused1) ;
.swap_long(&pntr->dime.funused2) ;
.swap_long(&pntr->dime.cal_max) ;
.swap_long(&pntr->dime.cal_min) ;
.swap_long(&pntr->dime.compressed) ;
.swap_long(&pntr->dime.verified) ;
.swap_short(&pntr->dime.dim_un0) ;
.swap_long(&pntr->dime.glmax) ;
.swap_long(&pntr->dime.glmin) ;
.}

swap_long(pntr)
unsigned char *pntr;
.{
.unsigned char b0, b1, b2, b3;

.b0 = *pntr;
.b1 = *(pntr+1);
.b2 = *(pntr+2);
.b3 = *(pntr+3);

.*pntr = b3;
.*(pntr+1) = b2;
.*(pntr+2) = b1;
.*(pntr+3) = b0;
.}

swap_short(pntr)
unsigned char *pntr;
.{
.unsigned char b0, b1;

.b0 = *pntr;
.b1 = *(pntr+1);

.*pntr = b1;
.*(pntr+1) = b0;
.}



The next part is part6 -  hosts & compression.

