summaryrefslogtreecommitdiff
path: root/include/libnsgif.h
blob: fd92a0a04a445bd8f1d7bfad0bd274a59826669f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
 * Copyright 2004 Richard Wilson <richard.wilson@netsurf-browser.org>
 * Copyright 2008 Sean Fox <dyntryx@gmail.com>
 *
 * This file is part of NetSurf's libnsgif, http://www.netsurf-browser.org/
 * Licenced under the MIT License,
 *                http://www.opensource.org/licenses/mit-license.php
 */

/**
 * \file
 * Interface to progressive animated GIF file decoding.
 */

#ifndef _LIBNSGIF_H_
#define _LIBNSGIF_H_

#include <stdbool.h>
#include <inttypes.h>

/* Error return values */
typedef enum {
        GIF_WORKING = 1,
        GIF_OK = 0,
        GIF_INSUFFICIENT_FRAME_DATA = -1,
        GIF_FRAME_DATA_ERROR = -2,
        GIF_INSUFFICIENT_DATA = -3,
        GIF_DATA_ERROR = -4,
        GIF_INSUFFICIENT_MEMORY = -5,
        GIF_FRAME_NO_DISPLAY = -6,
        GIF_END_OF_FRAME = -7
} gif_result;

/** GIF frame data */
typedef struct gif_frame {
        /** whether the frame should be displayed/animated */
        bool display;
        /** delay (in cs) before animating the frame */
        unsigned int frame_delay;

        /* Internal members are listed below */

        /** offset (in bytes) to the GIF frame data */
        unsigned int frame_pointer;
        /** whether the frame has previously been used */
        bool virgin;
        /** whether the frame is totally opaque */
        bool opaque;
        /** whether a forcable screen redraw is required */
        bool redraw_required;
        /** how the previous frame should be disposed; affects plotting */
        unsigned char disposal_method;
        /** whether we acknoledge transparency */
        bool transparency;
        /** the index designating a transparent pixel */
        unsigned char transparency_index;
        /** x co-ordinate of redraw rectangle */
        unsigned int redraw_x;
        /** y co-ordinate of redraw rectangle */
        unsigned int redraw_y;
        /** width of redraw rectangle */
        unsigned int redraw_width;
        /** height of redraw rectangle */
        unsigned int redraw_height;
} gif_frame;

/* API for Bitmap callbacks */
typedef void* (*gif_bitmap_cb_create)(int width, int height);
typedef void (*gif_bitmap_cb_destroy)(void *bitmap);
typedef unsigned char* (*gif_bitmap_cb_get_buffer)(void *bitmap);
typedef void (*gif_bitmap_cb_set_opaque)(void *bitmap, bool opaque);
typedef bool (*gif_bitmap_cb_test_opaque)(void *bitmap);
typedef void (*gif_bitmap_cb_modified)(void *bitmap);

/** Bitmap callbacks function table */
typedef struct gif_bitmap_callback_vt {
        /** Create a bitmap. */
        gif_bitmap_cb_create bitmap_create;
        /** Free a bitmap. */
        gif_bitmap_cb_destroy bitmap_destroy;
        /** Return a pointer to the pixel data in a bitmap. */
        gif_bitmap_cb_get_buffer bitmap_get_buffer;

        /* Members below are optional */

        /** Sets whether a bitmap should be plotted opaque. */
        gif_bitmap_cb_set_opaque bitmap_set_opaque;
        /** Tests whether a bitmap has an opaque alpha channel. */
        gif_bitmap_cb_test_opaque bitmap_test_opaque;
        /** The bitmap image has changed, so flush any persistant cache. */
        gif_bitmap_cb_modified bitmap_modified;
} gif_bitmap_callback_vt;

/** GIF animation data */
typedef struct gif_animation {
        /** callbacks for bitmap functions */
        gif_bitmap_callback_vt bitmap_callbacks;
        /** pointer to GIF data */
        unsigned char *gif_data;
        /** width of GIF (may increase during decoding) */
        unsigned int width;
        /** heigth of GIF (may increase during decoding) */
        unsigned int height;
        /** number of frames decoded */
        unsigned int frame_count;
        /** number of frames partially decoded */
        unsigned int frame_count_partial;
        /** decoded frames */
        gif_frame *frames;
        /** current frame decoded to bitmap */
        int decoded_frame;
        /** currently decoded image; stored as bitmap from bitmap_create callback */
        void *frame_image;
        /** number of times to loop animation */
        int loop_count;

        /* Internal members are listed below */

        /** current index into GIF data */
        unsigned int buffer_position;
        /** total number of bytes of GIF data available */
        unsigned int buffer_size;
        /** current number of frame holders */
        unsigned int frame_holders;
        /** index in the colour table for the background colour */
        unsigned int background_index;
        /** image aspect ratio (ignored) */
        unsigned int aspect_ratio;
        /** size of colour table (in entries) */
        unsigned int colour_table_size;
        /** whether the GIF has a global colour table */
        bool global_colours;
        /** global colour table */
        unsigned int *global_colour_table;
        /** local colour table */
        unsigned int *local_colour_table;
} gif_animation;

/**
 * Initialises necessary gif_animation members.
 */
void gif_create(gif_animation *gif, gif_bitmap_callback_vt *bitmap_callbacks);

/**
 * Initialises any workspace held by the animation and attempts to decode
 * any information that hasn't already been decoded.
 * If an error occurs, all previously decoded frames are retained.
 *
 * @return Error return value.
 *         - GIF_FRAME_DATA_ERROR for GIF frame data error
 *         - GIF_INSUFFICIENT_FRAME_DATA for insufficient data to process
 *                                     any more frames
 *         - GIF_INSUFFICIENT_MEMORY for memory error
 *         - GIF_DATA_ERROR for GIF error
 *         - GIF_INSUFFICIENT_DATA for insufficient data to do anything
 *         - GIF_OK for successful decoding
 *         - GIF_WORKING for successful decoding if more frames are expected
 */
gif_result gif_initialise(gif_animation *gif, size_t size, unsigned char *data);

/**
 * Decodes a GIF frame.
 *
 * @return Error return value. If a frame does not contain any image data,
 *		GIF_OK is returned and gif->current_error is set to
 *		GIF_FRAME_NO_DISPLAY
 *         - GIF_FRAME_DATA_ERROR for GIF frame data error
 *         - GIF_INSUFFICIENT_FRAME_DATA for insufficient data to complete the frame
 *         - GIF_DATA_ERROR for GIF error (invalid frame header)
 *         - GIF_INSUFFICIENT_DATA for insufficient data to do anything
 *         - GIF_INSUFFICIENT_MEMORY for insufficient memory to process
 *         - GIF_OK for successful decoding
 */
gif_result gif_decode_frame(gif_animation *gif, unsigned int frame);

/**
 * Releases any workspace held by a gif
 */
void gif_finalise(gif_animation *gif);

#endif