2018-01-21 16:51:22 (UTC-02:00)
Marcel Rodrigues <marcelgmr@gmail.com>
README: format text as justified in 72 columns.
diff --git a/README b/README index 70ae380..eb21e76 100644 --- a/README +++ b/README @@ -24,20 +24,21 @@ Documentation 0. Essential GIF concepts -GIF animations are stored in files as a series of palette-based +GIF animations are stored in files as a series of palette-based compressed frames. -In order to display the animation, a program must lay the frames on top -of a fixed-size canvas, one after the other. Each frame has a size, -position and duration. Each frame can have its own palette or use a +In order to display the animation, a program must lay the frames on top +of a fixed-size canvas, one after the other. Each frame has a size, +position and duration. Each frame can have its own palette or use a global palette defined in the beginning of the file. -In order to properly use extension hooks, it's necessary to understand +In order to properly use extension hooks, it's necessary to understand how GIF files store variable-sized data. A GIF block of variable size is -a sequence of sub-blocks. The first byte in a sub-block indicates the -number of data bytes to follow. The end of the block is indicated by an -empty sub-block: one byte of value 0x00. For instance, a data block of +a sequence of sub-blocks. The first byte in a sub-block indicates the +number of data bytes to follow. The end of the block is indicated by an +empty sub-block: one byte of value 0x00. For instance, a data block of 600 bytes is stored as 4 sub-blocks: + 255, <255 data bytes>, 255, <255 data bytes>, 90, <90 data bytes>, 0 1. Opening and closing a GIF file @@ -48,11 +49,11 @@ The function `gd_open_gif()` tries to open a GIF file for reading. If this function fails, it returns NULL. -If `gd_open_gif()` succeeds, it returns a GIF handler (`gd_GIF *`). -The GIF handler can be passed to the other gifdec functions to -decode GIF metadata and frames. +If `gd_open_gif()` succeeds, it returns a GIF handler (`gd_GIF *`). The +GIF handler can be passed to the other gifdec functions to decode GIF +metadata and frames. -To close the GIF file and free memory after it has been decoded, the +To close the GIF file and free memory after it has been decoded, the function `gd_close_gif()` must be called. void gd_close_gif(gd_GIF *gif); @@ -74,47 +75,47 @@ The function `gd_get_frame()` decodes one frame from the GIF file. This function returns 0 if there are no more frames to read. -The decoded frame is stored in `gif->frame`, which is a buffer of size +The decoded frame is stored in `gif->frame`, which is a buffer of size `gif->width * gif->height`, in bytes. Each byte value is an index to the palette at `gif->palette`. -Since GIF files often only store the rectangular region of a frame that -changed from the previous frame, this function will only update the -bytes in `gif->frame` that are in that region. For GIF files that only -use the global palette, the whole state of the canvas is stored in -`gif->frame` at all times, in the form of an indexed color image. -However, when local palettes are used, it's not enough to keep color -indices from previous frames. The color RGB values themselves need to -be stored. - -For this reason, in order to get the whole state of the canvas after a -new frame has been read, it's necessary to call the function +Since GIF files often only store the rectangular region of a frame that +changed from the previous frame, this function will only update the +bytes in `gif->frame` that are in that region. For GIF files that only +use the global palette, the whole state of the canvas is stored in +`gif->frame` at all times, in the form of an indexed color image. +However, when local palettes are used, it's not enough to keep color +indices from previous frames. The color RGB values themselves need to be +stored. + +For this reason, in order to get the whole state of the canvas after +a new frame has been read, it's necessary to call the function `gd_render_frame()`, which writes all pixels to a given buffer. void gd_render_frame(gd_GIF *gif, uint8_t *buffer); -The buffer size must be at least `gif->width * gif->height * 3`, in -bytes. The function `gd_render_frame()` writes the 24-bit RGB values of +The buffer size must be at least `gif->width * gif->height * 3`, in +bytes. The function `gd_render_frame()` writes the 24-bit RGB values of all canvas pixels in it. 4. Frame duration -GIF animations are not required to have a constant frame rate. Each -frame can have a different duration, which is stored right before the -frame in a Graphic Control Extension (GCE) block. This type of block -is read by gifdec into a `gd_GCE` struct that is a member of the GIF -handler. Specifically, the unsigned integer `gif->gce.delay` holds the -current frame duration, in hundreths of a second. That means that, for -instance, if `gif->gce.delay` is `50`, then the current frame must be +GIF animations are not required to have a constant frame rate. Each +frame can have a different duration, which is stored right before the +frame in a Graphic Control Extension (GCE) block. This type of block is +read by gifdec into a `gd_GCE` struct that is a member of the GIF +handler. Specifically, the unsigned integer `gif->gce.delay` holds the +current frame duration, in hundreths of a second. That means that, for +instance, if `gif->gce.delay` is `50`, then the current frame must be displayed for half a second. 5. Looping -Most GIF animations are supposed to loop automatically, going back to -the first frame after the last one is displayed. GIF files may contain +Most GIF animations are supposed to loop automatically, going back to +the first frame after the last one is displayed. GIF files may contain looping instruction in the form of a non-negative number. If this number -is zero, the animation must loop forever. Otherwise, this number -indicates how many times the animation must be played. When `gifdec` is +is zero, the animation must loop forever. Otherwise, this number +indicates how many times the animation must be played. When `gifdec` is decoding a GIF file, this number is stored in `gif->loop_count`. The function `gd_rewind()` must be called to go back to the start of the @@ -140,22 +141,22 @@ gd_close_gif(gif); 7. Reading streamed metadata with extension hooks -Some metadata blocks may occur any number of times in GIF files in -between frames. By default, gifdec ignore these blocks. However, it's -possible to setup callback functions to handle each type of extension +Some metadata blocks may occur any number of times in GIF files in +between frames. By default, gifdec ignore these blocks. However, it's +possible to setup callback functions to handle each type of extension block, by changing some GIF handler members. Whenever a Comment Extension block is found, `gif->comment()` is called. void (*comment)(struct gd_GIF *gif); -As defined in the GIF specification, "[t]he Comment Extension contains -textual information which is not part of the actual graphics in the GIF -Data Stream." Encoders are recommended to only include "text using the +As defined in the GIF specification, "[t]he Comment Extension contains +textual information which is not part of the actual graphics in the GIF +Data Stream." Encoders are recommended to only include "text using the 7-bit ASCII character set" in GIF comments. -The actual comment is stored as a variable-sized block and must be read -from the file (using the file descriptor gif->fd) by the callback +The actual comment is stored as a variable-sized block and must be read +from the file (using the file descriptor gif->fd) by the callback function. Here's an example, printing the comment to stdout: void @@ -178,7 +179,7 @@ function. Here's an example, printing the comment to stdout: gif->comment = comment; -Whenever a Plain Text Extension block is found, `gif->plain_text()` is +Whenever a Plain Text Extension block is found, `gif->plain_text()` is called. @@ -189,34 +190,34 @@ called. ); According to the GIF specification, "[t]he Plain Text Extension contains -textual data and the parameters necessary to render that data as a -graphic [...]". This is a rarely used extension that requires the +textual data and the parameters necessary to render that data as a +graphic [...]". This is a rarely used extension that requires the decoder to actually render text on the canvas. In order to support this, -one must read the relevant specification and implement a suitable +one must read the relevant specification and implement a suitable callback function to setup as `gif->plain_text`. -The actual plain text is stored as a variable-sized block and must be +The actual plain text is stored as a variable-sized block and must be read from the file by the callback function. -Whenever an unknown Application Extension block is found, +Whenever an unknown Application Extension block is found, `gif->application()` is called. void (*application)(struct gd_GIF *gif, char id[8], char auth[3]); -Application Extensions are used to extend GIF with extraofficial -features. Currently, gifdec only supports the so-called "Netscape -Application Extension", which is commonly used to specify looping +Application Extensions are used to extend GIF with extraofficial +features. Currently, gifdec only supports the so-called "Netscape +Application Extension", which is commonly used to specify looping behavior. Other Application Extensions may be supported via this hook. -The application data is stored as a variable-sized block and must be +The application data is stored as a variable-sized block and must be read from the file by the callback function. Example ------- -The file "example.c" is a demo GIF player based on gifdec and SDL2. It +The file "example.c" is a demo GIF player based on gifdec and SDL2. It can be tested like this: $ cc `pkg-config --cflags --libs sdl2` -o gifplay gifdec.c example.c