APPENDIX D - Interchange File Format (IFF) 1.4

The Interchange File Format (IFF) is a binary file with an AmigaOS chunk structure (like IFF-ILBM, AIFF, etc). All chunks are optional (with the exception of the first one) and the structure is totally expandable. Use this powerful format if you want store the largest number of information when you are using VEGA and VEGA ZZ.

 

Conventions for numeric formats:

Type Size (bit) Description
BYTE 8 Byte integer.
UBYTE 8 Unsigned byte integer.
WORD 16 Two byte integer.
UWORD 16 Two byte unsigned integer.
LONG 32 Four byte integer.
ULONG 32 Four byte unsigned integer.
DLONG 64 Eight byte integer.
UDLONG 64 Eight byte unsigned integer.
FLOAT 32 Single precision IEEE float (4 bytes).
DOUBLE 64 Double precision IEEE float (8 bytes).

IFF files are in big endian format and so if the hardware doesn’t support it (e.g. x86 CPUs), you must change the byte order when write the floats and integers which size is more than one character.
RIFF files (Resource Interchange File Format) are equivalent to IFF, but the numeric data is stored in little endian format and they are supported starting from VEGA ZZ 2.0.6 and VEGA 1.5.6.
A chunk is a data block with a 8 byte header:

 

Chunk {
    HEADER (8 bytes)
    Data
    ...
}

 

The first 4 bytes are a string identifying the chunk type and the next 4 bytes (ULONG format) are the size of Data block, as shown in the following C structure:

 

typedef struct {
    UBYTE  Hdr[4]
    ULONG  Size
} HEADER;

 

IFF file structure:

 

IFF_File {
    HEADER {
        "FORM",
        4 + sizeof(Chunk_1) + sizeof(Chunk_1) + ... + sizeof(Chunk_N)
    }

    "MOLE"

    Chunk_1
    Chunk_2
    ...
    Chunk_N

}

 

All IFF files are a sequence of chunks with a header of 8 bytes. The recognition string (Hdr field) is FORM and the Size field is the sum of lengths of all chunks and the size of subformat recognition header (8 bytes). IFF is a family of binary files that can store a variety of data as audio, image, video and molecule. To recognize the subformat you must read the next 8 byte containing the subformat header. In particular, this second header contains the sub-recognition string MOLE and the Size field with the value of the size of all data chunks.
If the file is in little endian format, the main chunk starts with RIFF string instead of FORM.

 

ATOM  -  Atom name chunk:

ATOM {
    HEADER {
        "ATOM",
        4 + 2 * TotAtm
    }
    ULONG  TotAtm
    UBYTE  Element[2][TotAtm]
}

 

This is the only one chunk that can't be optional. TotAtm is the total number of atoms stored in the file. Element is a two byte vector containing the names of chemical elements for each atom. If the element name has the size of one character (e.g. H, C, O, S, etc), the second byte must be a space. The special Xc element name is reserved for centroids (dummy atoms). For example,  the ATOM chunk of chlorobenzene (C6H5Cl, 12 atoms) must be:

 

ATOM {
    HEADER {
        "ATOM",
        24,
    }
    "C ", "C ", "C ", "C ", "C ",
    "H ", "H ", "H ", "H ", "Cl"
}

 

XYZ1  -  Single precision Cartesian coordinate chunk:

XYZ1 {
    HEADER {
        "XYZ1",
        TotAtm * 12
    }
    XYZ[TotAtm] {
        FLOAT  x
        FLOAT  y
        FLOAT  z
    }
}

 

This chunk contains the Cartesian coordinates for each atom in single precision floating-point format. This chunk and the XYZ2 could be repeated more thane one time if the file is a MD trajectory. For example, the XYZ1 chunk of benzene (C6H6) could be:

 

XYZ1 {
    HEADER {
        "XYZ1",
        144
    }
    XYZ {
        { 0.695,  1.203,  0.000 },
        {-0.695,  1.203, -0.002 },
        {-1.389,  0.000, -0.006 },
        {-0.695, -1.203, -0.007 },
        { 0.695, -1.203, -0.006 },
        { 1.389,  0.000, -0.002 },
        { 1.235,  2.139,  0.003 },
        {-1.235,  2.139, -0.001 },
        {-2.470,  0.000, -0.007 },
        {-1.235, -2.139, -0.010 },
        { 1.235, -2.139, -0.007 },
        { 2.470,  0.000, -0.001 }
    }
}

 

