Copyright (c) Hyperion Entertainment and contributors.

Difference between revisions of "ANIM IFF CEL Animations"

From AmigaOS Documentation Wiki
Jump to navigation Jump to search
 
(4 intermediate revisions by the same user not shown)
Line 20: Line 20:
 
= Introduction =
 
= Introduction =
 
 
The ANIM IFF format was developed at Sparta originally for the production of animated video sequences on the Amiga computer. The intent was to be able to store, and play back, sequences of frames and to minimize both the storage space on disk (through compression) and playback time (through efficient de-compression algorithms). It was desired to maintain maximum compatibility with existing IFF formats and to be able to display the initial frame as a normal still IFF picture.
+
The ANIM IFF format was developed at Sparta originally for the production of animated video sequences on the Amiga computer. The intent was to be able to store, and play back, sequences of frames and to minimize both the storage space on disk (through compression) and playback time (through efficient decompression algorithms). It was desired to maintain maximum compatibility with existing IFF formats and to be able to display the initial frame as a normal still IFF picture.
 
 
Several compression schemes have been introduced in the ANIM format.
+
Several compression schemes have been introduced in the ANIM format. Most of these are strictly of historical interest as the only one currently being placed in new code is the vertical run length encoded byte encoding developed by Jim Kent.
Most of these are strictly of historical interest as the only one
 
currently being placed in new code is the vertical run length
 
encoded byte encoding developed by Jim Kent.
 
 
 
 
== ANIM Format Overview ==
 
== ANIM Format Overview ==
 
 
The general philosophy of ANIMs is to present the initial frame
+
The general philosophy of ANIMs is to present the initial frame as a normal, run-length-encoded, IFF picture. Subsequent
  +
frames are then described by listing only their differences from a previous frame. Normally, the "previous" frame is two frames back as that is the frame remaining in the hidden screen buffer when double-buffering is used. To better understand this, suppose one has two screens, called A and B, and the ability to instantly switch the display from one to the other. The normal playback mode is to load the initial frame into A and duplicate it into B. Then frame A is displayed on the screen. Then the differences for frame 2 are used to alter screen B and it is displayed. Then the differences for frame 3 are used to alter screen A and it is displayed, and so on. Note that frame 2 is stored as differences from frame 1, but all other frames are stored as differences from two frames back.
as a normal, run-length-encoded, IFF picture. Subsequent
 
frames are then described by listing only their differences
 
from a previous frame. Normally, the "previous" frame is two
 
frames back as that is the frame remaining in the hidden
 
screen buffer when double-buffering is used. To better
 
understand this, suppose one has two screens, called A and B,
 
and the ability to instantly switch the display from one to
 
the other. The normal playback mode is to load the initial
 
frame into A and duplicate it into B. Then frame A is displayed
 
on the screen. Then the differences for frame 2 are used to
 
alter screen B and it is displayed. Then the differences for
 
frame 3 are used to alter screen A and it is displayed, and so
 
on. Note that frame 2 is stored as differences from frame 1,
 
but all other frames are stored as differences from two frames
 
back.
 
 
 
ANIM is an IFF FORM and its basic format is as follows (this
+
ANIM is an IFF FORM and its basic format is as follows (this assumes the reader has a basic understanding of IFF format
assumes the reader has a basic understanding of IFF format
 
 
files):
 
files):
 
FORM ANIM
 
FORM ANIM
Line 64: Line 46:
 
...
 
...
 
 
The initial FORM ILBM can contain all the normal ILBM chunks,
+
The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc. The BODY will normally be a standard
  +
run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD). If desired, an ANHD
such as CRNG, etc. The BODY will normally be a standard
 
  +
chunk can appear here to provide timing data for the first frame. If it is here, the operation field should be =0.
run-length-encoded data chunk (but may be any other legal
 
compression mode as indicated by the BMHD). If desired, an ANHD
 
chunk can appear here to provide timing data for the first
 
frame. If it is here, the operation field should be =0.
 
 
 
The subsequent FORMs ILBM contain an ANHD, instead of a BMHD,
+
The subsequent FORMs ILBM contain an ANHD, instead of a BMHD, which duplicates some of BMHD and has additional parameters
  +
pertaining to the animation frame. The DLTA chunk contains the data for the delta compression modes. If the older XOR compression mode is used, then a BODY chunk will be here. In addition, other chunks may be placed in each of these as deemed necessary (and as code is placed in player programs to utilize them). A good example would be CMAP chunks to alter the color palette. A basic assumption in ANIMs is that the size of the bitmap, and the display mode (e.g. HAM) will not change through the animation. Take care when playing an ANIM that if a CMAP occurs with a frame, then the change must be applied to both buffers.
which duplicates some of BMHD and has additional parameters
 
pertaining to the animation frame. The DLTA chunk contains
 
the data for the delta compression modes. If
 
the older XOR compression mode is used, then a BODY chunk
 
will be here. In addition, other chunks may be placed in each
 
of these as deemed necessary (and as code is placed in player
 
programs to utilize them). A good example would be CMAP chunks
 
to alter the color palette. A basic assumption in ANIMs is
 
that the size of the bitmap, and the display mode (e.g. HAM)
 
will not change through the animation. Take care when playing
 
an ANIM that if a CMAP occurs with a frame, then the change must
 
be applied to both buffers.
 
 
 
  +
Note that the DLTA chunks are not interleaved bitmap representations, thus the use of the ILBM form is inappropriate for these frames. However, this inconsistency was not noted until there were a number of commercial products either released or close to release which generated/played this format. Therefore, this is probably an inconsistency which will have to stay with us.
Note that the DLTA chunks are not interleaved bitmap representations,
 
thus the use of the ILBM form is inappropriate for these frames.
 
However, this inconsistency was not noted until there were a number
 
of commercial products either released or close to release which
 
generated/played this format. Therefore, this is probably an
 
inconsistency which will have to stay with us.
 
   
 
== Recording ANIMs ==
 
== Recording ANIMs ==
   
To record an ANIM will require three bitmaps - one for
+
To record an ANIM will require three bitmaps - one for creation of the next frame, and two more for a "history" of the previous two frames for performing the compression calculations (e.g. the delta mode calculations).
creation of the next frame, and two more for a "history" of the
 
previous two frames for performing the compression calculations
 
(e.g. the delta mode calculations).
 
   
There are five frame-to-frame compression methods currently
+
There are five frame-to-frame compression methods currently defined. The first three are mainly for historical interest.
  +
The product Aegis VideoScape 3D utilizes the third method in version 1.0, but switched to method 5 on 2.0. This is the only instance known of a commercial product generating ANIMs of any of the first three methods. The fourth method is a general short or long word compression scheme which has several options including whether the compression is horizontal or vertical, and whether or not it is XOR format. This offers a choice to the user for the optimization of file size and/or playback speed. The fifth method is the byte vertical run length encoding as designed by Jim Kent. Do not confuse this with Jim's RIFF file format which is different than ANIM. Here we utilized his compression/decompression routines within the ANIM file structure.
defined. The first three are mainly for historical interest.
 
The product Aegis VideoScape 3D utilizes the third method in
 
version 1.0, but switched to method 5 on 2.0. This is
 
the only instance known of a commercial product generating
 
ANIMs of any of the first three methods. The fourth method
 
is a general short or long word compression scheme which has
 
several options including whether the compression is horizontal
 
or vertical, and whether or not it is XOR format. This offers
 
a choice to the user for the optimization of file size and/or
 
playback speed. The fifth method is the byte vertical run length
 
encoding as designed by Jim Kent. Do not confuse
 
this with Jim's RIFF file format which is different than ANIM.
 
Here we utilized his compression/decompression routines within the
 
ANIM file structure.
 
   
The following paragraphs give a general outline of each of the
+
The following paragraphs give a general outline of each of the methods of compression currently included in this spec.
methods of compression currently included in this spec.
 
   
 
=== XOR mode ===
 
=== XOR mode ===
 
 
  +
This mode is the original and is included here for historical interest. In general, the delta modes are far superior. The creation of XOR mode is quite simple. One simply performs an exclusive-or (XOR) between all corresponding bytes of the new frame and two frames back. This results in a new bitmap with 0 bits wherever the two frames were identical, and 1 bits where they are different. Then this new bitmap is saved using run-length-encoding. A major obstacle of this mode is in the time consumed in performing the XOR upon reconstructing the image.
This mode is the original and is included here for historical
 
interest. In general, the delta modes are far superior.
 
The creation of XOR mode is quite simple. One simply
 
performs an exclusive-or (XOR) between all corresponding
 
bytes of the new frame and two frames back. This results
 
in a new bitmap with 0 bits wherever the two frames were
 
identical, and 1 bits where they are different. Then this
 
new bitmap is saved using run-length-encoding. A major
 
obstacle of this mode is in the time consumed in performing
 
the XOR upon reconstructing the image.
 
 
 
 
=== Long Delta mode ===
 
=== Long Delta mode ===
 
 
  +
This mode stores the actual new frame long-words which are different, along with the offset in the bitmap. The exact format is shown and discussed in section 2 below. Each plane is handled separately, with no data being saved if no changes take place in a given plane. Strings of 2 or more long-words in a row which change can be run together so offsets do not have to be saved for each one.
This mode stores the actual new frame long-words which are
 
different, along with the offset in the bitmap. The
 
