FLI

Also Known As: FLI Animation, Flic, FLC, FII


Type Animation
Colors 64, 256
Compression Raw, RLE, and delta
Maximum Image Size 320x200, 64Kx64K
Multiple Images Per File Yes
Numerical Format Little-endian
Originator Autodesk
Platform Intel
Supporting Applications Autodesk Animator and Animator Pro
See Also GRASP

Usage
Used to store animation sequences found in graphics applications, CAD systems, and computer games.

Comments
Currently occupies a market niche being colonized by video.

Vendor specifications are available for this format.

Sample images are available for this format.


The FLI file format (sometimes called Flic) is one of the most popular animation formats found in the MS-DOS and Windows environments today. FLI is used widely in animation programs, computer games, and CAD applications requiring 3D manipulation of vector drawings. Flic, in common with most animation formats, does not support either audio or video data, but instead stores only sequences of still image data.

Contents:
File Organization
File Details
For Further Information

FLI is popular because of its simple design. It easy to implement FLI readers and writers in software-only applications. FLI also enables quick animation playback and does not require special hardware to encode or decode its data.

FLI is best suited for computer-generated or hand-drawn animation sequences, such as those created using animation and CAD programs. These images achieve the best compression ratios when stored using the FLI format.

Natural, real-world images may also be animated by FLI, but such images usually contain a fair amount of noise that will degrade the ability of the FLI encoding algorithms to compress the data and will therefore possibly affect the speed of the animation playback. Also, the fewer the colors in the animation, the better the compression ratio will typically be.

There are two types of FLI animation files. The original FLI format has an extension of .FLI, has a maximum display resolution of 320x200 pixels, and is only capable of supporting 64 colors. This format was created for use by the Autodesk Animator application.

The new FLI format has the extension .FLC, has a maximum display resolution of 64Kx64K pixels, and supports up to 256 colors. The data compression scheme used by .FLC files is also more efficient than the scheme used by .FLI files. Applications such as the IBM Multimedia Tool Series, Microsoft Video for Windows, and Autodesk Animator Pro all support .FLC files.

Any application capable of reading the newer .FLC files should be able to read and play back the older .FLI files as well. However, most newer FLI file writers may only have the capability of creating .FLC files. There is really no reason to create .FLI files, unless the animations you are producing must run under software that reads only the .FLI format.

File Organization

FLI animations are sequences of still images called frames. Each frame contains a slice of the animation data. The speed of the animation playback is controlled by specifying the amount of delay that is to occur between each frame.

The data in each frame is always color mapped. Each pixel in a frame contains an index value into a color map defined for that frame. The colors in the map may change from frame to frame as required. And, although the FLI file is limited to displaying a maximum of 256 colors per frame, each pixel is 24 bits in depth, resulting in a palette of more than 16 million colors from which to choose.

The FLI format also supports several types of data compression. Each frame of a FLI animation is typically compressed using an interframe delta encoding scheme. This scheme encodes only the differences between adjacent image frames and not the frames themselves. This strategy results in significantly smaller files than if each frame were independently encoded (intraframe encoding). Interframe encoded data is also very fast to uncompress and display.

The first frame of every FLI animation is compressed in its entirety, using a simple run-length encoding algorithm. Because only the differences between each successive frame are encoded, you have to start somewhere. If a frame is delta encoded and the resulting compressed data is larger than the original uncompressed data (quite possible with noisy, natural images), then the frame may be stored uncompressed.

File Details

The header of a FLI file is 128 bytes in length. The first nine fields (22 bytes) are the same for both .FLI and .FLC files. The last ten fields (106 bytes) contain valid data only in .FLC files and are set to 00h in .FLI files.

The FLI file header has the following format:

typedef struct _FlicHeader
{
  DWORD FileSize;       /* Total size of file */
  WORD  FileId;         /* File format indicator */
  WORD  NumberOfFrames; /* Total number of frames */
  WORD  Width;          /* Screen width in pixels */
  WORD  Height;         /* Screen height in pixels */
  WORD  PixelDepth;     /* Number of bits per pixel */
  WORD  Flags;          /* Set to 03h */
  DWORD FrameDelay;     /* Time delay between frames */
  WORD  Reserved1;      /* Not used (Set to 00h) */
  // The following fields are set to 00h in a .FLI file
  DWORD DateCreated;    /* Time/Date the file was created */
  DWORD CreatorSN;      /* Serial number of creator program */
  DWORD LastUpdated;    /* Time/Date the file last changed */
  DWORD UpdaterSN;      /* Serial number of updater program */
  WORD  XAspect;        /* X-axis of display aspect ratio */
  WORD  YAspect;        /* Y-axis of display aspect ratio */
  BYTE  Reserved2[38];  /* Not used (Set to 00h) */
  DWORD Frame1Offset;   /* Offset of first frame */
  DWORD Frame2Offset;   /* Offset of second frame */
  BYTE  Reserved3[40];  /* Not used (Set to 00h) */
} FLICHEADER;

FileSize contains the total size of the FLI file in bytes.

FileId contains a value identifying the type of Flic file. A value of AF11h indicates an .FLI file, and a value of AF12h indicates an .FLC file.

NumberOfFrames contains the total number of frames of animation data. A .FLC file may contain a maximum of 4000 frames; this does not include the ring frame.

Width and Height specify the size of the animation in pixels.

PixelDepth indicates the number of bits per pixel; the value of this field is always 08h.

Flags is always set to 03h, as an indication that the file was properly updated.

FrameDelay indicates the amount of time delay between frames and is used to control the speed of playback. For .FLI files, this value is interpreted in units of 1/70 of a second. For .FLC files, this value is in units of 1/1000 of a second.

Reserved1 is not used and is set to 00h.

DateCreated is an MS-DOS date stamp (the number of seconds occurring since midnight, January 1, 1970) of the date the FLI file was created.

CreatorSN contains the serial number of the Animator Pro application program that created the FLI file. If the file was created by an application using the FlicLib development library, the value of this field will be 46h 4Ch 49h 42h ("FLIB").

LastUpdated is an MS-DOS date stamp indicating the last time the FLI file was modified (also in number of seconds since midnight January 1, 1970).

UpdaterSN contains the serial number of the program that last modified the Flic file.

XAspect and YAspect contain the aspect ratio of the display used to create the animation. For a display with a resolution of 320x200, the aspect ratio is 6:5, and these fields contain the values 6 and 5 respectively. For all other resolutions, the aspect ratio is typically 1:1.

Reserved2 is not used and is set to 00h.

Frame1Offset and Frame2Offset contain the offset of the first and second frames, respectively, of the animation from the beginning of the file. The first frame offset is used to identify the beginning of the animation. The second offset is used as the starting point when the animation loops back to the beginning of the animation from the ring frame.

Reserved3 is not used and is set to 00h.

Chunks

All of the data in a FLI file is encapsulated into chunks. Each chunk is a collection of data beginning with a header and followed by the data for that chunk. Chunks may also contains subchunks of data with the same basic format. If a Flic reader encounters a chunk it does not recognize, it should simply skip over it.

Each chunk in a FLI file begins with a 16-byte header that contains the following format:

format:
typedef struct _ChunkHeader
{
  DWORD ChunkSize;        /* Total size of chunk */
  WORD  ChunkType;        /* Chunk identifier */
  WORD  NumberOfChunks;   /* Number of subchunks in this chunk */
  BYTE  Reserved[8];      /* Not used (Set to 00h) */
} CHUNKHEADER;

ChunkSize is the size of the chunk in bytes. This value includes the size of the header itself and any subchunks contained within the chunk.

ChunkType is an identification value indicating the format of the chunk and the type of data it contains.

NumberOfChunks specifies the number of subchunks contained within this chunk.

Reserved is not used and is set to 00h.

As we have said, a chunk may contain subchunks. In fact, the entire FLI file itself is a single chunk that begins with the FLICHEADER structure. In .FLC files, an optional CHUNKHEADER structure may follow the FLICHEADER structure. This secondary header is called a prefix header. If present, this header contains information specific to the Animator Pro application that is not used during the playback of the animation. Other applications can safely skip over the prefix header and ignore the information it contains. Applications other than Animator Pro should never include a prefix header in any .FLC files they create.

