An ANI file is a RIFF file. Every chunk is a four-character ID, a 32-bit little-endian length that counts the data only, and the data, followed by one zero byte when the length is odd. All numbers in the file are little-endian.
The form
Microsoft’s 1994 definition of the form, in the RIFF notation, with optional parts in square brackets:
RIFF( 'ACON'
[ LIST( 'INFO' <info chunks> ) ]
[ DISP( <display data> ) ]
anih( <ANIHEADER> )
[ rate( <DWORD>... ) ]
[ 'seq '( <DWORD>... ) ]
LIST( 'fram' icon( <icon file> )... )
)
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 4 | ASCII | chunk ID | RIFF: bytes 52 49 46 46 |
| 4 | 4 | u32 | length | the file length minus 8 |
| 8 | 4 | ASCII | form type | ACON: bytes 41 43 4F 4E |
| 12 | varies | chunks | the chunks below |
Chunk list
| ID | Required | Contents |
|---|---|---|
anih | yes | the 36-byte header: frame and step counts, default rate and flags; see Header (anih) |
LIST fram | yes | the frames: one icon chunk per frame |
rate | no | one display time per step |
seq | no | one frame number per step; the ID ends in a space, 73 65 71 20 |
LIST INFO | no | text about the file, such as its title and author |
DISP | no | a displayable form of the file, such as a picture or text |
The anih chunk must come before rate, seq and
the fram list, because a reader needs its counts to read them. Files from
the usual editors put the chunks in the order of the form above. A reader should skip
any chunk it does not know.
rate
An array of 32-bit unsigned values, one per step, cSteps of them. Each
is the time to show that step, in jiffies of 1/60 second. When the chunk is present it
replaces the header’s single default rate, jifRate, so each step can have
its own timing.
seq
An array of 32-bit unsigned values, one per step, cSteps of them. Each
is the number of the frame to show at that step, counting from 0 in the order of the
icon chunks. A frame can appear at several steps, so a long animation can
reuse a few frames. Without this chunk the steps show the frames in order, so
cSteps should not be more than cFrames.
LIST fram and icon
A LIST chunk whose list type is fram holds
cFrames chunks with the ID icon, one per frame. When the
header’s AF_ICON flag is set, which it always is in practice, each
icon chunk holds a complete ICO or CUR
file: the 6-byte header, the directory and the
images. A CUR frame carries its own hotspot, so
animated pointers use CUR frames; an ICO frame has no hotspot.
A frame may hold several sizes or colour depths, like any icon file, and since Windows
Vista a frame’s images may be PNG. The image offsets in the frame’s directory count from
the start of the icon chunk’s data, not from the start of the ANI
file.
Early third-party notes describe frames without AF_ICON as raw bitmaps.
Microsoft’s definition does not include that form and Windows is not known to load
it.
LIST INFO
The standard RIFF information list. Cursor editors write two of its chunks:
| ID | Contents |
|---|---|
INAM | the title of the cursor |
IART | the author |
Each is a zero-terminated string in the system’s ANSI code page. Any other RIFF information chunk may appear; the full list is on the WAV LIST INFO page. Windows ignores this list when it loads a cursor.
DISP
The standard RIFF display chunk: a 32-bit Windows clipboard format number followed by data in that format, such as 1 for text or 8 for a device-independent bitmap. It lets a program show something for the file without understanding it. It is rare in ANI files, and a reader can skip it.
Example
A two-frame cursor, each frame shown for a quarter of a second, with no
rate, seq or INFO:
| Offset | Bytes | Meaning |
|---|---|---|
| 0 | 52 49 46 46 len | RIFF, file length − 8 |
| 8 | 41 43 4F 4E | ACON |
| 12 | 61 6E 69 68 24 00 00 00 | anih, 36 bytes |
| 20 | 24 00 00 00 | cbSize 36 |
| 24 | 02 00 00 00 02 00 00 00 | cFrames 2, cSteps 2 |
| 32 | 16 × 00 | cx, cy, cBitCount, cPlanes: 0 |
| 48 | 0F 00 00 00 | jifRate 15: 15/60 s |
| 52 | 01 00 00 00 | flags: AF_ICON |
| 56 | 4C 49 53 54 len 66 72 61 6D | LIST, length, fram |
| 68 | 69 63 6F 6E len | first icon chunk: a CUR file |
| … | 69 63 6F 6E len | second icon chunk |