Here's some info on the delay property. It's in one of the extensions (graphic
control extension). You should also pay attention to the Netscape loop extension,
which indicates whether and how the animation should loop.
First, the GIF89a spec:
23. Graphic Control Extension.
a. Description. The Graphic Control Extension contains parameters used
when processing a graphic rendering block. The scope of this extension is
the first graphic rendering block to follow. The extension contains only
one data sub-block.
This block is OPTIONAL; at most one Graphic Control Extension may precede
a graphic rendering block. This is the only limit to the number of
Graphic Control Extensions that may be contained in a Data Stream.
b. Required Version. 89a.
c. Syntax.
7 6 5 4 3 2 1 0 Field Name Type
+---------------+
0 | | Extension Introducer Byte
+---------------+
1 | | Graphic Control Label Byte
+---------------+
+---------------+
0 | | Block Size Byte
+---------------+
1 | | | | | <Packed Fields> See below
+---------------+
2 | | Delay Time Unsigned
+- -+
3 | |
+---------------+
4 | | Transparent Color Index Byte
+---------------+
+---------------+
0 | | Block Terminator Byte
+---------------+
<Packed Fields> = Reserved 3 Bits
Disposal Method 3 Bits
User Input Flag 1 Bit
Transparent Color Flag 1 Bit
i) Extension Introducer - Identifies the beginning of an extension
16
block. This field contains the fixed value 0x21.
ii) Graphic Control Label - Identifies the current block as a
Graphic Control Extension. This field contains the fixed value
0xF9.
iii) Block Size - Number of bytes in the block, after the Block
Size field and up to but not including the Block Terminator. This
field contains the fixed value 4.
iv) Disposal Method - Indicates the way in which the graphic is to
be treated after being displayed.
Values : 0 - No disposal specified. The decoder is
not required to take any action.
1 - Do not dispose. The graphic is to be left
in place.
2 - Restore to background color. The area used by the
graphic must be restored to the background color.
3 - Restore to previous. The decoder is required to
restore the area overwritten by the graphic with
what was there prior to rendering the graphic.
4-7 - To be defined.
v) User Input Flag - Indicates whether or not user input is
expected before continuing. If the flag is set, processing will
continue when user input is entered. The nature of the User input
is determined by the application (Carriage Return, Mouse Button
Click, etc.).
Values : 0 - User input is not expected.
1 - User input is expected.
When a Delay Time is used and the User Input Flag is set,
processing will continue when user input is received or when the
delay time expires, whichever occurs first.
vi) Transparency Flag - Indicates whether a transparency index is
given in the Transparent Index field. (This field is the least
significant bit of the byte.)
Values : 0 - Transparent Index is not given.
1 - Transparent Index is given.
vii) Delay Time - If not 0, this field specifies the number of
hundredths (1/100) of a second to wait before continuing with the
processing of the Data Stream. The clock starts ticking immediately
after the graphic is rendered. This field may be used in
conjunction with the User Input Flag field.
viii) Transparency Index - The Transparency Index is such that when
encountered, the corresponding pixel of the display device is not
modified and processing goes on to the next pixel. The index is
present if and only if the Transparency Flag is set to 1.
ix) Block Terminator - This zero-length data block marks the end of
17
the Graphic Control Extension.
d. Extensions and Scope. The scope of this Extension is the graphic
rendering block that follows it; it is possible for other extensions to
be present between this block and its target. This block can modify the
Image Descriptor Block and the Plain Text Extension.
e. Recommendations.
i) Disposal Method - The mode Restore To Previous is intended to be
used in small sections of the graphic; the use of this mode imposes
severe demands on the decoder to store the section of the graphic
that needs to be saved. For this reason, this mode should be used
sparingly. This mode is not intended to save an entire graphic or
large areas of a graphic; when this is the case, the encoder should
make every attempt to make the sections of the graphic to be
restored be separate graphics in the data stream. In the case where
a decoder is not capable of saving an area of a graphic marked as
Restore To Previous, it is recommended that a decoder restore to
the background color.
ii) User Input Flag - When the flag is set, indicating that user
input is expected, the decoder may sound the bell (0x07) to alert
the user that input is being expected. In the absence of a
specified Delay Time, the decoder should wait for user input
indefinitely. It is recommended that the encoder not set the User
Input Flag without a Delay Time specified.
Second, some code from a program called gifsicle:
/* extension byte table:
0x01 plain text extension
0xCE name*
0xF9 graphic control extension
0xFE comment extension
0xFF application extension
*/
static void
write_graphic_control_extension(Gif_Image *gfi, Gif_Writer *grr)
{
byte packed = 0;
gifputbyte('!', grr);
gifputbyte(0xF9, grr);
gifputbyte(4, grr);
if (gfi->transparent >= 0) packed |= 0x01;
packed |= (gfi->disposal & 0x07) << 2;
gifputbyte(packed, grr);
gifputunsigned(gfi->delay, grr);
gifputbyte((byte)gfi->transparent, grr);
gifputbyte(0, grr);
}
static void
blast_data(byte *data, int len, Gif_Writer *grr)
{
while (len > 0) {
int s = len > 255 ? 255 : len;
gifputbyte(s, grr);
gifputblock(data, s, grr);
data += s;
len -= s;
}
gifputbyte(0, grr);
}
static void
write_name_extension(char *id, Gif_Writer *grr)
{
gifputbyte('!', grr);
gifputbyte(0xCE, grr);
blast_data((byte *)id, strlen(id), grr);
}
static void
write_comment_extensions(Gif_Comment *gfcom, Gif_Writer *grr)
{
int i;
for (i = 0; i < gfcom->count; i++) {
gifputbyte('!', grr);
gifputbyte(0xFE, grr);
blast_data((byte *)gfcom->str[i], gfcom->len[i], grr);
}
}
static void
write_netscape_loop_extension(u_int16_t value, Gif_Writer *grr)
{
gifputblock((byte *)"!\xFF\x0BNETSCAPE2.0\x03\x01", 16, grr);
gifputunsigned(value, grr);
gifputbyte(0, grr);
}
Third, some docs on the Netscape loop extension:
Netscape Navigator has an Application Extension Block that tells Navigator to loop
the entire GIF file. The Netscape block
MUST APPEAR IMMEDIATELY AFTER THE GLOBAL COLOR TABLE OF THE LOGICAL SCREEN
DESCRIPTOR. Only Navigator 2.0 Beta4 or better will recognize this Extension
block. The block is 19 bytes long composed
of: (note: hexadecimal equivalent supplied for programmers)
byte 1 : 33 (hex 0x21) GIF Extension code
byte 2 : 255 (hex 0xFF) Application Extension Label
byte 3 : 11 (hex (0x0B) Length of Application Block
(eleven bytes of data to follow)
bytes 4 to 11 : "NETSCAPE"
bytes 12 to 14 : "2.0"
byte 15 : 3 (hex 0x03) Length of Data Sub-Block
(three bytes of data to follow)
byte 16 : 1 (hex 0x01)
bytes 17 to 18 : 0 to 65535, an unsigned integer in
lo-hi byte format. This indicate the
number of iterations the loop should
be executed.
bytes 19 : 0 (hex 0x00) a Data Sub-block Terminator.
Andy Piper wrote:
At 10:39 PM 10/6/99 -0700, Ben Wing wrote:
>Congrats! Looks good. But there are some problems. In particular, you
don't
>handle multiple animated gifs properly. (In fact, there will be a timeout
leak
>in such a case!) You need to have each separate animated gif have its own
>timeout, which you store as a field in the image instance, and the timeout's
>argument should be the image instance, not a device. This allows for
animated
Yes I know. I will fix.
>gifs with different time delays (is this not a property of the gif itself?
You
>hardcode it at 100ms) and would also allow each gif to be stopped
independently
It is but I have no idea what property.
>of the others. You also really need to implement this stop ability, or people
>will go crazy. You should do this using a weak list or hashtable of all the
>animated gifs, which you map over. You might also think about providing a
lisp
>interface to retrieve this list, and possibly other similar lists of extant
>image instances. (Somebody, probably whose last name is Perry, is going to
want
>this.)
Ok, I'll look into it.
>Also, why do you have a separate IMAGE_WIDGET_MASK and IMAGE_LAYOUT_MASK?
>These are really one and the same.
I don't think so - the image data is different.
andy
--------------------------------------------------------------
Dr Andy Piper
Senior Consultant Architect, BEA Systems Ltd