summaryrefslogtreecommitdiff
path: root/include/libnsgif.h
blob: 114addfd969de226274f1a54034ed5ae1a228520 (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
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
 * Copyright 2004 Richard Wilson <richard.wilson@netsurf-browser.org>
 * Copyright 2008 Sean Fox <dyntryx@gmail.com>
 * Copyright 2013-2021 Michael Drake <tlsa@netsurf-browser.org>
 *
 * 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 NSNSGIF_H
#define NSNSGIF_H

#include <stdint.h>
#include <stdbool.h>

/* Error return values */
typedef enum {
	NSGIF_WORKING = 1,
	NSGIF_OK = 0,
	NSGIF_INSUFFICIENT_DATA = -1,
	NSGIF_INSUFFICIENT_FRAME_DATA = NSGIF_INSUFFICIENT_DATA,
	NSGIF_FRAME_DATA_ERROR = -2,
	NSGIF_DATA_ERROR = -4,
	NSGIF_INSUFFICIENT_MEMORY = -5,
	NSGIF_FRAME_NO_DISPLAY = -6,
	NSGIF_END_OF_FRAME = -7
} nsgif_result;

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

	/* Internal members are listed below */

	/** offset (in bytes) to the GIF frame data */
	uint32_t frame_pointer;
	/** whether the frame has previously been decoded. */
	bool decoded;
	/** whether the frame is totally opaque */
	bool opaque;
	/** whether a full image redraw is required */
	bool redraw_required;
	/** how the previous frame should be disposed; affects plotting */
	uint8_t disposal_method;
	/** whether we acknowledge transparency */
	bool transparency;
	/** the index designating a transparent pixel */
	uint32_t transparency_index;
	/** x co-ordinate of redraw rectangle */
	uint32_t redraw_x;
	/** y co-ordinate of redraw rectangle */
	uint32_t redraw_y;
	/** width of redraw rectangle */
	uint32_t redraw_width;
	/** height of redraw rectangle */
	uint32_t redraw_height;
	/* Frame flags */
	uint32_t flags;
} nsgif_frame;

/* API for Bitmap callbacks */
typedef void* (*nsgif_bitmap_cb_create)(int width, int height);
typedef void (*nsgif_bitmap_cb_destroy)(void *bitmap);
typedef uint8_t* (*nsgif_bitmap_cb_get_buffer)(void *bitmap);
typedef void (*nsgif_bitmap_cb_set_opaque)(void *bitmap, bool opaque);
typedef bool (*nsgif_bitmap_cb_test_opaque)(void *bitmap);
typedef void (*nsgif_bitmap_cb_modified)(void *bitmap);

/** Bitmap callbacks function table */
typedef struct nsgif_bitmap_cb_vt {
	/** Create a bitmap. */
	nsgif_bitmap_cb_create create;
	/** Free a bitmap. */
	nsgif_bitmap_cb_destroy destroy;
	/** Return a pointer to the pixel data in a bitmap. */
	nsgif_bitmap_cb_get_buffer get_buffer;

	/* Members below are optional */

	/** Sets whether a bitmap should be plotted opaque. */
	nsgif_bitmap_cb_set_opaque set_opaque;
	/** Tests whether a bitmap has an opaque alpha channel. */
	nsgif_bitmap_cb_test_opaque test_opaque;
	/** The bitmap image has changed, so flush any persistent cache. */
	nsgif_bitmap_cb_modified modified;
} nsgif_bitmap_cb_vt;

/** GIF animation data */
typedef struct nsgif_animation {
	/** LZW decode context */
	void *lzw_ctx;
	/** callbacks for bitmap functions */
	nsgif_bitmap_cb_vt bitmap;
	/** pointer to GIF data */
	const uint8_t *nsgif_data;
	/** width of GIF (may increase during decoding) */
	uint32_t width;
	/** height of GIF (may increase during decoding) */
	uint32_t height;
	/** number of frames decoded */
	uint32_t frame_count;
	/** number of frames partially decoded */
	uint32_t frame_count_partial;
	/** decoded frames */
	nsgif_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 */
	uint32_t buffer_position;
	/** total number of bytes of GIF data available */
	uint32_t buffer_size;
	/** current number of frame holders */
	uint32_t frame_holders;
	/** background index */
	uint32_t bg_index;
	/** background colour */
	uint32_t bg_colour;
	/** image aspect ratio (ignored) */
	uint32_t aspect_ratio;
	/** size of colour table (in entries) */
	uint32_t colour_table_size;
	/** whether the GIF has a global colour table */
	bool global_colours;
	/** global colour table */
	uint32_t *global_colour_table;
	/** local colour table */
	uint32_t *local_colour_table;
	/** current colour table */
	uint32_t *colour_table;

	/** previous frame for NSGIF_FRAME_RESTORE */
	void *prev_frame;
	/** previous frame index */
	int prev_index;
	/** previous frame width */
	unsigned prev_width;
	/** previous frame height */
	unsigned prev_height;
} nsgif_animation;

/**
 * Initialises necessary nsgif_animation members.
 */
void nsgif_create(nsgif_animation *gif, nsgif_bitmap_cb_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.
 *         - NSGIF_FRAME_DATA_ERROR for GIF frame data error
 *         - NSGIF_INSUFFICIENT_DATA reached unexpected end of source data
 *         - NSGIF_INSUFFICIENT_MEMORY for memory error
 *         - NSGIF_DATA_ERROR for GIF error
 *         - NSGIF_OK for successful decoding
 *         - NSGIF_WORKING for successful decoding if more frames are expected
 */
nsgif_result nsgif_initialise(nsgif_animation *gif, size_t size, const uint8_t *data);

/**
 * Decodes a GIF frame.
 *
 * \return Error return value.
 *         - NSGIF_FRAME_DATA_ERROR for GIF frame data error
 *         - NSGIF_DATA_ERROR for GIF error (invalid frame header)
 *         - NSGIF_INSUFFICIENT_DATA reached unexpected end of source data
 *         - NSGIF_INSUFFICIENT_MEMORY for insufficient memory to process
 *         - NSGIF_OK for successful decoding
 */
nsgif_result nsgif_decode_frame(nsgif_animation *gif, uint32_t frame);

/**
 * Releases any workspace held by a gif
 */
void nsgif_finalise(nsgif_animation *gif);

#endif