For the prefix header, ChunkSize is the size of the entire FLI file minus the 128 bytes of the FLICHEADER. ChunkType is F100h. NumberOfChunks contains the total number of subchunks in the file.

Following the prefix header is a series of frame chunks. Each frame chunk contains a single frame of data from the animation. For the frame chunk, ChunkSize is the total number of bytes in the frame, including the header and all subchunks. ChunkType is always F1FAh. NumberOfChunks contains the total number of subchunks in the frame. If the NumberOfChunks value is 0, then this frame is identical to the previous frame, so no color map or frame data is stored, and the previous frame is repeated with the delay specified in the header.

The following lists all the subchunks that may be found in a frame chunk.

ChunkType Value

Chunk Name

Chunk Data Description

04h

COLOR_256

256-level color palette

(.FLC files only)

07h

DELTA_FLC

Delta-compressed frame data

(.FLC files only)

0Bh

COLOR_64

64-level color palette

(.FLI files only)

0Ch

DELTA_FLI

Delta-compressed frame data

(.FLI files only)

0Dh

BLACK

Black frame data

0Fh

BYTE_RUN

RLE-compressed frame data

10h

FLI_COPY

Uncompressed frame data

12h

PSTAMP

Postage stamp image

(.FLC files only)

The following lists the general internal arrangement of a FLI file:


FLI header
Prefix header (optional)
Frame 1 (RLE compressed)
   PSTAMP subchunk (optional)
   COLOR_256 subchunk (256 colors)
   BYTE_RUN subchunk
   COLOR_256 subchunk (256 colors)
   BYTE_RUN subchunk