exact format is shown and discussed in section 2 below.
 
Each plane is handled separately, with no data being saved
 
if no changes take place in a given plane. Strings of
 
2 or more long-words in a row which change can be run
 
together so offsets do not have to be saved for each one.
 
   
Constructing this data chunk usually consists of having
+
Constructing this data chunk usually consists of having a buffer to hold the data, and calculating the data as one compares the new frame, long-word by long-word, with two frames back.
a buffer to hold the data, and calculating the data as
 
one compares the new frame, long-word by long-word, with
 
two frames back.
 
 
 
 
=== Short Delta mode ===
 
=== Short Delta mode ===
 
 
This mode is identical to the Long Delta mode except that
+
This mode is identical to the Long Delta mode except that short-words are saved instead of long-words. In most instances, this mode results in a smaller DLTA chunk. The Long Delta mode is mainly of interest in improving the playback speed when used on a 32-bit 68020 Turbo Amiga.
short-words are saved instead of long-words. In most
 
instances, this mode results in a smaller DLTA chunk.
 
The Long Delta mode is mainly of interest in improving
 
the playback speed when used on a 32-bit 68020 Turbo Amiga.
 
 
 
 
=== General Delta mode ===
 
=== General Delta mode ===
   
  +
The above two delta compression modes were hastily put together. This mode was an attempt to provide a well-thought-out delta compression scheme. Options provide for both short and long word compression, either vertical or horizontal compression, XOR mode (which permits reverse playback), etc. About the time this was being finalized, the fifth mode, below, was developed by Jim Kent. In practice the short-vertical-run-length-encoded deltas in this mode play back faster than the fifth mode (which is in essence a byte-vertical-run-length-encoded delta mode) but does not compress as well - especially for very noisy data such as digitized images. In most cases, playback speed not being terrifically slower, the better compression (sometimes 2x) is preferable due to limited storage media in most machines.
The above two delta compression modes were hastily put together.
 
This mode was an attempt to provide a well-thought-out delta
 
compression scheme. Options provide for both short and long
 
word compression, either vertical or horizontal compression,
 
XOR mode (which permits reverse playback), etc. About the time
 
this was being finalized, the fifth mode, below, was developed
 
by Jim Kent. In practice the short-vertical-run-length-encoded
 
deltas in this mode play back faster than the fifth mode (which
 
is in essence a byte-vertical-run-length-encoded delta mode) but
 
does not compress as well - especially for very noisy data such
 
as digitized images. In most cases, playback speed not being
 
terrifically slower, the better compression (sometimes 2x) is
 
preferable due to limited storage media in most machines.
 
   
 
Details on this method are contained in section 2.2.2 below.
 
Details on this method are contained in section 2.2.2 below.
Line 174: Line 86:
 
=== Byte Vertical Compression ===
 
=== Byte Vertical Compression ===
   
  +
This method does not offer the many options that method 4 offers, but is very successful at producing decent compression even for very noisy data such as digitized images. The method was devised by Jim Kent and is utilized in his RIFF file format which is different than the ANIM format. The description of this method in this document is taken from Jim's writings. Further, he has released both compression and decompression code to public domain.
This method does not offer the many options that method 4 offers,
 
but is very successful at producing decent compression even for
 
very noisy data such as digitized images. The method was devised
 
by Jim Kent and is utilized in his RIFF file format which is
 
different than the ANIM format. The description of this method
 
in this document is taken from Jim's writings. Further, he has
 
released both compression and decompression code to public domain.
 
   
 
Details on this method are contained in section 2.2.3 below.
 
Details on this method are contained in section 2.2.3 below.
Line 186: Line 92:
 
== Playing ANIMs ==
 
== Playing ANIMs ==
 
 
  +
Playback of ANIMs will usually require two buffers, as mentioned above, and double-buffering between them. The frame data from the ANIM file is used to modify the hidden frame to the next frame to be shown. When using the XOR mode, the usual run-length-decoding routine can be easily modified to do the exclusive-or operation required. Note that runs of zero bytes,
Playback of ANIMs will usually require two buffers, as mentioned
 
  +
which will be very common, can be ignored, as an exclusive or of any byte value to a byte of zero will not alter the original byte value.
above, and double-buffering between them. The frame data from
 
the ANIM file is used to modify the hidden frame to the next
 
frame to be shown. When using the XOR mode, the usual run-
 
length-decoding routine can be easily modified to do the
 
exclusive-or operation required. Note that runs of zero bytes,
 
which will be very common, can be ignored, as an exclusive or
 
of any byte value to a byte of zero will not alter the original
 
byte value.
 
   
  +
The general procedure, for all compression techniques, is to first decode the initial ILBM picture into the hidden buffer and double-buffer it into view. Then this picture is copied to the other (now hidden) buffer. At this point each frame is displayed with the same procedure. The next frame is formed in the hidden buffer by applying the DLTA data (or the XOR data from the BODY chunk in the case of the first XOR method) and the new frame is double-buffered into view. This process continues to the end of the file.
The general procedure, for all compression techniques, is to first
 
decode the initial ILBM picture into the hidden buffer and double-
 
buffer it into view. Then this picture is copied to the other (now
 
hidden) buffer. At this point each frame is displayed with the
 
same procedure. The next frame is formed in the hidden buffer by
 
applying the DLTA data (or the XOR data from the BODY chunk in the
 
case of the first XOR method) and the new frame is double-buffered
 
into view. This process continues to the end of the file.
 
   
  +
A master colormap should be kept for the entire ANIM which would be initially set from the CMAP chunk in the initial ILBM. This colormap should be used for each frame. If a CMAP chunk appears in one of the frames, then this master colormap is updated and the new colormap applies to all frames until the occurrance of another CMAP chunk.
A master colormap should be kept for the entire ANIM which would
 
be initially set from the CMAP chunk in the initial ILBM. This
 
colormap should be used for each frame. If a CMAP chunk appears
 
in one of the frames, then this master colormap is updated and the
 
new colormap applies to all frames until the occurrance of another
 
CMAP chunk.
 
   
  +
Looping ANIMs may be constructed by simply making the last two frames identical to the first two. Since the first two frames are special cases (the first being a normal ILBM and the second being a delta from the first) one can continually loop the animation by repeating from frame three. In this case the delta for creating frame three will modify the next to the last frame which is in the hidden buffer (which is identical to the first frame), and the delta for creating frame four will modify the last frame which is identical to the second frame.
Looping ANIMs may be constructed by simply making the last two frames
 
identical to the first two. Since the first two frames are special
 
cases (the first being a normal ILBM and the second being a delta from
 
the first) one can continually loop the anim by repeating from frame
 
three. In this case the delta for creating frame three will modify
 
the next to the last frame which is in the hidden buffer (which is
 
identical to the first frame), and the delta for creating frame four
 
will modify the last frame which is identical to the second frame.
 
   
  +
Multi-File ANIMs are also supported so long as the first two frames of a subsequent file are identical to the last two frames of the preceeding file. Upon reading subsequent files, the ILBMs for the first two frames are simply ignored, and the remaining frames are simply appended to the preceding frames. This permits splitting ANIMs across multiple floppies and also permits playing each section independently and/or editing it independent of the rest of the ANIM.
Multi-File ANIMs are also supported so long as the first two frames
 
of a subsequent file are identical to the last two frames of the
 
preceeding file. Upon reading subsequent files, the ILBMs for the
 
first two frames are simply ignored, and the remaining frames are
 
simply appended to the preceeding frames. This permits splitting
 
ANIMs across multiple floppies and also permits playing each section
 
independently and/or editing it independent of the rest of the ANIM.
 
 
 
  +
Timing of ANIM playback is easily achieved using the vertical blank interrupt of the Amiga. There is an example of setting up such a timer in the SDK. Be sure to remember the timer value when a frame is flipped up, so the next frame can be flipped up relative to that time. This will make the playback independent of how long it takes to decompress a frame (so long as there is enough time between frames to accomplish this decompression).
Timing of ANIM playback is easily achieved using the vertical blank
 
interrupt of the Amiga. There is an example of setting up such
 
a timer in the SDK. Be sure to remember the timer
 
value when a frame is flipped up, so the next frame can be flipped
 
up relative to that time. This will make the playback independent
 
of how long it takes to decompress a frame (so long as there is enough
 
time between frames to accomplish this decompression).
 
   
 
= Chunk Formats =
 
= Chunk Formats =
Line 269: Line 137:
   
 
; UWORD w,h
 
; UWORD w,h
: (XOR mode only - width and height of the area represented by the BODY to eliminate unnecessary un-changed data)
+
: (XOR mode only - width and height of the area represented by the BODY to eliminate unnecessary unchanged data)
   
 
; WORD x,y
 
; WORD x,y
: (XOR mode only - position of rectangular area representd by the BODY)
+
: (XOR mode only - position of rectangular area represented by the BODY)
   
 
; ULONG abstime
 
; ULONG abstime
Line 311: Line 179:
 
== DLTA Chunk ==
 
== DLTA Chunk ==
 
 
This chunk is the basic data chunk used to hold delta compression
+
This chunk is the basic data chunk used to hold delta compression data. The format of the data will be dependent upon the exact compression format selected. At present there are two basic formats for the overall structure of this chunk.
data. The format of the data will be dependent upon the exact
 
compression format selected. At present there are two basic
 
