1 /*
2  * Copyright 2004 Richard Wilson <richard.wilson@netsurf-browser.org>
3  * Copyright 2008 Sean Fox <dyntryx@gmail.com>
4  *
5  * This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/
6  * Licenced under the MIT License,
7  *                http://www.opensource.org/licenses/mit-license.php
8  */
9 
10 /**
11  * \file
12  * Interface to progressive animated GIF file decoding.
13  */
14 
15 #ifndef _LIBNSGIF_H_
16 #define _LIBNSGIF_H_
17 
18 #include <stdbool.h>
19 #include <inttypes.h>
20 
21 /* Error return values */
22 typedef enum {
23         GIF_WORKING = 1,
24         GIF_OK = 0,
25         GIF_INSUFFICIENT_FRAME_DATA = -1,
26         GIF_FRAME_DATA_ERROR = -2,
27         GIF_INSUFFICIENT_DATA = -3,
28         GIF_DATA_ERROR = -4,
29         GIF_INSUFFICIENT_MEMORY = -5,
30         GIF_FRAME_NO_DISPLAY = -6,
31         GIF_END_OF_FRAME = -7
32 } gif_result;
33 
34 /** GIF frame data */
35 typedef struct gif_frame {
36         /** whether the frame should be displayed/animated */
37         bool display;
38         /** delay (in cs) before animating the frame */
39         unsigned int frame_delay;
40 
41         /* Internal members are listed below */
42 
43         /** offset (in bytes) to the GIF frame data */
44         unsigned int frame_pointer;
45         /** whether the frame has previously been used */
46         bool virgin;
47         /** whether the frame is totally opaque */
48         bool opaque;
49         /** whether a forcable screen redraw is required */
50         bool redraw_required;
51         /** how the previous frame should be disposed; affects plotting */
52         unsigned char disposal_method;
53         /** whether we acknoledge transparency */
54         bool transparency;
55         /** the index designating a transparent pixel */
56         unsigned char transparency_index;
57         /** x co-ordinate of redraw rectangle */
58         unsigned int redraw_x;
59         /** y co-ordinate of redraw rectangle */
60         unsigned int redraw_y;
61         /** width of redraw rectangle */
62         unsigned int redraw_width;
63         /** height of redraw rectangle */
64         unsigned int redraw_height;
65 } gif_frame;
66 
67 /* API for Bitmap callbacks */
68 typedef void* (*gif_bitmap_cb_create)(int width, int height);
69 typedef void (*gif_bitmap_cb_destroy)(void *bitmap);
70 typedef unsigned char* (*gif_bitmap_cb_get_buffer)(void *bitmap);
71 typedef void (*gif_bitmap_cb_set_opaque)(void *bitmap, bool opaque);
72 typedef bool (*gif_bitmap_cb_test_opaque)(void *bitmap);
73 typedef void (*gif_bitmap_cb_modified)(void *bitmap);
74 
75 /** Bitmap callbacks function table */
76 typedef struct gif_bitmap_callback_vt {
77         /** Create a bitmap. */
78         gif_bitmap_cb_create bitmap_create;
79         /** Free a bitmap. */
80         gif_bitmap_cb_destroy bitmap_destroy;
81         /** Return a pointer to the pixel data in a bitmap. */
82         gif_bitmap_cb_get_buffer bitmap_get_buffer;
83 
84         /* Members below are optional */
85 
86         /** Sets whether a bitmap should be plotted opaque. */
87         gif_bitmap_cb_set_opaque bitmap_set_opaque;
88         /** Tests whether a bitmap has an opaque alpha channel. */
89         gif_bitmap_cb_test_opaque bitmap_test_opaque;
90         /** The bitmap image has changed, so flush any persistant cache. */
91         gif_bitmap_cb_modified bitmap_modified;
92 } gif_bitmap_callback_vt;
93 
94 /** GIF animation data */
95 typedef struct gif_animation {
96         /** LZW decode context */
97         void *lzw_ctx;
98         /** callbacks for bitmap functions */
99         gif_bitmap_callback_vt bitmap_callbacks;
100         /** pointer to GIF data */
101         unsigned char *gif_data;
102         /** width of GIF (may increase during decoding) */
103         unsigned int width;
104         /** heigth of GIF (may increase during decoding) */
105         unsigned int height;
106         /** number of frames decoded */
107         unsigned int frame_count;
108         /** number of frames partially decoded */
109         unsigned int frame_count_partial;
110         /** decoded frames */
111         gif_frame *frames;
112         /** current frame decoded to bitmap */
113         int decoded_frame;
114         /** currently decoded image; stored as bitmap from bitmap_create callback */
115         void *frame_image;
116         /** number of times to loop animation */
117         int loop_count;
118 
119         /* Internal members are listed below */
120 
121         /** current index into GIF data */
122         unsigned int buffer_position;
123         /** total number of bytes of GIF data available */
124         unsigned int buffer_size;
125         /** current number of frame holders */
126         unsigned int frame_holders;
127         /** index in the colour table for the background colour */
128         unsigned int background_index;
129         /** image aspect ratio (ignored) */
130         unsigned int aspect_ratio;
131         /** size of colour table (in entries) */
132         unsigned int colour_table_size;
133         /** whether the GIF has a global colour table */
134         bool global_colours;
135         /** global colour table */
136         unsigned int *global_colour_table;
137         /** local colour table */
138         unsigned int *local_colour_table;
139 } gif_animation;
140 
141 /**
142  * Initialises necessary gif_animation members.
143  */
144 void gif_create(gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);
145 
146 /**
147  * Initialises any workspace held by the animation and attempts to decode
148  * any information that hasn't already been decoded.
149  * If an error occurs, all previously decoded frames are retained.
150  *
151  * @return Error return value.
152  *         - GIF_FRAME_DATA_ERROR for GIF frame data error
153  *         - GIF_INSUFFICIENT_FRAME_DATA for insufficient data to process
154  *                                     any more frames
155  *         - GIF_INSUFFICIENT_MEMORY for memory error
156  *         - GIF_DATA_ERROR for GIF error
157  *         - GIF_INSUFFICIENT_DATA for insufficient data to do anything
158  *         - GIF_OK for successful decoding
159  *         - GIF_WORKING for successful decoding if more frames are expected
160  */
161 gif_result gif_initialise(gif_animation *gif, size_t size, unsigned char *data);
162 
163 /**
164  * Decodes a GIF frame.
165  *
166  * @return Error return value. If a frame does not contain any image data,
167  *		GIF_OK is returned and gif->current_error is set to
168  *		GIF_FRAME_NO_DISPLAY
169  *         - GIF_FRAME_DATA_ERROR for GIF frame data error
170  *         - GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
171  *         - GIF_DATA_ERROR for GIF error (invalid frame header)
172  *         - GIF_INSUFFICIENT_DATA for insufficient data to do anything
173  *         - GIF_INSUFFICIENT_MEMORY for insufficient memory to process
174  *         - GIF_OK for successful decoding
175  */
176 gif_result gif_decode_frame(gif_animation *gif, unsigned int frame);
177 
178 /**
179  * Releases any workspace held by a gif
180  */
181 void gif_finalise(gif_animation *gif);
182 
183 #endif
184