Copyright (c) Hyperion Entertainment and contributors.
A Quick Introduction to IFF
A Quick Introduction to IFF
By Jerry Morrison, Electronic Arts (17 October 1988)
IFF is the Amiga-standard “Interchange File Format”, designed to work across many machines.
Did you ever have this happen to your picture file?
- You can’t load it into another paint program.
- You need a converter to adopt to “ZooPaint” release 2.0 or a new hardware feature.
- You must “export” and “import” to use it in a page layout program.
- You can’t move it to another brand of computer.
What about interchanging musical scores, digitized audio, and other data? It seems the only thing that does interchange well is plain ASCII text files.
It’s inexcusable. And yet this is “normal” in MS-DOS.
What is IFF?
IFF, the “Interchange File Format” standard, encourages multimedia interchange between different programs and different computers. It supports long-lived, extensible data. It’s great for composite files like a page layout file that includes photos, an animation file that includes music, and a library of sound effects.
IFF is a 2-level standard. The first layer is the “wrapper” or “envelope” structure for all IFF files. Technically, it’s the syntax. The second layer defines particular IFF file types such as ILBM (standard raster pictures), ANIM (animation), SMUS (simple musical score), and 8SVX (8-bit sampled audio voice).
IFF is also a design idea: programs should use interchange formats for their everyday storage.
This way, users rarely need converters and import/export commands to change software releases, application programs, or hardware.
What’s the trick?
File compatibility is easy to achieve if programmers let go of one notion—dumping internal data structures to disk. A program’s internal data structures should really be suited to what the program does and how it works. What’s “best” changes as the program evolves new functions and methods. But a disk format should be suited to storage and interchange.
Once we design internal formats and disk formats for their own separate purposes, the rest is easy. Reading and writing become behind-the-scenes conversions. But two conversions hidden in each program is much better than a pile of conversion programs.
Does this seem strange? It’s what ASCII text programs do! Text editors use line tables, piece tables, gaps, and other structures for fast editing and searching. Text generators and consumers construct and parse files. That’s why the ASCII standard works so well.
Also, every file must be self-sufficient. E.g., a picture file has to include its size and number of bits/pixel.
What does an IFF file look like?
IFF is based on data blocks called “chunks”. Here’s an example color map chunk:
A chunk is made of a 4-character type identifier, a 32 bit data byte count, and the data bytes. It’s like a Macintosh “resource” with a 32-bit size.
- Every 16- and 32-bit number is stored in 68000 byte order—highest byte first.
- An Intel CPU must reverse the 2- or 4-byte sequence of each number. This applies to chunk dataSize fields and to numbers inside chunk data. It does not affect character strings and byte data because you can’t reverse a 1-byte sequence. But it does affect the 32-bit math used in IFF’s MakeID macro. The standard does allow CPU specific byte ordering hidden within a chunk itself, but the practice is discouraged.
- Every 16- and 32-bit number is stored on an even address.
- Every odd-length chunk must be followed by a 0 pad byte. This pad byte is not counted in dataSize.
- An ID is made of 4 ASCII characters in the range “ ” (space, hex 20) through “~” (tilde, hex 7E). Leading spaces are not permitted.
- IDs are compared using a quick 32-bit equality test. Case matters.
A chunk typically holds a C structure, Pascal record, or an array. For example, an ’ILBM’ picture has a ’BMHD’ bitmap header chunk (a structure) and a ’BODY’ raster body chunk (an array).
To construct an IFF file, just put a file type ID (like ’ILBM’) into a wrapper chunk called a ’FORM’ (Think “FILE”). Inside that wrapper place chunks one after another (with pad bytes as needed). The chunk size always tells you how many more bytes you need to skip over to get to the next chunk.
A FORM always contains one 4-character FORM type ID (a file type, in this case ’ILBM’) followed by any number of data chunks. In this example, the FORM type is ’ILBM’, which stands for InterLeaved Bitmap. (ILBM is an IFF standard for bitplane raster pictures.) This example has 3 chunks. Note the pad byte after the odd length chunk.
Within FORMs ILBM, ’BMHD’ identifies a bitmap header chunk, ’CMAP’ a color map, and ’BODY’ a raster body. In general, the chunk IDs in a FORM are local to the FORM type ID. The exceptions are the 4 global chunk IDs ’FORM’, ’LIST’, ’CAT ’, and ’PROP’. (A FORM may contain other FORM chunks. E.g., an animation FORM might contain picture FORMs and sound FORMs.)
How to read an IFF file?
Example code and modules are provided for reading IFF files using iffparse.library. However, if you wish to read a non-complex FORM by hand, the following logic can be used.
Once you have entered the FORM (for example, the FORM ILBM shown above), stored the FORM length (24070 in the ILBM example) and are positioned on the first chunk, you may:
Loop: (until end-of-file or end-of-form) - Read the 4-character identifier of the chunk - Read the 32-bit (4 byte) chunklength - Decide if you want that chunk If yes, read chunklength bytes into destination structure or buffer If no, seek forward chunklength bytes - If chunklength is odd, seek one more byte
Every IFF file is a ’FORM’, ’LIST’, or ’CAT ’ chunk. You can recognize an IFF file by those first 4 bytes. (’FORM’ is far and away the most common. We’ll get to LIST and CAT below.) If the file contains a FORM, dispatch on the FORM type ID to a chunk-reader loop like the one above.
IFF files are extensible and forward/backward compatible:
- Chunk contents should be designed for compatibility across and for longevity. Every chunk should have a path for expansion; at minimum this will be an unused bit or two.
- The standards team for a FORM type can extend one of the chunks that contains a structure by appending new, optional structure fields.
- Anyone can define new FORM types as well as new chunk types within a FORM type. Storing private chunks within a FORM is OK, but be sure to register your activities with the AmigaOS development team.
- A chunk can be superseded by a new chunk type, e.g., to store more bits per RGB color register. New programs can output the old chunk (for backward compatibility) along with the new chunk.
- If you must change data in an incompatible way, change the chunk ID or the FORM type ID.
Advanced Topics: CAT, LIST, and PROP (not all that important)
Sometimes you want to put several “files” into one, such as a picture library. This is what CAT is for. It “concatenates” FORM and LIST chunks.
This example CAT holds two ILBMs. It can be shown outline-style:
CAT ILBM ..FORM ILBM \ ....BMHD | a complete FORM ILBM picture ....CMAP | ....BODY / ..FORM ILBM ....BMHD ....CMAP ....BODY
Sometimes you want to share the same color map across many pictures. LIST and PROP do this:
LIST ILBM ..PROP ILBM default properties for FORMs ILBM ....CMAP an ILBM CMAP chunk (there could be a BMHD chunk here, too) ..FORM ILBM ....BMHD (there could be a CMAP here to override the default) ....BODY ..FORM ILBM ....BMHD (there could be a CMAP here to override the default) ....BODY
A LIST holds PROPs and FORMs (and occasionally LISTs and CATs). A PROP ILBM contains default data (in the above example, just one CMAP chunk) for all FORMs ILBM in the LIST. Any FORM may override the PROP-defined default with its own CMAP. All PROPs must appear at the beginning of a LIST. Each FORM type defines as standard (among other things) which of its chunks are “property chunks” (may appear in PROPs) and which are “data chunks” (may not appear in PROPs).