formats for the overall structure of this chunk.
 
   
 
=== Format for methods 2 & 3 ===
 
=== Format for methods 2 & 3 ===
   
This chunk is a basic data chunk used to hold the delta
+
This chunk is a basic data chunk used to hold the delta compression data. The minimum size of this chunk is 32 bytes as the first 8 long-words are byte pointers into the chunk for the data for each of up to 8 bit planes. The pointer for the
  +
plane data starting immediately following these 8 pointers will have a value of 32 as the data starts in the 33-rd byte of the chunk (index value of 32 due to zero-base indexing).
compression data. The minimum size of this chunk is 32 bytes
 
as the first 8 long-words are byte pointers into the chunk for
 
the data for each of up to 8 bitplanes. The pointer for the
 
plane data starting immediately following these 8 pointers will
 
have a value of 32 as the data starts in the 33-rd byte of the
 
chunk (index value of 32 due to zero-base indexing).
 
   
 
The data for a given plane consists of groups of data words. In
 
The data for a given plane consists of groups of data words. In
Line 333: Line 193:
 
Each group consists of a starting word which is an offset. If
 
Each group consists of a starting word which is an offset. If
 
the offset is positive then it indicates the increment in long
 
the offset is positive then it indicates the increment in long
or short words (whichever is appropriate) through the bitplane.
+
or short words (whichever is appropriate) through the bit plane.
 
In other words, if you were reconstructing the plane, you would
 
In other words, if you were reconstructing the plane, you would
 
start a pointer (to shorts or longs depending on the mode) to
 
start a pointer (to shorts or longs depending on the mode) to
point to the first word of the bitplane. Then the offset would
+
point to the first word of the bit plane. Then the offset would
 
be added to it and the following data word would be placed at
 
be added to it and the following data word would be placed at
 
that position. Then the next offset would be added to the
 
that position. Then the next offset would be added to the
Line 348: Line 208:
 
follow. Following that is the indicated number of contiguous
 
follow. Following that is the indicated number of contiguous
 
data words (longs or shorts depending on mode) which are to
 
data words (longs or shorts depending on mode) which are to
be placed in contiguous locations of the bitplane.
+
be placed in contiguous locations of the bit plane.
   
 
If there are no changed words in a given plane, then the pointer
 
If there are no changed words in a given plane, then the pointer
Line 357: Line 217:
 
The DLTA chunk is modified slightly to have 16 long pointers at
 
The DLTA chunk is modified slightly to have 16 long pointers at
 
the start. The first 8 are as before - pointers to the start of
 
the start. The first 8 are as before - pointers to the start of
the data for each of the bitplanes (up to a theoretical max of 8
+
the data for each of the bit planes (up to a theoretical max of 8
 
planes). The next 8 are pointers to the start of the offset/numbers
 
planes). The next 8 are pointers to the start of the offset/numbers
 
data list. If there is only one list of offset/numbers for all
 
data list. If there is only one list of offset/numbers for all
 
planes, then the pointer to that list is repeated in all positions
 
planes, then the pointer to that list is repeated in all positions
 
so the playback code need not even be aware of it. In fact, one
 
so the playback code need not even be aware of it. In fact, one
could get fancy and have some bitplanes share lists while others
+
could get fancy and have some bit planes share lists while others
 
have different lists, or no lists (the problems in these schemes
 
have different lists, or no lists (the problems in these schemes
 
lie in the generation, not in the playback).
 
lie in the generation, not in the playback).
Line 426: Line 286:
 
reasons. First to be somewhat compatible with code for option
 
reasons. First to be somewhat compatible with code for option
 
4 (although this has not proven to be of any benefit) and
 
4 (although this has not proven to be of any benefit) and
second, to allow extending the format for more bitplanes (code
+
second, to allow extending the format for more bit planes (code
 
has been written for up to 12 planes).
 
has been written for up to 12 planes).
   
Line 439: Line 299:
 
code (skip.c and unvscomp.asm) for more details:
 
code (skip.c and unvscomp.asm) for more details:
   
Each column of the bitplane is compressed separately.
+
Each column of the bit plane is compressed separately.
A 320x200 bitplane would have 40 columns of 200 bytes each.
+
A 320x200 bit plane would have 40 columns of 200 bytes each.
 
Each column starts with an op-count followed by a number
 
Each column starts with an op-count followed by a number
of ops. If the op-count is zero, that's ok, it just means
+
of ops. If the op-count is zero, that's OK, it just means
 
there's no change in this column from the last frame.
 
there's no change in this column from the last frame.
 
The ops are of three classes, and followed by a varying
 
The ops are of three classes, and followed by a varying
Line 600: Line 460:
 
: Wr. Neustaedterstr. 140
 
: Wr. Neustaedterstr. 140
   
Anim method 7 is designed for maximum playback speed and acceptable
+
Anim method 7 is designed for maximum playback speed and acceptable packing rates (packing usually not as good as method 5, but more efficient than methods 1 -- 4)
packing rates (packing usually not as good as method 5, but more
 
efficient than methodes 1 -- 4)
 
   
Method 7 was not originally in the IFF specification
+
Method 7 was not originally in the IFF specification but supported by the Public Domain Programs AAP/AAC.
but supported by the Public Domain Programs AAP/AAC.
 
   
 
== Chunk Sequence ==
 
== Chunk Sequence ==
   
Method 7 Anims should use the same Chunk Sequence as methods 1..5.
+
Method 7 Anims should use the same Chunk Sequence as methods 1..5. Alternatively the first frame may have a DLTA chunk instead of the BODY chunk.
Alternativley the first frame may have a DLTA chunk instead
 
of the BODY chunk.
 
   
In that case the DLTA is the difference to a 'black frame'.
+
In that case the DLTA is the difference to a 'black frame'. A player has to clear all bit planes of the first bitmap to zero, and then call his DLTA unpack routines for this frame.
A player has to clear all bitplanes of the first bitmap to zero,
 
and then call his DLTA unpack routines for this frame.
 
   
 
FORM ANIM
 
FORM ANIM
Line 671: Line 524:
 
In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8 planes. The second set of 8 longwords are pointers to the corresponding data lists. If there are less than 8 Planes all unused pointers are set to zero.
 
In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8 planes. The second set of 8 longwords are pointers to the corresponding data lists. If there are less than 8 Planes all unused pointers are set to zero.
   
Compression/decompression is performed on a plane-by-plane basis.
+
Compression/decompression is performed on a plane-by-plane basis. The following description of the method is similar to
  +
Jim Kent's method 5, except that data is stored in a separated data list (long or short, depending on bit#0 of the ANHD bits) and doesn't follow immediate after the opcode.
The following description of the method is similar to
 
Jim Kent's method 5, except that data is stored in a seperated
 
datalist (long or short, depending on bit#0 of the ANHD bits)
 
and doesn't follow immediate after the opcode.
 
   
  +
In method 7 the bit plane is split into vertical columns. Each column of the bit plane is compressed separately. A 320x200 bitplane would have 20 columns of 200 short datas each. (or 10 columns of 200 long datas)
In method 7 the bitplane is splitted into vertical columns.
 
Each column of the bitplane is compressed separately.
 
A 320x200 bitplane would have 20 columns of 200 short datas each.
 
(or 10 columns of 200 long datas)
 
   
Each column starts with an op-count followed by a number
+
Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means
  +
there's no change in this column from the last frame. The ops are of three classes. The ops refer to a varying
of ops. If the op-count is zero, that's ok, it just means
 
  +
amount of data (to fetch from the corresponding data list) depending on which class:
there's no change in this column from the last frame.
 
The ops are of three classes. The ops refer to a varying
 
amount of data (to fetch from the corresponding datalist)
 
depending on which class:
 
   
# Skip ops - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, ie to skip. It is non-zero. Skip ops have no corresponding data-items in the datalist.
+
# Skip ops - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero. Skip ops have no corresponding data-items in the data list.
# Uniq ops - this is a byte with the hi bit set. The hi bit is masked down and the remainder is a count of the number of data to copy literally from the datalist to the "dest" pointer column. (Each data item to the next destination row) Data items may be long or short organized.
+
# Uniq ops - this is a byte with the hi bit set. The hi bit is masked down and the remainder is a count of the number of data to copy literally from the data list to the "dest" pointer column. (Each data item to the next destination row) Data items may be long or short organized.
# Same ops - this is a 0 byte followed by a count byte. The count byte says how many rows of the current column are to be set to the same data-item. the data-item (long or short) is fetched from the datalist.
+
# Same ops - this is a 0 byte followed by a count byte. The count byte says how many rows of the current column are to be set to the same data-item. the data-item (long or short) is fetched from the data list.
   
 
{{Note|text=Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next address in the destination we have to add the number of bytes per row instead of 2 (or 4)!}}
 
{{Note|text=Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next address in the destination we have to add the number of bytes per row instead of 2 (or 4)!}}
Line 701: Line 545:
 
Joe Porkka 10-jan-92
 
Joe Porkka 10-jan-92
   
Anim method 8 is designed for maximum playback speed and acceptable
+
Anim method 8 is designed for maximum playback speed and acceptable packing rates (packing usually not as good as method 5, but more efficient than methods 1 -- 4). In addition, it is easier to convert existing Anim5 code to support Anim8 than Anim7.
packing rates (packing usually not as good as method 5, but more
 
efficient than methodes 1 -- 4). In addition, it is easier to convert
 
existing Anim5 code to support Anim8 than Anim7.
 
   
 
== Chunk Sequence ==
 
== Chunk Sequence ==
   
Method 8 Anims should use the same Chunk Sequence as methods 1..5.
+
Method 8 Anims should use the same Chunk Sequence as methods 1..5. Alternatively the first frame may have a DLTA chunk instead of the BODY chunk.
Alternativley the first frame may have a DLTA chunk instead
 
of the BODY chunk.
 
   
In that case the DLTA is the difference to a 'black frame'.
+
In that case the DLTA is the difference to a 'black frame'. A player has to clear all bit planes of the first bitmap to zero, and then call his DLTA unpack routines for this frame. The same rules about copying the first frame into both frame buffers still applies in this case.
A player has to clear all bitplanes of the first bitmap to zero,
 
and then call his DLTA unpack routines for this frame.
 
The same rules about copying the first frame into both frame
 
buffers still applies in this case.
 
   
 
FORM ANIM
 
FORM ANIM
Line 734: Line 569:
 
...
 
...
   
  +
The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc. The BODY will normally be a standard run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD). If desired, an ANHD chunk can appear here to provide timing data for the first frame. If it is here, the operation field should be =0.
The initial FORM ILBM can contain all the normal ILBM chunks,
 