Frame 2 (Delta compressed)
   COLOR_256 subchunk (colors different from previous map
   DELTA_FLC subchunk
Frame 3 (Uncompressed)
   COLOR_256 subchunk (colors different from previous map)
   FLI_COPY subchunk
Frame 4 (Black)
   BLACK subchunk
Frame n (Delta compressed)
   COLOR_256 subchunk (colors different from previous map)
   DELTA_FLC subchunk

Each frame chunk contains at least two subchunks: a color map and the data for the frame. The frame data may be stored in one of several different compressed or uncompressed formats. The first frame of a Flic animation may also contain an additional postage stamp subchunk. Following is an explanation of each subchunk:

DELTA_FLI chunk

The DELTA_FLI chunk contains a single frame of data, which is compressed using delta encoding. The data in this chunk contains the pixel value differences between the current frame and the previous frame. Each scan line of the frame which contains pixel changes is encoded into packets, and only the values of the pixels in the line that have changed are stored.

The DELTA_FLI encoding scheme is an older scheme found mostly in .FLI files, although .FLC files may also contain DELTA_FLI chunks.

The format of a DELTA_FLI chunk is as follows:

typedef struct _DeltaFliChunk
{
  CHUNKHEADER Header;   /* Header for this chunk */
  WORD LinesToSkip;     /* Number of initial lines to skip */
  WORD NumberOfLines;   /* Number of encoded lines */
  /* Encoded line (one per 'NumberOfLines') */
  struct _Line
  {
   BYTE NumberOfPackets; /* Number of packets in this line */
   BYTE LineSkipCount;   /* Number of lines to skip */
   struct _Packet        /* Encoded packet (one/NumberOfPackets) */
    {
     BYTE SkipCount;     /* Number of pixels to skip */
     BYTE PacketType;    /* Type of encoding used on this packet */
     BYTE PixelData[];   /* Pixel data for this packet */
    } Packet[NumberOfPackets];
  } Lines[NumberOfLines];
} DELTAFLICHUNK;

LinesToSkip contains the number of lines down from the top of the image that are unchanged from the prior frame. This value is used to find the first scan line which contains deltas.

NumberOfLines indicates the number of encoded scan lines in this chunk.

NumberOfPackets indicates the number of packets used to encode this scan line. Each encoded scan line begins with this value.

LineSkipCount is the number of lines to skip to locate the next encoded line.

Each packet in every encoded line contains two values. SkipCount indicates the location of the pixel deltas in this line that are encoded in this packet. PacketType specifies the type of encoding used in this packet. A positive value indicates that the next "PacketType" pixels should be literally read from the chunk and written to the display. A negative value indicates that the absolute value of "PacketType" pixels are to be read literally from the encoded data.

For example, suppose that we have a frame with three encoded scan lines. The first is line number 25, which contains deltas at pixels 4, 22, 23, 24, and 202. The second is line number 97, which contains deltas at pixels 20 and 54 through 67. The third is line number 199, in which all 320 pixels of the line have changed to the same color. The sequence of line and packet field values is shown below:

LinesToSkip

24

Skip 24 lines to first encoded line

NumberOfLines

3

Three encoded lines in this frame

Line

Line 1

NumberOfPackets

3

Three encoded packets in this line

LineSkipCount

71

Skip 71 lines to the next encoded line

Packet

Packet 1

SkipCount

4

Skip 4 pixels

PacketType

1

Read one pixel literally

PixelData

23

New value of pixel 4 is 23

Packet

Packet 2

SkipCount

17

Skip 17 pixels

PacketType

-3

Read one pixel and repeat 3 times

PixelData

65

New value of pixels 22, 23, and 24 is 65

Packet

Packet 3

SkipCount

176

Skip 176 pixels

PacketType

1

Read one pixel literally

PixelData

17

New value of pixel 202 is 17

Line

Line 2

NumberOfPackets

2

Two encoded packets in this line

LineSkipCount

102

Skip 102 lines to the next encoded line

Packet

Packet 1

SkipCount

20

Skip 20 pixels

PacketType

1

Read one pixel literally

PixelData

121

New value of pixel 20 is 121

Packet

Packet 2

SkipCount

32

Skip 32 pixels

PacketType

13

Read next 13 pixels literally

PixelData

255

New value of pixels 54 through 67 is 255

Line

Line 3

NumberOfPackets

2

Two encoded packets in this line

LineSkipCount

0

Last encoded line in frame

Packet

Packet 1

SkipCount

0

Start at first pixel in line

PacketType

-256

Read one pixel and repeat 256 times

PixelData

0

New value of pixels 0 though 255 is 0

Packet

Packet 2

SkipCount

256

Skip 256 pixels

PacketType

-64

Read one pixel and repeat 64 times

PixelData

0

New value of pixels 256 though 319 is 0

DELTA_FLC chunk

The DELTA_FLC chunk is a newer version of the DELTA_FLI chunk and is found in all .FLC files. This chunk is essentially the same as the DELTA_FLI chunk with a few field modifications. The PixelData values stored in a DELTA_FLC chunk are 16 bits in size rather than the 8-bit pixel size found in the DELTA_FLI chunk.

The structure of a DELTA_FLC chunk is as follows:

typedef struct _DeltaFlcChunk
{
CHUNKHEADER Header;     /* Header for this chunk */
WORD NumberOfLines;     /* Number of encoded lines in chunk */
struct _Line            /* Encoded line (one/'NumberOfLines') */
  {
  WORD PacketCount;     /* Packet count, skip count, or last byte value */
  /*
  ** Additional WORDs of data may appear in this location
  */
  struct _Packet        /* Encoded packet (one per 'Count') */
    {
    BYTE SkipCount;     /* Number of pixels to skip */
    BYTE PacketType;    /* Type of encoding used on this packet */
    WORD PixelData[];   /* Pixel data for this packet */
    } Packet[NumberOfPackets];
  } Lines[NumberOfLines];
} DELTAFLCCHUNK;

The number of fields occurring between the PacketCount and the first packet will vary depending upon the value stored in PacketCount. The two most significant bits in PacketCount determine the interpretation of the value stored in this field. If these two bits are 0, then the value is the number of packets occurring in this line. Packet data immediately follows this field and there are no additional WORD values following.

A value of 0 in this field indicates that only the last pixel on the line has changed.

If the most significant bit (bit 15) is 1 and the next bit (bit 14) is 0, the low byte in this WORD is to be stored in the last byte of the current line. A WORD field containing the number of packets in this line follows this value.

If both bits 14 and 15 are set to 1, PacketCount contains a skip count to the next encoded line. PacketCount may then be followed by additional WORD values containing a packet count, skip counts, or last byte values.

BYTE_RUN chunk

When a frame is run-length encoded, the data is stored in a BYTE_RUN chunk. Normally, only the data in the first frame of an animation is encoded using this scheme.

The structure of a BYTE_RUN chunk is as follows:

typedef struct _ByteRunChunk
{
  CHUNKHEADER Header;  /* Header for this chunk */
  BYTE PixelData[];    /* RLE pixel data */
} BYTERUNCHUNK;

Each line in the frame is individually encoded into a series of one or more RLE packets. In the original .FLI format, the first byte of each encoded line was the count of the number of packets used to encode that line, with a packet maximum of 255. The .FLC format, however, allows much longer lines to be used in an animation, and more than 255 packets may be used to encode a line. Therefore, in both .FLC and .FLI files, this initial count byte is read and ignored. Instead, a FLI reader should keep track of the number of pixels decoded to determine when the end of a scan line has been reached.

The RLE scheme used in the BYTE_RUN packet is fairly simple. The first byte in each packet is a type byte that indicates how the packet data is to be interpreted. If the value of this byte is a positive number then the next byte is to be read and repeated "type" times. If the value is negative then it is converted to its absolute value and the next "type" pixels are read literally from the encoded data.

FLI_COPY chunk

This chunk contains a single, uncompressed frame of data. When a frame is stored uncompressed, the FLI_COPY chunk is used. Data is only stored uncompressed when delta or RLE encoding would result in negative compression.

The structure of a FLI_COPY chunk is as follows:

typedef struct _CopyChunk
{
  CHUNKHEADER Header;          /* Header for this chunk */
  BYTE PixelData[];            /* Raw pixel data */
} COPYCHUNK;

The number of pixels in this chunk is equal to the product of the Width and Height fields (Width*Height) in the FLI file header. FLI_COPY chunks usually result when very complex or noisy images cause the compressed frames to be larger than the uncompressed originals.

PSTAMP chunk

The PSTAMP is a postage stamp of a FLI animation found in the first frame chunk only in .FLC files. This stamp may be a reduced-sized copy of a frame from the animation, possibly from the title screen, that is used as an icon. The size of the stamp is usually 100x63 pixels, but will vary to match the aspect ratio of the frame. This chunk is skipped by FLI readers that do not support the use of PSTAMP chunks.

The PSTAMP chunk contains a CHUNKHEADER and two subchunks:

typedef struct _PstampChunk
{
  DWORD ChunkSize;              /* Total size of chunk */
  WORD  ChunkType;              /* Chunk identifier */
  WORD  Height;                 /* Height of stamp in pixels */
  WORD  Width;                  /* Width of stamp in pixels */
  WORD  ColorType;              /* Color translation type */
  BYTERUNCHUNK  PixelData;      /* Postage stamp data */
} PSTAMPCHUNK;

ChunkSize is the total size of the PSTAMP chunk.

ChunkType value is 0fh, 10h, or 12h.

Height and Width are the height and width of the stamp in pixels.

ColorType indicates the type of color space used by the postage stamp image. This value is always 01h, indicating a six-cube colorspace (see the FLI file format specification for more information on six-cube color space).

Following this header is the postage stamp data chunk.

ChunkType of this header indicates the format of the pixel data. Values are:

0Fh Indicates run-length encoding (a BYTE_RUN chunk)
10h Indicates uncompressed data (a FLI_COPY chunk)
12h Indicates a six-cube color translation table

BLACK chunk

The BLACK chunk represents a single frame of data in which all pixels are set to the color index 0 (normally black) in the color map for this frame. This chunk itself contains no data and has a ChunkType of 0Dh.

The BLACK chunk contains only a CHUNKHEADER:

typedef struct _BlackChunk
{
  CHUNKHEADER Header;	/* Header for this chunk */
} BLACKCHUNK;

COLOR_64 and COLOR_256 chunks

The FLI file format uses a color map to define the colors in an animation. The older .FLI format may have a maximum of 64 colors and stores its color map in a COLOR_64 chunk. A .FLC file may have up to 256 colors and stores its color map in a COLOR_256 chunk. Both of these chunks have the same format:

typedef struct _ColormapChunk
{
  CHUNKHEADER Header;        /* Header for this chunk */
  WORD NumberOfElements;     /* Number of color elements in map */
  struct _ColorElement       /* Color element (one per NumberOfElements) */
  {
   BYTE SkipCount;           /* Color index skip count */
   BYTE ColorCount;          /* Number of colors in this element */
   struct _ColorComponent    /* Color component (one /'ColorCount') */
   {
    BYTE Red;                /* Red component color */
    BYTE Green;              /* Green component color */
    BYTE Blue;               /* Blue component color */
   } ColorComponents[ColorCount];
  } ColorElements[NumberOfElements];
} COLORMAPCHUNK;

The value of ChunkSize in the Header varies depending upon the number of elements in this color map. A chunk containing a color map with 256 elements is 788 bytes in size and therefore ChunkSize contains the value 788.

ChunkType contains a value of 04h for a COLOR_256 chunk or a value of 0Bh for a COLOR_64 chunk.

NumberOfChunks always contains a value of 00h, indicating that this chunk contains no subchunks.

NumberOfElements indicates the number of ColorElement structures in the COLORMAPCHUNK structure. Following this value are the actual ColorElement structures themselves. Each structure contains two fields and one or more ColorComponent structures.

SkipCount indicates the number of color elements to skip when locating the next color map element.

ColorCount indicates the number of ColorComponents structures contained within this ColorElement structure. Following the ColorCount field are the actual ColorComponents structures. Each structure is three bytes in size and contains three fields.

The Red, Green, and Blue fields of each ColorComponents structure contain the component values for this color. The range of these field values is 0 to 63 for a COLOR_64 chunk and 0 to 255 for a COLOR_256 chunk.

Normally, an image file contains only one color map. A FLI file, however, allows a color map to be defined for each frame in the animation. Storing a complete color map for each frame would normally require quite a bit of data (768 bytes per frame). FLI files, however, have the capability of storing color maps that contain only the colors that change from frame to frame.

Storing only the deltas in a color map requires that not only the color values be stored, but also their locations in the map. This is accomplished by using a color index value and a skip count. Before a color map value is written, the skip count of the packet is added to the current color index. This sum is the location of the next color map value to write. The number of entries in the packet are written across the same number of entries in the color map. The color index for each color map always starts with the value 0.

For example, the first frame of a .FLC animation always contains a full, 256-element color map. This map is represented by a NumberOfElements value of 1 followed by a single ColorElements structure. This structure will contain a SkipCount value of 0, a ColorCount value of 256, and 256 ColorComponents structures defining the colors in the map. This chunk is 788 bytes in size.

Now, let's say that in the next frame the colors 2, 15, 16, 17, and 197 in the color map are different from those in the first frame. Rather than storing another 788-byte color map chunk, with 251 elements identical to the color map in the previous chunk, we will store only the values and positions of the five color components that changed in the color map.

The color map chunk for the second frame will then contain a NumberOfElements value of 3, followed by three ColorElements structures:

The sequence of fields and values for this map is the following:

NumberOfElements

3

ColorElement

SkipCount

2

ColorCount

1

ColorComponent

R,G,B

ColorElement

SkipCount

14

ColorCount

3

ColorComponent

R,G,B

ColorComponent

R,G,B

ColorComponent

R,G,B

ColorElement

SkipCount

180

ColorCount

1

ColorComponent

R,G,B

As you can see, the location of changed color elements is determined by their relative position from the previous changed elements and from their absolute position in the color map. The SkipCount value of the first element is always calculated from the 0th index position. To change the value of element 2, we skip two places, from element 0 to element 2, and change a single component value. To change the values of elements 17, 18, and 19, we make 14 skips from element 2 to element 17 and change the next three component values. We then make 180 skips to element 197 and change the final component value.

Note that if the color map for the current frame is identical to the color map of the previous frame, the color map subchunk need not appear in the current frame chunk.

For Further Information

Autodesk no longer maintains the FLI format and does not formally distribute information about it. However, you may possibly be able to get some information from their homepage:

http://www.autodesk.com

For further information about FLI, see the articles by Jim Kent and John Bridges (the author of the format) that are included on the CD-ROM. In addition, see the following article for information on FLI:

Kent, Jim. "The Flic File Format," Dr. Dobb's Journal, March 1993.



Copyright © 1996, 1994 O'Reilly & Associates, Inc. All Rights Reserved.