XYZ2  -  Double precision Cartesian coordinate chunk:

XYZ2 {
    HEADER {
        "XYZ1",
        TotAtm * 24
    }
    XYZ[TotAtm] {
        DOUBLE  x
        DOUBLE  y
        DOUBLE  z
    }
}

 

XYZ2 is the double precision version of XYZ1 chunk, keeping the same structure.

 

CENT  -  Centroid chunk:

CENT {
    HEADER {
        "CENT",
        4 + 5 * TotCent + TotRefAtm * 4
    }
    ULONG TotCent;
    CENTROIDS[TotCent] {
        ULONG  CentID
        BYTE   TotRef
        ULONG  RefAtmID[TotRef]
    }
}

 

Centroids are dummy atoms labelled as Xc in the element chunk (ATOM). This chunk contains the data to calculate dynamically the position of each centroid. TotCent is the number of centroids, CentID is the identification number of the centroid (it's the normal atom serial number), TotRef is the number of the atoms used to calculate dynamically the centroid position, RefAtmID is the array containing the serials of the atoms used to calculate the position. TotRefAtm in the IFF header is the number of all atoms involved in the position calculation of all centroids. If this chunk is missing, the centroids specified in the ATOM chunk will be considered fixed and their coordinates aren't dynamically calculated when the coordinates of the reference atoms are changed.

 

CHIR  -  Chirality chunk:

VGCL {
    HEADER {
        "CHIR",
        TotAtm
    }
    BYTE  Chiral[TotAtm]
}

 

It stores the chirality flag of each atom. The possible values of each array elements are:

Value Character Description
0 - No chirality
82 R R chirality
83 S S chirality
42 * Unknown chirality

 

CONX  -  Connectivity chunk:

CONX {
    HEADER {
        "CONX",
        TotBond * 9
    }
    ULONG TotBond;
    CONN[TotBond] {
        ULONG  Atom1
        ULONG  Atom2
        UBYTE  BondOrder
    }
}

 

This chunk is needed to indicate the connectivity between atom pairs. TotBond is the number of bonds, Atom1 and Atom2 is the pair of connected atom and BondOrder is the bond order that can be 1 (single bond), 2 (double bond), 3 (triple bond) and 4 (partial double bond).

 

IIUB  -  IUPAC IUB atom name chunk:

IIUB {
    HEADER {
        "IIUB",
        TotAtm * IUB_Len
    }
    UBYTE  IUB_Len
    UBYTE  Name[IUB_Len][TotAtm]
}

 

In this chunk you can find the IUPAC IUB atom names. IUB_Len is the length of Name record.

 

CALC  -  Potential and atomic charges chunk:

CALC {
    HEADER {
        "CALC",
        18 + sizeof(ForceFieldName[ ]) + TotAtm * (4 + ATPY_Len)
    }
    UBYTE  ForceFieldName[ ]
    HEADER {
        "CHRG",
        TotAtm * 4
    }
    FLOAT  AtmCharge[TotAtm]

    HEADER {
        "ATYP",
        TotAtm * ATPY_Len
    }
    UBYTE  ATPY_Len
    UBYTE  AtmType[ATPY_Len][TotAtm]
}

 

This is a complex chunk containing the atom type and the atomic charge of each atom. In this chunk, two sub-chunk are present: CHRG and ATYP. The former includes the atomic charges in single precision format (AtmCharge) and the latter stores the atom potentials (atom types). ATPY_Len is the size (in bytes) of each potential record. At this time, the default value is 8.

 

FIXA  -  Atom constraints chunk:

FIXA {
    HEADER {
        "FIXA",
        TotAtm
    }
    FLOAT  FixValue[TotAtm]
}

 

This chunk contains constraint values used by molecular dynamics simulations. Each value is a positive floating point number, usually ranged from 0 (free) to 1 (fix).

 

RESI  -  Residue name, residue number and chain identification chunk:

RESI {
    HEADER {
        "RESI",
        TotRes * 13
    }
    RESDATA[TotRes] {
        ULONG  Atoms

        UBYTE  ResName[4]
        UBYTE  ResNum[4]
       
UBYTE  ChainID
    }
}

 

TotRes is the total number of residues, Atoms is the number of atoms in the residue, ResName is the residue name, ResNum is the residue number and ChainID is the chain indicator. ChainID contains the chain identification character or a null value.

 

RSNU  -  Residue number chunk (obsolete):

RSNU {
    HEADER {
        "RSNU",
        TotAtm * 4
    }
    UBYTE  ResNum[4][TotAtm]
}

 

It's the residue number of each atom. ResNum is a four character string and not an integer number, because it can include the chain indicator (e.g. "99 A"). This chunk was maintained for backward compatibility only and  it was replaced by RESI chunk.

 

RSNA  -  Residue name chunk (obsolete):

RSNA {
    HEADER {
        "RSNA",
        TotRes * 4
    }
    UWORD  TotRes
    RESNAME[TotRes] {
        UBYTE  ResNum[4]
        UBYTE  ResName[4]
    }
}

 

This chunk is used to translate the residue number ResNum to residue name ResName. TotRes is the total number of residue in the file. This chunk was maintained for backward compatibility only and  it was replaced by RESI chunk.

 

SEGM  -  Segments chunk:

SEGM {
    HEADER {
        "SEGM",
        TotSeg * 4
    }
    ULONG  AtmNum[TotSeg]
}

 

This chunk is equivalent to TER record in PDB file format. TotSeg is the number of segments and AtmNum is a vector containing the atom IDs (progressive number) indicating the end of each segment.

 

MOLM  -  Name of the molecules chunk:

MOLM {
    HEADER {
        "MOLM",
        sizeof(MOLNAME[ ])
    }
    ULONG  TotMol
    MOLNAME[TotMol] {
        ULONG  AtmStart
        ULONG  AtmNum
        UBYTE  MolName[ ]
    }
}

 

IFF files can include more than one molecule. TotMol is the total number of molecules, AtmStart is the first atom number of the molecule, AtmNum is the number of atoms in the selected molecule and MolName is the molecule name (C string format, null terminated).

 

MOLN  -  Name of the molecules chunk:

MOLN {
    HEADER {
        "MOLN",
        sizeof(MOLNAME[ ])
    }
    UWORD  TotMol
    MOLNAME[TotMol] {
        ULONG  AtmStart
        ULONG  AtmNum
        UBYTE  MolName[ ]
    }
}

 

This chunk is replaced by MOLM and it's kept for compatibility.

 

COMM  -  Remark chunk:

COMM {
    HEADER {
        "COMM",
        1 + sizeof(Remark[ ])
    }
    UBYTE  Remark[ ]
}

 

In this chunk, you can include a remark.

 

SRFA  -  Surface atom number chunk:

SRFA {
    HEADER {
        "SRFA",
        Points * 4
    }
    ULONG  AtmNum[Points]
}

 

It stores the atom number for each surface point. This chunk requires the SURF chunk before it.

 

SRC3  -  Surface color chunk (24 bit):

SRC3 {
    HEADER {
        "SRC3",
        Points * 3
    }
    DOTCOLOR[Points] {

      UBYTE  R
      UBYTE  G
      UBYTE  B
    }
}

 

This chunk contains the color for each surface point in RGB format (24 bit), where R is the red component , G is the green component and B is the blue component. All these parameters must be in the range from 0 to 255. This is the default color chunk written by VEGA ZZ. You can use SRFC chunk also, preferring SRC3 if the alpha (transparency) information isn't required.

 

SRFC  -  Surface color chunk (32 bit):

SRFC {
    HEADER {
        "SRFC",
        Points * 4
    }
    DOTCOLOR[Points] {

      UBYTE  A
      UBYTE  R
      UBYTE  G
      UBYTE  B
    }
}

 

This chunk contains the color for each surface point in ARGB format, where A is the alpha key (transparency), R is the red component , G is the green component and B is the blue component. All these parameters must be in the range from 0 to 255.

SRFF  -  Surface face chunk:

SRFF {
    HEADER {
        "SRFF",
        NumVertexID * Size + 1
    }
    UBYTE  Size

    UBYTE  (or UWORD, or ULONG) VertexIDArray[NumVertexID]
}

 

This chunk contains the surface faces as triplets of vertex IDs. The vertex ID is a positive integer number indicating the surface dot (see SURF chunk) used to define one face (triangle) vertex. The vertex IDs can be stored in the formats defined by the Size byte: UBYTE (Size = 1), UWORD (Size = 2) and ULONG (Size = 3). The three formats are able to store respectively until 256, 65536 and 4294967296 vertex IDs.

 

SRFV  -  Surface value chunk:

SRFV {
    HEADER {
        "SRFV",
        Points * 4
    }

    FLOAT  Value[Points]
}

 

It contains the property value of each surface dot.

 

SRFI  -  Surface information chunk:

SRFI {
    HEADER {
        "SRFI",
        LenOfSrfName + 16
    }

    UBYTE  LenOfSrfName
    UBYTE  SrfName[LenOfSrfName]
    LONG   Flags
    UBYTE  SrfType
    UBYTE  Alpha
    UBYTE  DotSize
    ULONG  Reserved1
    ULONG  Reserved2
}

 

If you want to add extra information to surfaces, you can use this chunk in which SrfName is the surface name, LenOfSrfName is the length of the surface name (max. 255 characters),  Flags is the special surface flags (click here for more information), SrfType is the surface type (click here for more information), Alpha is the alpha blending value (0 full transparent, 255 full opaque) and DotSize is the dot size used to show the dotted surface. LenOfSrfName can be zero, but in this case SrfName mustn't present in the chunk. Reserved1 and Reserved2 are for future use.

 

SRFN  -  Surface normal chunk:

SRFN {
    HEADER {
        "SRFN",
        Points * 6 
    }
    XYZ[Points] {
        WORD  x
        WORD  y
        WORD  z
    }
}

 

This chunk stores the normal vectors of each surface point used by VEGA ZZ lighting engine for shading. If the surface type is dotted, this chunk is ignored. The normals, which values are in range from -1.0 to 1.0, are stored in low precision integer format. When you want put the normals in the chunk, you must multiply each coordinate by 32767 and thus you must take the integer part. To revert the floating point format, you must divide the coordinates by 32767 and cast to float. In this way, you can obtain a good precision using half of disk space.  

 

SURF  -  Generic surface chunk:

SURF {
    HEADER {
        "SURF",
        Points * 12
    }
    XYZ[Points] {
        FLOAT  x
        FLOAT  y
        FLOAT  z
    }
}

 

This chunk contains the Cartesian coordinates of each surface point. Points is the number of surface points. The IFF format allows more than one surfaces and so one or more SURF chunk can be present in the file. Please remember that this chunk must written before all other surfaces chunk otherwise they will be ignored. All other surface chunk are optional.

 

VERS  -  Version chunk:

VERS {
    HEADER {
        "VERS",
        4
    }
    LONG  Version
}

 

The chunk contains the file version number organized in two 16 bit words: the higher word is the version and the lower word is the revision.

 

Special VEGA chunks:

 

VGAB  -  Active atom chunk:

VGAB {
    HEADER {
        "VGAB",
        (TotAtm / 8) + 1
    }
    UBYTE  Active[(TotAtm / 8) + 1]
}

 

It defines if the atom is active or not (visible or not). The boolean values are stored in a bitmap in order to reduce the size and so this chunk is eight time smaller then the previous VGAC. If a bit is true (1), the atom is active, otherwise if it's false (0), the atom is inactive. To encode/decode this chunk, you can use the routines at the end of this document.

 

VGAC  -  Active atom chunk (obsolete):

VGAC {
    HEADER {
        "VGAC",
        TotAtm
    }
    UBYTE  Active[TotAtm]
}

 

It defines if the atom is active or not (visible or not). If a vector item is true (1), the atom is active, otherwise if it's false (0), the atom is inactive. This chunk is obsolete and it's replaced by VGAB. 

 

VGCL  -  Color chunk:

VGCL {
    HEADER {
        "VGCL",
        TotAtm
    }
    UBYTE  ColorID[TotAtm]
}

 

It stores the color of each atom with the VEGA color code. See below for all color codes.

 

VGDM  -  Draw mode chunk:

VGDM {
    HEADER {
        "VGDM",
        TotAtm
    }
    UBYTE  DrawMode[TotAtm]
}

 

It stores the information about the draw mode of each atom. Starting from VEGA ZZ 2.0.0, it's possible to change the display mode of each atom. See below for the draw modes.

 

VGLB  -  Label chunk:

VGLB {
    HEADER {
        "VGLB",
        TotAtm
    }
    UBYTE  Label[TotAtm]
}

 

This chunk stores the label of each atom. See below for label codes.

 

VGMO  -  Monitor chunk:

VGLB {
    HEADER {
        "VGMO",
        The size can't be pre-computed
    }
    MONITOR[TotMon] {
        UBYTE  MonType
        IF (MonType != 0x10) {
            UBYTE  LblLen
            BYTE  Label[LblLen]
        IF (NonType == 0x20) {
            ULONG  AtmNum[2]
            BYTE   EzGeom
        } ELSE {
            ULONG  AtmNum[MonType & 0xf]
        }
    } 
}

 

This chunk contains the information for the monitors. The MonType byte is the monitor type as reported in the following table:

 

MonType Description
0x02 Distance.
0x03 Angle.
0x04 Torsion.
0x06 Angle between two planes.
0x10 H-bond label.
0x12 H-bond.
0x20 E/Z geometry.

 

AtmNum is the vector of atom numbers defining the monitor and its size can be obtained by MonType AND (logical operator) 0xf (16). If MonType is 0x10, the AtmNum array is replaced by the LblLen unsigned byte and Label byte array containing the H-bond label. If MonType is 0x20, AtmNum array has two elements only and the EzGeom byte is added.

 

VGTR  -  Transformation chunk:

VGAC {
    HEADER {
        "VGTR",
        TotAtm
    }
    FLOAT  PosX

    FLOAT  PosY
    FLOAT  PosZ

    FLOAT  RotStepX
    FLOAT  RotStepY
    FLOAT  RotStepZ

    FLOAT  PosStepX
    FLOAT  PosStepY
    FLOAT  PosStepZ

    FLOAT  Scale

    FLOAT  RotMat[4][4]
}

 

This chunk is only for private use and stores the current view settings of VEGA ZZ.

 

 

C subroutines and definitions:

In order to simplify the C programming, some useful definitions and subroutines are reported:

/**** VEGA atom label definitions ****

#define VG_ATMLBL_NONE       0
#define VG_ATMLBL_NAME       1
#define VG_ATMLBL_ELEMENT    2
#define VG_ATMLBL_NUMBER     3
#define VG_ATMLBL_TYPE       4
#define VG_ATMLBL_CHARGE     5
#define VG_ATMLBL_CHIRAL     6
#define VG_ATMLBL_FIX        7
#define VG_ATMLBL_RESNAMESEQ 8
#define VG_ATMLBL_RESNAME    9
#define VG_ATMLBL_RESSEQ    10

/**** VEGA color definitions ****/

#define VGCOL_NONE           0
#define VGCOL_BLACK          1
#define VGCOL_WHITE          2
#define VGCOL_RED            3
#define VGCOL_GREEN          4
#define VGCOL_CYAN           5
#define VGCOL_YELLOW         6
#define VGCOL_FIREBIRCK      7
#define VGCOL_MAGENTA        8
#define VGCOL_PINK           9
#define VGCOL_VIOLET        10
#define VGCOL_GRAY          11
#define VGCOL_ORANGE        12
#define VGCOL_DARKGREEN     13
#define VGCOL_BLUE          14
#define VGCOL_DARKYELLOW    15
#define VGCOL_BROWN         16
#define VGCOL_SKYBLUE       17
#define VGCOL_DARKGRAY      18
#define VGCOL_GHOSTPINK     19
#define VGCOL_GHOSTGREEN    20
#define VGCOL_GHOSTBLUE     21
#define VGCOL_GHOSTYELLOW   22
#define VGCOL_GHOSTGRAY     23
#define VGCOL_SAND          24

/**** Draw modes ****/

#define VG_ATMD_WIREFRAME   0    /* Vectors only                */
#define VG_ATMD_CPK_DOTTED  1    /* CPK/Van der Waals dotted    */
#define VG_ATMD_CPK_WIRE    2    /* CPK/Van der Waals wireframe */
#define VG_ATMD_CPK_SOLID   3    /* CPK/Van der Waals solid     */
#define VG_ATMD_BALL_WIRE   4    /* Ball & stick wireframe      */
#define VG_ATMD_BALL_SOLID  5    /* Ball & stick solid          */
#define VG_ATMD_SICK_WIRE   7    /* Stick wireframe             */
#define VG_ATMD_SICK_SOLID  8    /* Stick solid                 */
#define VG_ATMD_TUBE_SOLID  8    /* Tube solid                  */
#define VG_ATMD_TRACE_SOLID 9    /* Trace solid                 */
/**** Chirality ****/
#define VG_ATMC_NONE        0    /* Not chiral                  */
#define VG_ATMC_E         'E'    /* E geometry                  */
#define VG_ATMC_Z         'Z'    /* Z geometry                  */
#define VG_ATMC_R         'R'    /* R                           */
#define VG_ATMC_S         'S'    /* S                           */
#define VG_ATMC_UNDEF     '*'    /* Undefined chirality         */

/**** Surface Flags (see SRFI chunk) ****/

#define VG_SRFF_NONE        0    /* None                        */
#define VG_SRFF_ACTIVE      1    /* The surface is visible      */
#define VG_SRFF_ALPHA       2    /* Enable the alpha blending   */

/**** Surface types ****/

#define VG_SRFT_DOTTED      0    /* Dotted surface              */
#define VG_SRFT_MESH        1    /* Mesh surface                */
#define VG_SRFT_SOLID       2    /* Solid surface               */

/**** Types ****/

typedef char             BYTE;
typedef unsigned char    UBYTE;
typedef int              LONG;
typedef unsigned int     ULONG;
typedef short            WORD;
typedef unsigned short   UWORD;
typedef float            FLOAT;
typedef double           DOUBLE;

/**** IFF Chunk header ****/

typedef struct {
    char Hdr[4];
    ULONG Size;
} IFFHDR;

/**** Prototypes ****/

void SwapW(void *);
void SwapL(void *);
void SwapD(void *);


/**** Change the endian for WORD and UWORD ****/

void SwapW(register void *Val)
{
    register UBYTE T;
    T = ((UBYTE *)Val)[0];
    ((UBYTE *)Val)[0] = ((UBYTE *)Val)[1];
    ((UBYTE *)Val)[1] = T;
}


/**** Change endian for LONG, ULONG and FLOAT ****/

void SwapL(register void *Val)
{
    register UBYTE T;
    T = ((UBYTE *)Val)[0];
    ((UBYTE *)Val)[0] = ((UBYTE *)Val)[3];
    ((UBYTE *)Val)[3] = T;
    T = ((UBYTE *)Val)[1];
    ((UBYTE *)Val)[1] = ((UBYTE *)Val)[2];
    ((UBYTE *)Val)[2] = T;
}


/**** Change the endian for DOUBLE ****/

void SwapD(void *Val)
{
    register UBYTE T;
    T = ((UBYTE *)Val)[0];
    ((UBYTE *)Val)[0] = ((UBYTE *)Val)[7];
    ((UBYTE *)Val)[7] = T;
    T = ((UBYTE *)Val)[1];
    ((UBYTE *)Val)[1] = ((UBYTE *)Val)[6];
    ((UBYTE *)Val)[6] = T;
    T = ((UBYTE *)Val)[2];
    ((UBYTE *)Val)[2] = ((UBYTE *)Val)[5];
    ((UBYTE *)Val)[5] = T;
    T = ((UBYTE *)Val)[3];
    ((UBYTE *)Val)[3] = ((UBYTE *)Val)[4];
    ((UBYTE *)Val)[4] = T;
}


/**** Encode the active atom into the bitmap ****/

/*
 * Active -> An array of unsigned bytes from which the boolean values
 *           are packed.
 * TotAtm -> Number of atom in the IFF file.
 *
 * The returned value is the pointer of the bitmap that can be saved
 * directly in the IFF file.
 */

UBYTE *EncodeActiveAtm(UBYTE *Active, ULONG TotAtm)
{
    UBYTE           *PtrMtx;
    UBYTE           Bit;
    UBYTE           *Bitmap;
    ULONG           i;

    if ((Bitmap = (BYTE *)calloc(1, (TotAtm >> 3) + 1)) != NULL) {
        PtrMtx = Bitmap;
        Bit    = 1;
        for(i = 0; i < TotAtm; ++i) {
            if (Active[i]) *PtrMtx |= Bit;
            if (Bit == 128) {
                Bit = 1;
                ++PtrMtx;
            } else Bit <<= 1;
        } /* End of for */
    }

    return Bitmap;
}


/**** Decode the active atom from the bitmap ****/

/*
 * Active -> An array of unsigned bytes in which the boolean values
 *           are unpacked.
 * Bitmap -> The bitmap pointer.
 * TotAtm -> Number of atom in the IFF file.
 */

void PopActiveAtm(UBYTE *Active, UBYTE *Bitmap, ULONG TotAtm)
{
    ULONG          i;

    UBYTE          Bit = 1;

    for(i = 0; i < TotAtm; ++i) {
        Active[i] = ((*Bitmap & Bit) != 0);
        if (Bit == 128) {
            Bit = 1;
            ++Bitmap;
        } else Bit <<= 1;
    } /* End of for */
}