such as CRNG, etc. The BODY will normally be a standard
 
run-length-encoded data chunk (but may be any other legal
 
compression mode as indicated by the BMHD). If desired, an ANHD
 
chunk can appear here to provide timing data for the first
 
frame. If it is here, the operation field should be =0.
 
   
If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk
+
If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk must appear, and the operation field must be set to the
must appear, and the operation field must be set to the
 
 
according anim method.
 
according anim method.
   
Each of the frames from frame 2 on up may use an anhd->operation
+
Each of the frames from frame 2 on up may use an anhd->operation of 0, 5 or 8. Note that only for the first frame in the file do you copy the image data into two buffers, not every time you get an ANHD->operation==0.
of 0, 5 or 8. Note that only for the first frame in the file do
 
you copy the image data into two buffers, not every time you get
 
an ANHD->operation==0.
 
   
 
== Chunk Formats ==
 
== Chunk Formats ==
Line 764: Line 590:
 
UBYTE interleave = 0 (see ANHD description above)
 
UBYTE interleave = 0 (see ANHD description above)
 
UBYTE pad0 unused
 
UBYTE pad0 unused
ULONG bits 32 option bits used by methode=4 and 5.
+
ULONG bits 32 option bits used by method=4 and 5.
methode 8 uses only bit #0
+
method 8 uses only bit #0
 
bit # set =0 set =1
 
bit # set =0 set =1
 
=============================================
 
=============================================
Line 776: Line 602:
 
* 16 pointers same as in method 5
 
* 16 pointers same as in method 5
   
In this method the DLTA Chunk begins with 16 pointers.
+
In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8
The first 8 longwords are pointers to the opcode lists for up to 8
+
planes. The second set of 8 longwords are unused. If there are less than 8 Planes all unused pointers are set to zero.
planes. The second set of 8 longwords are unused. If there are
 
less than 8 Planes all unused pointers are set to zero.
 
   
Compression/decompression is performed on a plane-by-plane basis.
+
Compression/decompression is performed on a plane-by-plane basis. The following description of the method is similar to Jim Kent's methode 5, except that data is either in WORDs or LONGS, depending on bit 0 of the ANHD bits.
The following description of the method is similar to
 
Jim Kent's methode 5, except that data is either in WORDs or LONGS,
 
depending on bit 0 of the ANHD bits.
 
   
  +
In method 8 the bit plane is split into vertical columns. Each column of the bit plane is compressed separately. A 320x200 bit plane would have 20 columns of 200 short data each (or 10 columns of 200 long data).
In methode 8 the bitplane is split into vertical columns.
 
Each column of the bitplane is compressed separately.
 
A 320x200 bitplane would have 20 columns of 200 short datas each.
 
(or 10 columns of 200 long datas)
 
   
  +
Each column of the bit plane is compressed separately. A 320x200 bit plane would have 20 (WORD) or 10 (LONG)columns of 200 bytes each. Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means there's no change in this column from the last frame. The ops are of three classes, and followed by a varying amount of data depending on which class:
Each column of the bitplane is compressed
 
separately. A 320x200 bitplane would have 20
 
(WORD) or 10 (LONG)columns of 200 bytes each.
 
Each column starts with an op-count followed by a
 
number of ops. If the op-count is zero, that's
 
ok, it just means there's no change in this
 
column from the last frame. The ops are of three
 
classes, and followed by a varying amount of data
 
depending on which class:
 
   
# Skip ops - this is a word or long with the hi bit clear that says how many rows to move the "dest" pointer forward, ie to skip. It is non-zero. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.
+
# Skip ops - this is a word or long with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.
 
# Uniq ops - this is a word or long with the hi bit set. The hi bit is masked down and the remainder is a count of the number of bytes of data to copy literally. It's of course followed by the data to copy. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.
 
# Uniq ops - this is a word or long with the hi bit set. The hi bit is masked down and the remainder is a count of the number of bytes of data to copy literally. It's of course followed by the data to copy. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.
 
# Same ops - this is a 0 word or long followed by a count word or long, followed by a word or long value to repeat count times. Note that the range of values is much larger for word and long data, 0xffff and 0xffffffff.
 
# Same ops - this is a 0 word or long followed by a count word or long, followed by a word or long value to repeat count times. Note that the range of values is much larger for word and long data, 0xffff and 0xffffffff.
Line 807: Line 617:
 
{{Note|text=Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next word or long in the destination we add the number of bytes per row instead of one!}}
 
{{Note|text=Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next word or long in the destination we add the number of bytes per row instead of one!}}
   
  +
There is a slight complication in the case of long data. Normally an Amiga BitMap is and even number of 16bit WORDs wide, so it is possible to have an image which is not an even number or LONGs wide. For example, an image which is 336 pixels wide is 42 bytes wide, 21 words wide, and 10.5 longs wide. In the case that the data is not an even number of longs wide, and the data is to be long compressed, then the last column of data is to be word compressed instead. So, that 336 pixel wide image would be compress as 10 long columns and 1 word column.
There is a slight complication in the case of long data. Normally an
 
Amiga BitMap is and even number of 16bit WORDs wide, so it is possible
 
to have an image which is not an even number or LONGs wide. For example,
 
an image which is 336 pixels wide is 42 bytes wide, 21 words wide, and
 
10.5 longs wide. In the case that the data is not an even number of longs
 
wide, and the data is to be long compressed, then the last column of
 
data is to be word compressed instead. So, that 336 pixel wide image would
 
be compress as 10 long columns and 1 word column.
 
   
 
= ANIM.brush =
 
= ANIM.brush =
Line 822: Line 625:
 
From a description by the author of DPaint, Dan Silva, Electronic Arts.
 
From a description by the author of DPaint, Dan Silva, Electronic Arts.
   
The "Anim Brushes" of DPaint III are saved on disk in the IFF "ANIM"
+
The "Anim Brushes" of DPaint III are saved on disk in the IFF "ANIM" format. Basically, an ANIM Form consists of an initial ILBM which is the first frame of the animation, and any number of subsequent "ILBM"S (which aren't really ILBM's) each of which contains an ANHD animation header chunk and a DLTA chunk comprised of the encoded difference between a frame and a previous one.
format. Basically, an ANIM Form consists of an initial ILBM
 
which is the first frame of the animation, and any number of
 
subsequent "ILBM"S (which aren't really ILBM's) each of which
 
contains an ANHD animation header chunk and a DLTA chunk
 
comprised of the encoded difference between a frame and a previous one.
 
   
  +
To use ANIM terminology (for a description of the ANIM format, see the IFF Anim Spec, by Gary Bonham). Anim Brushes use a "type 5" encoding, which is a vertical, byte-oriented delta encoding (based on Jim Kent's RIFF). The deltas have an interleave of 1, meaning deltas are computed between adjacent frames, rather than between frames 2 apart, which is the usual ANIM custom for the purpose of fast hardware page-flipping. Also, the deltas use Exclusive Or to allow reversable play.
To use ANIM terminology (for a description of the ANIM format,
 
see the IFF Anim Spec, by Gary Bonham). Anim Brushes use a "type
 
5" encoding, which is a vertical, byte-oriented delta encoding
 
(based on Jim Kent's RIFF). The deltas have an interleave of 1,
 
meaning deltas are computed between adjacent frames, rather than
 
between frames 2 apart, which is the usual ANIM custom for the
 
purpose of fast hardware page-flipping. Also, the deltas use
 
Exclusive Or to allow reversable play.
 
   
  +
However, to my knowledge, all the existing Anim players in the Amiga world will only play type 5 "Anim"s which have an interleave of 0 (i.e. 2) and which use a Store operation rather than Exclusive Or, so no existing programs will read Anim Brushes anyway. The job of modifying existing Anim readers to read Anim Brushes should be simplified, however.
However, to my knowledge, all the existing Anim players in the Amiga
 
world will only play type 5 "Anim"s which have an interleave of 0 (i.e. 2)
 
and which use a Store operation rather than Exclusive Or, so no existing
 
programs will read Anim Brushes anyway. The job of modifying existing
 
Anim readers to read Anim Brushes should be simplified, however.
 
   
Here is an outline of the structure of the IFF Form output by
+
Here is an outline of the structure of the IFF Form output by DPaint III as an "Anim Brush". The IFF Reader should of course be flexible enough to tolerate variation in what chunks actually appear in the initial ILBM.
DPaint III as an "Anim Brush". The IFF Reader should of course be
 
flexible enough to tolerate variation in what chunks actually
 
appear in the initial ILBM.
 
   
 
FORM ANIM
 
FORM ANIM
Line 947: Line 731:
 
{{Note|text=The "bits" field was actually intended ( by the original creator of the ANIM format, Gary Bonham of SPARTA, Inc.) for use with only with compression method 4. I am using bit 2 of the bits field to indicate the Exclusive OR operation in the context of method 5, which seems like a reasonable generalization.}}
 
{{Note|text=The "bits" field was actually intended ( by the original creator of the ANIM format, Gary Bonham of SPARTA, Inc.) for use with only with compression method 4. I am using bit 2 of the bits field to indicate the Exclusive OR operation in the context of method 5, which seems like a reasonable generalization.}}
   
  +
== DLTA ==
For an Anim Brush with 10 frames, there will be an initial frame
 
  +
followed by 10 Delta's (i.e ILBMS containing ANHD and DLTA
 
  +
For an Anim Brush with 10 frames, there will be an initial frame followed by 10 Delta's (i.e ILBMS containing ANHD and DLTA
chunks). Applying the first Delta to the initial frame generates
 
the second frame, applying the second Delta to the second frame
+
chunks). Applying the first Delta to the initial frame generates the second frame, applying the second Delta to the second frame
generates the third frame, etc. Applying the last Delta thus
+
generates the third frame, etc. Applying the last Delta thus brings back the first frame.
brings back the first frame.
 
   
The DLTA chunk begins with 16 LONG plane offets, of which DPaint
+
The DLTA chunk begins with 16 LONG plane offets, of which DPaint only uses the first 6 (at most). These plane offsets are either
  +
the offset (in bytes ) from the beginning of the DLTA chunk to the data for the corresponding plane, or Zero, if there was no
only uses the first 6 (at most). These plane offsets are either
 
the offset (in bytes ) from the beginning of the DLTA chunk to
+
change in that plane. Thus the first plane offset is either 0 or 64.
the data for the corresponding plane, or Zero, if there was no
 
change in that plane. Thus the first plane offset is either 0 or
 
64.
 
   
 
(The following description of the method is based on Gary Bonham's rewording of Jim Kent's RIFF documentation.)
 
(The following description of the method is based on Gary Bonham's rewording of Jim Kent's RIFF documentation.)
Line 965: Line 745:
 
Compression/decompression is performed on a plane-by-plane basis.
 
Compression/decompression is performed on a plane-by-plane basis.
   
Each byte-column of the bitplane is compressed separately. A
+
Each byte-column of the bit plane is compressed separately. A 320x200 bit plane would have 40 columns of 200 bytes each. In
  +
general, the bit planes are always an even number of bytes wide, so for instance a 17x20 bit plane would have 4 columns of 20
320x200 bitplane would have 40 columns of 200 bytes each. In
 
general, the bitplanes are always an even number of bytes wide,
 
so for instance a 17x20 bitplane would have 4 columns of 20
 
 
bytes each.
 
bytes each.
   
Each column starts with an op-count followed by a number of
+
Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means there's no change in this column from the last frame. The ops are of three kinds, and followed by a varying amount of data depending on which kind:
ops. If the op-count is zero, that's ok, it just means there's
 
no change in this column from the last frame. The ops are of
 
three kinds, and followed by a varying amount of data depending
 
on which kind:
 
   
# SKIP - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, ie to skip. It is non-zero.
+
# SKIP - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero.
 
# DUMP - this is a byte with the hi bit set. The hi bit is masked off and the remainder is a count of the number of bytes of data to XOR directly. It is followed by the bytes to copy.
 
# DUMP - this is a byte with the hi bit set. The hi bit is masked off and the remainder is a count of the number of bytes of data to XOR directly. It is followed by the bytes to copy.
 
# RUN - this is a 0 byte followed by a count byte, followed by a byte value to repeat "count" times, XOR'ing it into the destination.
 
# RUN - this is a 0 byte followed by a count byte, followed by a byte value to repeat "count" times, XOR'ing it into the destination.

Latest revision as of 23:00, 8 July 2013

ANIM

An IFF Format For CEL Animations

Revision date: 6 June 2013

Originally prepared by:

SPARTA Inc.
23041 de la Carlota
Laguna Hills, Calif 92653
(714) 768-8161
Contact: Gary Bonham

Also by:

Aegis Development Co.
2115 Pico Blvd.
Santa Monica, Calif 90405
(213) 392-9972

Introduction

The ANIM IFF format was developed at Sparta originally for the production of animated video sequences on the Amiga computer. The intent was to be able to store, and play back, sequences of frames and to minimize both the storage space on disk (through compression) and playback time (through efficient decompression algorithms). It was desired to maintain maximum compatibility with existing IFF formats and to be able to display the initial frame as a normal still IFF picture.

Several compression schemes have been introduced in the ANIM format. Most of these are strictly of historical interest as the only one currently being placed in new code is the vertical run length encoded byte encoding developed by Jim Kent.

ANIM Format Overview

The general philosophy of ANIMs is to present the initial frame as a normal, run-length-encoded, IFF picture. Subsequent frames are then described by listing only their differences from a previous frame. Normally, the "previous" frame is two frames back as that is the frame remaining in the hidden screen buffer when double-buffering is used. To better understand this, suppose one has two screens, called A and B, and the ability to instantly switch the display from one to the other. The normal playback mode is to load the initial frame into A and duplicate it into B. Then frame A is displayed on the screen. Then the differences for frame 2 are used to alter screen B and it is displayed. Then the differences for frame 3 are used to alter screen A and it is displayed, and so on. Note that frame 2 is stored as differences from frame 1, but all other frames are stored as differences from two frames back.

ANIM is an IFF FORM and its basic format is as follows (this assumes the reader has a basic understanding of IFF format files):

                     FORM ANIM
                     . FORM ILBM         first frame
                     . . BMHD                normal type IFF data
                     . . ANHD                optional animation header
                                             chunk for timing of 1st frame.
                     . . CMAP
                     . . BODY
                     . FORM ILBM         frame 2
                     . . ANHD                animation header chunk
                     . . DLTA                delta mode data
                     . FORM ILBM         frame 3
                     . . ANHD
                     . . DLTA
                          ...
     

The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc. The BODY will normally be a standard run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD). If desired, an ANHD chunk can appear here to provide timing data for the first frame. If it is here, the operation field should be =0.

The subsequent FORMs ILBM contain an ANHD, instead of a BMHD, which duplicates some of BMHD and has additional parameters pertaining to the animation frame. The DLTA chunk contains the data for the delta compression modes. If the older XOR compression mode is used, then a BODY chunk will be here. In addition, other chunks may be placed in each of these as deemed necessary (and as code is placed in player programs to utilize them). A good example would be CMAP chunks to alter the color palette. A basic assumption in ANIMs is that the size of the bitmap, and the display mode (e.g. HAM) will not change through the animation. Take care when playing an ANIM that if a CMAP occurs with a frame, then the change must be applied to both buffers.

Note that the DLTA chunks are not interleaved bitmap representations, thus the use of the ILBM form is inappropriate for these frames. However, this inconsistency was not noted until there were a number of commercial products either released or close to release which generated/played this format. Therefore, this is probably an inconsistency which will have to stay with us.

Recording ANIMs

To record an ANIM will require three bitmaps - one for creation of the next frame, and two more for a "history" of the previous two frames for performing the compression calculations (e.g. the delta mode calculations).

There are five frame-to-frame compression methods currently defined. The first three are mainly for historical interest. The product Aegis VideoScape 3D utilizes the third method in version 1.0, but switched to method 5 on 2.0. This is the only instance known of a commercial product generating ANIMs of any of the first three methods. The fourth method is a general short or long word compression scheme which has several options including whether the compression is horizontal or vertical, and whether or not it is XOR format. This offers a choice to the user for the optimization of file size and/or playback speed. The fifth method is the byte vertical run length encoding as designed by Jim Kent. Do not confuse this with Jim's RIFF file format which is different than ANIM. Here we utilized his compression/decompression routines within the ANIM file structure.

The following paragraphs give a general outline of each of the methods of compression currently included in this spec.

XOR mode

This mode is the original and is included here for historical interest. In general, the delta modes are far superior. The creation of XOR mode is quite simple. One simply performs an exclusive-or (XOR) between all corresponding bytes of the new frame and two frames back. This results in a new bitmap with 0 bits wherever the two frames were identical, and 1 bits where they are different. Then this new bitmap is saved using run-length-encoding. A major obstacle of this mode is in the time consumed in performing the XOR upon reconstructing the image.

Long Delta mode

This mode stores the actual new frame long-words which are different, along with the offset in the bitmap. The exact format is shown and discussed in section 2 below. Each plane is handled separately, with no data being saved if no changes take place in a given plane. Strings of 2 or more long-words in a row which change can be run together so offsets do not have to be saved for each one.

Constructing this data chunk usually consists of having a buffer to hold the data, and calculating the data as one compares the new frame, long-word by long-word, with two frames back.

Short Delta mode

This mode is identical to the Long Delta mode except that short-words are saved instead of long-words. In most instances, this mode results in a smaller DLTA chunk. The Long Delta mode is mainly of interest in improving the playback speed when used on a 32-bit 68020 Turbo Amiga.

General Delta mode

The above two delta compression modes were hastily put together. This mode was an attempt to provide a well-thought-out delta compression scheme. Options provide for both short and long word compression, either vertical or horizontal compression, XOR mode (which permits reverse playback), etc. About the time this was being finalized, the fifth mode, below, was developed by Jim Kent. In practice the short-vertical-run-length-encoded deltas in this mode play back faster than the fifth mode (which is in essence a byte-vertical-run-length-encoded delta mode) but does not compress as well - especially for very noisy data such as digitized images. In most cases, playback speed not being terrifically slower, the better compression (sometimes 2x) is preferable due to limited storage media in most machines.

Details on this method are contained in section 2.2.2 below.

Byte Vertical Compression

This method does not offer the many options that method 4 offers, but is very successful at producing decent compression even for very noisy data such as digitized images. The method was devised by Jim Kent and is utilized in his RIFF file format which is different than the ANIM format. The description of this method in this document is taken from Jim's writings. Further, he has released both compression and decompression code to public domain.

Details on this method are contained in section 2.2.3 below.

Playing ANIMs

Playback of ANIMs will usually require two buffers, as mentioned above, and double-buffering between them. The frame data from the ANIM file is used to modify the hidden frame to the next frame to be shown. When using the XOR mode, the usual run-length-decoding routine can be easily modified to do the exclusive-or operation required. Note that runs of zero bytes, which will be very common, can be ignored, as an exclusive or of any byte value to a byte of zero will not alter the original byte value.

The general procedure, for all compression techniques, is to first decode the initial ILBM picture into the hidden buffer and double-buffer it into view. Then this picture is copied to the other (now hidden) buffer. At this point each frame is displayed with the same procedure. The next frame is formed in the hidden buffer by applying the DLTA data (or the XOR data from the BODY chunk in the case of the first XOR method) and the new frame is double-buffered into view. This process continues to the end of the file.

A master colormap should be kept for the entire ANIM which would be initially set from the CMAP chunk in the initial ILBM. This colormap should be used for each frame. If a CMAP chunk appears in one of the frames, then this master colormap is updated and the new colormap applies to all frames until the occurrance of another CMAP chunk.

Looping ANIMs may be constructed by simply making the last two frames identical to the first two. Since the first two frames are special cases (the first being a normal ILBM and the second being a delta from the first) one can continually loop the animation by repeating from frame three. In this case the delta for creating frame three will modify the next to the last frame which is in the hidden buffer (which is identical to the first frame), and the delta for creating frame four will modify the last frame which is identical to the second frame.

Multi-File ANIMs are also supported so long as the first two frames of a subsequent file are identical to the last two frames of the preceeding file. Upon reading subsequent files, the ILBMs for the first two frames are simply ignored, and the remaining frames are simply appended to the preceding frames. This permits splitting ANIMs across multiple floppies and also permits playing each section independently and/or editing it independent of the rest of the ANIM.

Timing of ANIM playback is easily achieved using the vertical blank interrupt of the Amiga. There is an example of setting up such a timer in the SDK. Be sure to remember the timer value when a frame is flipped up, so the next frame can be flipped up relative to that time. This will make the playback independent of how long it takes to decompress a frame (so long as there is enough time between frames to accomplish this decompression).

Chunk Formats

ANHD Chunk

The ANHD chunk consists of the following data structure:

UBYTE operation
The compression method:
0 set directly (normal ILBM BODY)
1 XOR ILBM mode
2 Long Delta mode
3 Short Delta mode
4 Generalized short/long Delta mode
5 Byte Vertical Delta mode
6 Stereo op 5 (third party)
7 short/long Vertical Delta mode
74 (ASCII 'J') reserved for Eric Graham's compression technique (details to be released later).
UBYTE mask
(XOR mode only - plane mask where each bit is set =1 if there is data and =0 if not.)
UWORD w,h
(XOR mode only - width and height of the area represented by the BODY to eliminate unnecessary unchanged data)
WORD x,y
(XOR mode only - position of rectangular area represented by the BODY)
ULONG abstime
(currently unused - timing for a frame relative to the time the first frame was displayed - in jiffies (1/60 sec))
ULONG reltime
(timing for frame relative to time previous frame was displayed - in jiffies (1/60 sec))
UBYTE interleave
(unused so far - indicates how may frames back this data is to modify. =0 defaults to indicate two frames back (for double buffering). =n indicates n frames back. The main intent here is to allow values of =1 for special applications where frame data would modify the immediately previous frame)
UBYTE pad0
Pad byte, not used at present.
ULONG bits
32 option bits used by options=4 and 5. At present only 6 are identified, but the rest are set =0 so they can be used to implement future ideas. These are defined for option 4 only at this point. It is recommended that all bits be set =0 for option 5 and that any bit settings used in the future (such as for XOR mode) be compatible with the option 4 bit settings. Player code should check undefined bits in options 4 and 5 to assure they are zero.
The six bits for current use are:
bit # set =0 set =1
0 short data long data
1 set XOR
2 separate info for each plane one info list for all planes
3 not RLC RLC (run length coded)
4 horizontal vertical
5 short info offsets long info offsets
UBYTE pad[16]
This is a pad for future use for future compression modes.

DLTA Chunk

This chunk is the basic data chunk used to hold delta compression data. The format of the data will be dependent upon the exact compression format selected. At present there are two basic formats for the overall structure of this chunk.

Format for methods 2 & 3

This chunk is a basic data chunk used to hold the delta compression data. The minimum size of this chunk is 32 bytes as the first 8 long-words are byte pointers into the chunk for the data for each of up to 8 bit planes. The pointer for the plane data starting immediately following these 8 pointers will have a value of 32 as the data starts in the 33-rd byte of the chunk (index value of 32 due to zero-base indexing).

The data for a given plane consists of groups of data words. In Long Delta mode, these groups consist of both short and long words - short words for offsets and numbers, and long words for the actual data. In Short Delta mode, the groups are identical except data words are also shorts so all data is short words. Each group consists of a starting word which is an offset. If the offset is positive then it indicates the increment in long or short words (whichever is appropriate) through the bit plane. In other words, if you were reconstructing the plane, you would start a pointer (to shorts or longs depending on the mode) to point to the first word of the bit plane. Then the offset would be added to it and the following data word would be placed at that position. Then the next offset would be added to the pointer and the following data word would be placed at that position. And so on... The data terminates with an offset equal to 0xFFFF.

A second interpretation is given if the offset is negative. In that case, the absolute value is the offset+2. Then the following short-word indicates the number of data words that follow. Following that is the indicated number of contiguous data words (longs or shorts depending on mode) which are to be placed in contiguous locations of the bit plane.

If there are no changed words in a given plane, then the pointer in the first 32 bytes of the chunk is =0.

Format for method 4

The DLTA chunk is modified slightly to have 16 long pointers at the start. The first 8 are as before - pointers to the start of the data for each of the bit planes (up to a theoretical max of 8 planes). The next 8 are pointers to the start of the offset/numbers data list. If there is only one list of offset/numbers for all planes, then the pointer to that list is repeated in all positions so the playback code need not even be aware of it. In fact, one could get fancy and have some bit planes share lists while others have different lists, or no lists (the problems in these schemes lie in the generation, not in the playback).

The best way to show the use of this format is in a sample playback routine.

   SetDLTAshort(bm,deltaword)
   struct BitMap *bm;
   WORD *deltaword;
   {
      int i;
      LONG *deltadata;
      WORD *ptr,*planeptr;
      register int s,size,nw;
      register WORD *data,*dest;
 
      deltadata = (LONG *)deltaword;
      nw = bm->BytesPerRow >>1;
 
      for (i=0;i<bm->Depth;i++) {
         planeptr = (WORD *)(bm->Planes[i]);
         data = deltaword + deltadata[i];
         ptr  = deltaword + deltadata[i+8];
         while (*ptr != 0xFFFF) {
            dest = planeptr + *ptr++;
            size = *ptr++;
            if (size < 0) {
               for (s=size;s<0;s++) {
                  *dest = *data;
                  dest += nw;
               }
               data++;
            }
            else {
               for (s=0;s<size;s++) {
                  *dest = *data++;
                  dest += nw;
               }
            }
         }
      }
      return(0);
   }

The above routine is for short word vertical compression with run length compression. The most efficient way to support the various options is to replicate this routine and make alterations for, say, long word or XOR. The variable nw indicates the number of words to skip to go down the vertical column. This one routine could easily handle horizontal compression by simply setting nw=1. For ultimate playback speed, the core, at least, of this routine should be coded in assembly language.

Format for method 5

In this method the same 16 pointers are used as in option 4. The first 8 are pointers to the data for up to 8 planes. The second set of 8 are not used but were retained for several reasons. First to be somewhat compatible with code for option 4 (although this has not proven to be of any benefit) and second, to allow extending the format for more bit planes (code has been written for up to 12 planes).

Compression/decompression is performed on a plane-by-plane basis. For each plane, compression can be handled by the skip.c code (provided Public Domain by Jim Kent) and decompression can be handled by unvscomp.asm (also provided Public Domain by Jim Kent).

Compression/decompression is performed on a plane-by-plane basis. The following description of the method is taken directly from Jim Kent's code with minor re-wording. Please refer to Jim's code (skip.c and unvscomp.asm) for more details:

Each column of the bit plane is compressed separately. A 320x200 bit plane would have 40 columns of 200 bytes each. Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means there's no change in this column from the last frame. The ops are of three classes, and followed by a varying amount of data depending on which class:

  1. Skip ops - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero.
  2. Uniq ops - this is a byte with the hi bit set. The hi bit is masked down and the remainder is a count of the number of bytes of data to copy literally. It's of course followed by the data to copy.
  3. Same ops - this is a 0 byte followed by a count byte, followed by a byte value to repeat count times.

Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next byte in the destination we add the number of bytes per row instead of one!

ANIM.op6

OpCode 6 Addition to ANIM IFF Format

Stereo (3D) Animations

Submitted by William J. Coldwell (08/23/91)

Revision Date: 20.8.91

Prepared by:

Cryogenic Software
13045 SouthEast Stark St
Suite 144
Portland, OR 97233-1557
Contact: William J. Coldwell
Voice: (503) 254-8147 (11a-4p PDT/PST)
Data: (503) 257-4823 (EMail to SYSOP)
Portal: Cryogenic
UUCP: uunet!m2xenix!percy!cryo!billc
Internet: billc@cryo.rain.com

Introduction

In 1989, we added support into one of our commercial products to support the Haitex X-Specs glasses. This documentation will not go into a detailed description of this product. Contact Haitex for more information concerning the hardware:

Haitex Resources, Inc.
Post Office Box 20609
Charleston, SC 29413
Voice: (803) 881-7518
Fax: (803) 881-7522
Contact: Shawn Glisson

We found that there was not a supported way to display stereo animations using the current IFF ANIM OpCode 5 specification.

Cryogenic supported OpCode 6 as an internal format in our commercial programs (see below) and provided Public Domain players. It is our intention at this time, to release this format to other developers wishing to support stereo animations using this OpCode.

When we first started this project, the current Amiga machines had a 512K of CHIP RAM maximum. This caused some memory problems with some of the higher resolution stereo animations, since the Quad Buffers were in CHIP RAM for our players. It was our intention to attempt to do some memory magic to require only two of the four bitmaps to be in CHIP RAM at one time. It was our feeling that this would have caused the animations to slow down, due to data swapping that may or may not have needed to be done. By the end of 1989, all development had stopped on OpCode 6. This left all buffers in CHIP, and the format has remained the same since then.

OpCode 6 Additions to OpCode 5

The format is exactly the same as OpCode 5 but is QUAD buffered instead of DOUBLE buffered. This allows the player to show 2 screens at one time for the X-Specs Glasses. Each picture MUST be viewed for 1/60th of a second, therefore to see a 3-D Picture the viewer can only play ANIMs at 30 frames per second. (2 pictures = 1 frame).

The IFF file is stored exactly the same except that instead of having each DLTA (delta) modify bitmap two frames back, it modifies the bitmap four frames back.

Example:

------------------------
|                      |
|   BMHD               |
|                      |
------------------------
|   DLTA  (1)          |
------------------------
|   DLTA  (2)          |
------------------------
|   DLTA  (3)          |
------------------------
|   DLTA  (4)          |
------------------------
|   DLTA  (5)          |
------------------------
|   DLTA  (6)          |
------------------------
           .
           .
           .
------------------------
|   DLTA  (x)          |
------------------------

Playing OpCode 6 ANIMs

Four bitmaps are allocated. Bitmaps 1 and 3 are the left views, and bitmaps 2 and 4 are the right.

The First bitmap is gets its image from the bitmap in the file (BMHD). The Second bitmap is a copy of the first with DLTA (1) performed on it. The Third Bitmap is a copy of the first with DLTA (2) performed on it. The Fourth Bitmap is a copy of the first with DLTA (3) performed on it.

We now have the first two 3-D Pictures:

One in bitmaps 1 and 2 and the other in bitmaps 3 and 4

DLTA (6) is used to create the third left view from bitmap 1.

DLTA (7) is used to create the third right view from bitmap 2.

DLTA (8) is used to create the forth left view from bitmap 3.

DLTA (9) is used to create the forth right view from bitmap 4.

NOTE: This technique requires 4 Loop frames at the end to perform looping.

Chunk Changes

In the ANHDChunk structure the only differences between OpCode 5 and OpCode 6 are the _Operation_ field which should be set to 6, and the _Interleave_ field which should be set to 4.

Supporting Software

  • 3-D Professional 1.0+ (Progressive Peripherals and Software)
  • View 1.7 and above (Public Domain) on a Fred Fish Disk
  • MSA: Make Stereo ANIM (internal) Available upon request.
  • PSA: Play Stereo ANIM (internal) Available upon request.

ANIM.op7

Appendix for Anim7 Formats

Anim7 (July 92) by:

Wolfgang Hofer
A-2722 Winzendorf
Wr. Neustaedterstr. 140

Anim method 7 is designed for maximum playback speed and acceptable packing rates (packing usually not as good as method 5, but more efficient than methods 1 -- 4)

Method 7 was not originally in the IFF specification but supported by the Public Domain Programs AAP/AAC.

Chunk Sequence

Method 7 Anims should use the same Chunk Sequence as methods 1..5. Alternatively the first frame may have a DLTA chunk instead of the BODY chunk.

In that case the DLTA is the difference to a 'black frame'. A player has to clear all bit planes of the first bitmap to zero, and then call his DLTA unpack routines for this frame.

     FORM ANIM
     . FORM ILBM         first frame
     . . BMHD                normal type IFF data
     . . ANHD                optional animation header chunk for timing of 1st frame.
     . . CMAP
     . . { BODY | DLTA }     full picture or difference to 'black frame'
     . FORM ILBM         frame 2
     . . ANHD                animation header chunk
     . . DLTA                delta mode data
     . . [CMAP]
     . FORM ILBM         frame 3
     . . ANHD
     . . DLTA
     . . [CMAP]
         ...

The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc. The BODY will normally be a standard run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD). If desired, an ANHD chunk can appear here to provide timing data for the first frame. If it is here, the operation field should be =0.

If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk must appear, and the operation field must be set to the according anim method.

Chunk Formats

ANHD Chunk for method 7

The ANHD chunk consists of the following data structure:

 UBYTE operation    The compression method=7 short/long Vertical Delta mode
 UBYTE mask         unused
 UWORD w,h          unused
 WORD  x,y          unused
 ULONG abstime      unused
 ULONG reltime      (timing for frame relative to time previous frame was displayed - in jiffies (1/60 sec))
 UBYTE interleave   = 0 (see ANHD description above)
 UBYTE pad0         unused
 ULONG bits         32 option bits used by method=4 and 5.
                    method 7 uses only bit #0
                    bit #          set =0               set =1
                    ===============================================
                    0              short data           long data
 UBYTE pad[16]       unused

DLTA Chunk

The DLTA Chunks of method 7 consists of

  • 8 pointers to opcode lists
  • 8 pointers to data lists
  • data lists (long/short)
  • opcode lists (bytes)

In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8 planes. The second set of 8 longwords are pointers to the corresponding data lists. If there are less than 8 Planes all unused pointers are set to zero.

Compression/decompression is performed on a plane-by-plane basis. The following description of the method is similar to Jim Kent's method 5, except that data is stored in a separated data list (long or short, depending on bit#0 of the ANHD bits) and doesn't follow immediate after the opcode.

In method 7 the bit plane is split into vertical columns. Each column of the bit plane is compressed separately. A 320x200 bitplane would have 20 columns of 200 short datas each. (or 10 columns of 200 long datas)

Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means there's no change in this column from the last frame. The ops are of three classes. The ops refer to a varying amount of data (to fetch from the corresponding data list) depending on which class:

  1. Skip ops - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero. Skip ops have no corresponding data-items in the data list.
  2. Uniq ops - this is a byte with the hi bit set. The hi bit is masked down and the remainder is a count of the number of data to copy literally from the data list to the "dest" pointer column. (Each data item to the next destination row) Data items may be long or short organized.
  3. Same ops - this is a 0 byte followed by a count byte. The count byte says how many rows of the current column are to be set to the same data-item. the data-item (long or short) is fetched from the data list.
Note
Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next address in the destination we have to add the number of bytes per row instead of 2 (or 4)!

ANIM.op8

Appendix for Anim8

Joe Porkka 10-jan-92

Anim method 8 is designed for maximum playback speed and acceptable packing rates (packing usually not as good as method 5, but more efficient than methods 1 -- 4). In addition, it is easier to convert existing Anim5 code to support Anim8 than Anim7.

Chunk Sequence

Method 8 Anims should use the same Chunk Sequence as methods 1..5. Alternatively the first frame may have a DLTA chunk instead of the BODY chunk.

In that case the DLTA is the difference to a 'black frame'. A player has to clear all bit planes of the first bitmap to zero, and then call his DLTA unpack routines for this frame. The same rules about copying the first frame into both frame buffers still applies in this case.

                  FORM ANIM
                  . FORM ILBM         first frame
                  . . BMHD                normal type IFF data
                  . . ANHD                optional animation header chunk for timing of 1st frame.
                  . . CMAP
                  . . { BODY | DLTA }     full picture or difference to 'black frame'
                  . FORM ILBM         frame 2
                  . . ANHD                animation header chunk
                  . . DLTA                delta mode data
                  . . [CMAP]
                  . FORM ILBM         frame 3
                  . . ANHD
                  . . DLTA
                  . . [CMAP]
                       ...

The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc. The BODY will normally be a standard run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD). If desired, an ANHD chunk can appear here to provide timing data for the first frame. If it is here, the operation field should be =0.

If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk must appear, and the operation field must be set to the according anim method.

Each of the frames from frame 2 on up may use an anhd->operation of 0, 5 or 8. Note that only for the first frame in the file do you copy the image data into two buffers, not every time you get an ANHD->operation==0.

Chunk Formats

ANHD Chunk for method 8

The ANHD chunk consists of the following data structure:

    UBYTE operation  The compression method=8 short/long Vertical Delta mode
    UBYTE mask         unused
    UWORD w,h          unused
    WORD  x,y          unused
    ULONG abstime      unused
    ULONG reltime     (timing for frame relative to time previous frame was displayed - in jiffies (1/60 sec))
    UBYTE interleave = 0 (see ANHD description above)
    UBYTE pad0         unused
    ULONG bits         32 option bits used by method=4 and 5.
                       method 8 uses only bit #0
                      bit #              set =0              set =1
                      =============================================
                      0              short data           long data
    UBYTE pad[16]       unused

DLTA Chunk

The DLTA Chunks of method8 consists of

  • 16 pointers same as in method 5

In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8 planes. The second set of 8 longwords are unused. If there are less than 8 Planes all unused pointers are set to zero.

Compression/decompression is performed on a plane-by-plane basis. The following description of the method is similar to Jim Kent's methode 5, except that data is either in WORDs or LONGS, depending on bit 0 of the ANHD bits.

In method 8 the bit plane is split into vertical columns. Each column of the bit plane is compressed separately. A 320x200 bit plane would have 20 columns of 200 short data each (or 10 columns of 200 long data).

Each column of the bit plane is compressed separately. A 320x200 bit plane would have 20 (WORD) or 10 (LONG)columns of 200 bytes each. Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means there's no change in this column from the last frame. The ops are of three classes, and followed by a varying amount of data depending on which class:

  1. Skip ops - this is a word or long with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.
  2. Uniq ops - this is a word or long with the hi bit set. The hi bit is masked down and the remainder is a count of the number of bytes of data to copy literally. It's of course followed by the data to copy. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.
  3. Same ops - this is a 0 word or long followed by a count word or long, followed by a word or long value to repeat count times. Note that the range of values is much larger for word and long data, 0xffff and 0xffffffff.
Note
Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next word or long in the destination we add the number of bytes per row instead of one!

There is a slight complication in the case of long data. Normally an Amiga BitMap is and even number of 16bit WORDs wide, so it is possible to have an image which is not an even number or LONGs wide. For example, an image which is 336 pixels wide is 42 bytes wide, 21 words wide, and 10.5 longs wide. In the case that the data is not an even number of longs wide, and the data is to be long compressed, then the last column of data is to be word compressed instead. So, that 336 pixel wide image would be compress as 10 long columns and 1 word column.

ANIM.brush

Dpaint Anim Brush IFF Format

From a description by the author of DPaint, Dan Silva, Electronic Arts.

The "Anim Brushes" of DPaint III are saved on disk in the IFF "ANIM" format. Basically, an ANIM Form consists of an initial ILBM which is the first frame of the animation, and any number of subsequent "ILBM"S (which aren't really ILBM's) each of which contains an ANHD animation header chunk and a DLTA chunk comprised of the encoded difference between a frame and a previous one.

To use ANIM terminology (for a description of the ANIM format, see the IFF Anim Spec, by Gary Bonham). Anim Brushes use a "type 5" encoding, which is a vertical, byte-oriented delta encoding (based on Jim Kent's RIFF). The deltas have an interleave of 1, meaning deltas are computed between adjacent frames, rather than between frames 2 apart, which is the usual ANIM custom for the purpose of fast hardware page-flipping. Also, the deltas use Exclusive Or to allow reversable play.

However, to my knowledge, all the existing Anim players in the Amiga world will only play type 5 "Anim"s which have an interleave of 0 (i.e. 2) and which use a Store operation rather than Exclusive Or, so no existing programs will read Anim Brushes anyway. The job of modifying existing Anim readers to read Anim Brushes should be simplified, however.

Here is an outline of the structure of the IFF Form output by DPaint III as an "Anim Brush". The IFF Reader should of course be flexible enough to tolerate variation in what chunks actually appear in the initial ILBM.

FORM ANIM
    . FORM ILBM         first frame
    . . BMHD        
    . . CMAP
    . . DPPS
    . . GRAB
    . . CRNG
    . . CRNG
    . . CRNG
    . . CRNG
    . . CRNG
    . . CRNG
    . . DPAN     my own little chunk.
    . . CAMG
    . . BODY
    
    . FORM ILBM         frame 2
    . . ANHD                animation header chunk
    . . DLTA                delta mode data
    
    . FORM ILBM         frame 3
    . . ANHD                animation header chunk
    . . DLTA                delta mode data
    
    . FORM ILBM         frame 4
    . . ANHD                animation header chunk
    . . DLTA                delta mode data
    
    ...
    
 . FORM ILBM         frame N
    . . ANHD                animation header chunk
    . . DLTA                delta mode data

DPAN

Here is the format of the DPAN chunk:

typedef struct {
 UWORD version;   /* current version=4 */
 UWORD nframes;   /* number of frames in the animation.*/
 ULONG flags;   /* Not used */
 } DPAnimChunk;

The version number was necessary during development. At present all I look at is "nframes".

ANHD

Here is the ANHD chunk format:

typedef struct {
 UBYTE operation;  /* =0  set directly
       =1  XOR ILBM mode,
       =2 Long Delta mode,
       =3 Short Delta mode
       =4 Generalize short/long Delta mode,
       =5 Byte Vertical Delta (riff)
       =74 (Eric Grahams compression mode)
   */
 UBYTE mask;      /* XOR ILBM only: plane mask where data is*/
 UWORD w,h;  
 WORD x,y;
 ULONG abstime;
 ULONG reltime;
 UBYTE interleave; /* 0 defaults to 2 */
 UBYTE pad0;   /* not used */
 ULONG bits;   /* meaning of bits:
     bit#    =0         =1
    0  short data      long data
    1  store         XOR
    2  separate info       one info for
      for each plane     for all planes
    3  not RLC    RLC (run length encoded)
    4  horizontal   vertical
    5  short info offsets long info offsets
   -------------------------*/
 UBYTE pad[16];
 } AnimHdr;

for Anim Brushes, I set:

animHdr.operation = 5;  /* RIFF encoding */
animHdr.interleave = 1;
animHdr.w = curAnimBr.bmob.pict.box.w; 
animHdr.h = curAnimBr.bmob.pict.box.h; 
animHdr.reltime = 1;
animHdr.abstime = 0;
animHdr.bits = 4; /* indicating XOR */

everything else is set to 0.

Note
The "bits" field was actually intended ( by the original creator of the ANIM format, Gary Bonham of SPARTA, Inc.) for use with only with compression method 4. I am using bit 2 of the bits field to indicate the Exclusive OR operation in the context of method 5, which seems like a reasonable generalization.

DLTA

For an Anim Brush with 10 frames, there will be an initial frame followed by 10 Delta's (i.e ILBMS containing ANHD and DLTA chunks). Applying the first Delta to the initial frame generates the second frame, applying the second Delta to the second frame generates the third frame, etc. Applying the last Delta thus brings back the first frame.

The DLTA chunk begins with 16 LONG plane offets, of which DPaint only uses the first 6 (at most). These plane offsets are either the offset (in bytes ) from the beginning of the DLTA chunk to the data for the corresponding plane, or Zero, if there was no change in that plane. Thus the first plane offset is either 0 or 64.

(The following description of the method is based on Gary Bonham's rewording of Jim Kent's RIFF documentation.)

Compression/decompression is performed on a plane-by-plane basis.

Each byte-column of the bit plane is compressed separately. A 320x200 bit plane would have 40 columns of 200 bytes each. In general, the bit planes are always an even number of bytes wide, so for instance a 17x20 bit plane would have 4 columns of 20 bytes each.

Each column starts with an op-count followed by a number of ops. If the op-count is zero, that's OK, it just means there's no change in this column from the last frame. The ops are of three kinds, and followed by a varying amount of data depending on which kind:

  1. SKIP - this is a byte with the hi bit clear that says how many rows to move the "dest" pointer forward, i.e. to skip. It is non-zero.
  2. DUMP - this is a byte with the hi bit set. The hi bit is masked off and the remainder is a count of the number of bytes of data to XOR directly. It is followed by the bytes to copy.
  3. RUN - this is a 0 byte followed by a count byte, followed by a byte value to repeat "count" times, XOR'ing it into the destination.
Note
Bear in mind that the data is compressed vertically rather than horizontally, so to get to the next byte in the destination you add the number of bytes per row instead of one.

The Format of DLTA chunks is as described in section 2.2.2 of the Anim Spec. The encoding for type 5 is described in section 2.2.3 of the Anim Spec.