1 /* gif.h - Interface to the LCDF GIF library.
2    Copyright (C) 1997-2021 Eddie Kohler, ekohler@gmail.com
3    This file is part of the LCDF GIF library.
4 
5    The GIF library is free software. It is distributed under the GNU General
6    Public License, version 2; you can copy, distribute, or alter it at will,
7    as long as this notice is kept intact and this source code is made
8    available. There is no warranty, express or implied. */
9 
10 #ifndef LCDF_GIF_H /* -*- mode: c -*- */
11 #define LCDF_GIF_H
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <lcdf/inttypes.h>
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /* NOTE: You should define the types uint8_t, uint16_t and uint32_t before
20    including this file, probably by #including <inttypes.h>. */
21 
22 #define GIF_MAJOR_VERSION       2
23 #define GIF_MINOR_VERSION       0
24 #define GIF_VERSION             "2.0"
25 
26 typedef struct Gif_Stream       Gif_Stream;
27 typedef struct Gif_Image        Gif_Image;
28 typedef struct Gif_Colormap     Gif_Colormap;
29 typedef struct Gif_Comment      Gif_Comment;
30 typedef struct Gif_Extension    Gif_Extension;
31 typedef struct Gif_Record       Gif_Record;
32 
33 typedef uint16_t Gif_Code;
34 #define GIF_MAX_CODE_BITS       12
35 #define GIF_MAX_CODE            0x1000
36 #define GIF_MAX_BLOCK           255
37 
38 
39 /** GIF_STREAM **/
40 
41 struct Gif_Stream {
42     Gif_Image **images;
43     int nimages;
44     int imagescap;
45 
46     Gif_Colormap *global;
47     uint16_t background;        /* 256 means no background */
48 
49     uint16_t screen_width;
50     uint16_t screen_height;
51     long loopcount;             /* -1 means no loop count */
52 
53     Gif_Comment* end_comment;
54     Gif_Extension* end_extension_list;
55 
56     unsigned errors;
57     uint32_t user_flags;
58 
59     const char* landmark;
60     int refcount;
61 };
62 
63 Gif_Stream *    Gif_NewStream(void);
64 void            Gif_DeleteStream(Gif_Stream *);
65 
66 Gif_Stream *    Gif_CopyStreamSkeleton(Gif_Stream *);
67 Gif_Stream *    Gif_CopyStreamImages(Gif_Stream *);
68 
69 #define         Gif_ScreenWidth(gfs)            ((gfs)->screen_width)
70 #define         Gif_ScreenHeight(gfs)           ((gfs)->screen_height)
71 #define         Gif_ImageCount(gfs)             ((gfs)->nimages)
72 
73 #define         GIF_UNOPTIMIZE_SIMPLEST_DISPOSAL        1
74 #define         GIF_MAX_SCREEN_WIDTH                    65535
75 #define         GIF_MAX_SCREEN_HEIGHT                   65535
76 
77 void            Gif_CalculateScreenSize(Gif_Stream *, int force);
78 int             Gif_Unoptimize(Gif_Stream *);
79 int             Gif_FullUnoptimize(Gif_Stream *, int flags);
80 
81 
82 /** GIF_IMAGE **/
83 
84 struct Gif_Image {
85     uint8_t **img;              /* img[y][x] == image byte (x,y) */
86     uint8_t *image_data;
87 
88     uint16_t width;
89     uint16_t height;
90     uint16_t left;
91     uint16_t top;
92     uint16_t delay;
93     uint8_t disposal;
94     uint8_t interlace;
95 
96     short transparent;          /* -1 means no transparent index */
97     Gif_Colormap *local;
98 
99     char* identifier;
100     Gif_Comment* comment;
101     Gif_Extension* extension_list;
102 
103     void (*free_image_data)(void *);
104 
105     uint32_t compressed_len;
106     uint32_t compressed_errors;
107     uint8_t* compressed;
108     void (*free_compressed)(void *);
109 
110     uint32_t user_flags;
111     void* user_data;
112     void (*free_user_data)(void *);
113     int refcount;
114 
115 };
116 
117 #define         GIF_DISPOSAL_NONE               0
118 #define         GIF_DISPOSAL_ASIS               1
119 #define         GIF_DISPOSAL_BACKGROUND         2
120 #define         GIF_DISPOSAL_PREVIOUS           3
121 
122 Gif_Image *     Gif_NewImage(void);
123 void            Gif_DeleteImage(Gif_Image *gfi);
124 
125 int             Gif_AddImage(Gif_Stream *gfs, Gif_Image *gfi);
126 void            Gif_RemoveImage(Gif_Stream *gfs, int i);
127 Gif_Image *     Gif_CopyImage(Gif_Image *gfi);
128 void            Gif_MakeImageEmpty(Gif_Image* gfi);
129 
130 Gif_Image *     Gif_GetImage(Gif_Stream *gfs, int i);
131 Gif_Image *     Gif_GetNamedImage(Gif_Stream *gfs, const char *name);
132 int             Gif_ImageNumber(Gif_Stream *gfs, Gif_Image *gfi);
133 
134 #define         Gif_ImageWidth(gfi)             ((gfi)->width)
135 #define         Gif_ImageHeight(gfi)            ((gfi)->height)
136 #define         Gif_ImageDelay(gfi)             ((gfi)->delay)
137 #define         Gif_ImageUserData(gfi)          ((gfi)->userdata)
138 #define         Gif_SetImageUserData(gfi, v)    ((gfi)->userdata = v)
139 int             Gif_ImageColorBound(const Gif_Image* gfi);
140 
141 typedef         void (*Gif_ReadErrorHandler)(Gif_Stream* gfs,
142                                              Gif_Image* gfi,
143                                              int is_error,
144                                              const char* error_text);
145 
146 typedef struct {
147     int flags;
148     int loss;
149     void *padding[7];
150 } Gif_CompressInfo;
151 
152 #define         Gif_UncompressImage(gfs, gfi) Gif_FullUncompressImage((gfs),(gfi),0)
153 int             Gif_FullUncompressImage(Gif_Stream* gfs, Gif_Image* gfi,
154                                         Gif_ReadErrorHandler handler);
155 int             Gif_CompressImage(Gif_Stream *gfs, Gif_Image *gfi);
156 int             Gif_FullCompressImage(Gif_Stream *gfs, Gif_Image *gfi,
157                                       const Gif_CompressInfo *gcinfo);
158 void            Gif_ReleaseUncompressedImage(Gif_Image *gfi);
159 void            Gif_ReleaseCompressedImage(Gif_Image *gfi);
160 int             Gif_SetUncompressedImage(Gif_Image *gfi, uint8_t *data,
161                         void (*free_data)(void *), int data_interlaced);
162 int             Gif_CreateUncompressedImage(Gif_Image* gfi, int data_interlaced);
163 
164 int             Gif_ClipImage(Gif_Image *gfi, int l, int t, int w, int h);
165 
166 void            Gif_InitCompressInfo(Gif_CompressInfo *gcinfo);
167 
168 
169 /** GIF_COLORMAP **/
170 
171 typedef struct {
172     uint8_t haspixel;      /* semantics assigned by user */
173     uint8_t gfc_red;       /* red component (0-255) */
174     uint8_t gfc_green;     /* green component (0-255) */
175     uint8_t gfc_blue;      /* blue component (0-255) */
176     uint32_t pixel;        /* semantics assigned by user */
177 } Gif_Color;
178 
179 
180 struct Gif_Colormap {
181     int ncol;
182     int capacity;
183     uint32_t user_flags;
184     int refcount;
185     Gif_Color *col;
186 };
187 
188 Gif_Colormap *  Gif_NewColormap(void);
189 Gif_Colormap *  Gif_NewFullColormap(int count, int capacity);
190 void            Gif_DeleteColormap(Gif_Colormap *);
191 
192 Gif_Colormap *  Gif_CopyColormap(Gif_Colormap *);
193 
194 int             Gif_ColorEq(Gif_Color *, Gif_Color *);
195 #define         GIF_COLOREQ(c1, c2) \
196 ((c1)->gfc_red==(c2)->gfc_red && (c1)->gfc_green==(c2)->gfc_green && \
197  (c1)->gfc_blue==(c2)->gfc_blue)
198 #define         GIF_SETCOLOR(c, r, g, b) \
199 ((c)->gfc_red = (r), (c)->gfc_green = (g), (c)->gfc_blue = (b))
200 
201 int             Gif_FindColor(Gif_Colormap *, Gif_Color *);
202 int             Gif_AddColor(Gif_Colormap *, Gif_Color *, int look_from);
203 
204 
205 /** GIF_COMMENT **/
206 
207 struct Gif_Comment {
208     char **str;
209     int *len;
210     int count;
211     int cap;
212 };
213 
214 Gif_Comment *   Gif_NewComment(void);
215 void            Gif_DeleteComment(Gif_Comment *);
216 int             Gif_AddCommentTake(Gif_Comment *, char *, int);
217 int             Gif_AddComment(Gif_Comment *, const char *, int);
218 
219 
220 /** GIF_EXTENSION **/
221 
222 struct Gif_Extension {
223     int kind;                   /* negative kinds are reserved */
224     char* appname;
225     int applength;
226     uint8_t* data;
227     uint32_t length;
228     int packetized;
229 
230     Gif_Stream *stream;
231     Gif_Image *image;
232     Gif_Extension *next;
233     void (*free_data)(void *);
234 };
235 
236 
237 Gif_Extension*  Gif_NewExtension(int kind, const char* appname, int applength);
238 void            Gif_DeleteExtension(Gif_Extension* gfex);
239 Gif_Extension*  Gif_CopyExtension(Gif_Extension* gfex);
240 int             Gif_AddExtension(Gif_Stream* gfs, Gif_Image* gfi,
241                                  Gif_Extension* gfex);
242 
243 
244 /** READING AND WRITING **/
245 
246 struct Gif_Record {
247     const unsigned char *data;
248     uint32_t length;
249 };
250 
251 #define GIF_READ_COMPRESSED             1
252 #define GIF_READ_UNCOMPRESSED           2
253 #define GIF_READ_CONST_RECORD           4
254 #define GIF_READ_TRAILING_GARBAGE_OK    8
255 #define GIF_WRITE_CAREFUL_MIN_CODE_SIZE 1
256 #define GIF_WRITE_EAGER_CLEAR           2
257 #define GIF_WRITE_OPTIMIZE              4
258 #define GIF_WRITE_SHRINK                8
259 
260 void            Gif_SetErrorHandler(Gif_ReadErrorHandler handler);
261 Gif_Stream*     Gif_ReadFile(FILE* f);
262 Gif_Stream*     Gif_FullReadFile(FILE* f, int flags, const char* landmark,
263                                  Gif_ReadErrorHandler handler);
264 Gif_Stream*     Gif_ReadRecord(const Gif_Record* record);
265 Gif_Stream*     Gif_FullReadRecord(const Gif_Record* record, int flags,
266                                    const char* landmark,
267                                    Gif_ReadErrorHandler handler);
268 int             Gif_WriteFile(Gif_Stream *gfs, FILE *f);
269 int             Gif_FullWriteFile(Gif_Stream *gfs,
270                                   const Gif_CompressInfo *gcinfo, FILE *f);
271 
272 #define Gif_ReadFile(f)         Gif_FullReadFile((f),GIF_READ_UNCOMPRESSED,0,0)
273 #define Gif_ReadRecord(r)       Gif_FullReadRecord((r),GIF_READ_UNCOMPRESSED,0,0)
274 #define Gif_CompressImage(s, i) Gif_FullCompressImage((s),(i),0)
275 #define Gif_WriteFile(s, f)     Gif_FullWriteFile((s),0,(f))
276 
277 typedef struct Gif_Writer Gif_Writer;
278 Gif_Writer*     Gif_IncrementalWriteFileInit(Gif_Stream* gfs, const Gif_CompressInfo* gcinfo, FILE *f);
279 int             Gif_IncrementalWriteImage(Gif_Writer* grr, Gif_Stream* gfs, Gif_Image* gfi);
280 int             Gif_IncrementalWriteComplete(Gif_Writer* grr, Gif_Stream* gfs);
281 
282 
283 /** HOOKS AND MISCELLANEOUS **/
284 
285 int             Gif_InterlaceLine(int y, int height);
286 char *          Gif_CopyString(const char *);
287 
288 #define GIF_T_STREAM                    (0)
289 #define GIF_T_IMAGE                     (1)
290 #define GIF_T_COLORMAP                  (2)
291 typedef void    (*Gif_DeletionHookFunc)(int, void *, void *);
292 int             Gif_AddDeletionHook(int, Gif_DeletionHookFunc, void *);
293 void            Gif_RemoveDeletionHook(int, Gif_DeletionHookFunc, void *);
294 
295 #ifdef GIF_DEBUGGING
296 #define         GIF_DEBUG(x)                    Gif_Debug x
297 void            Gif_Debug(char *x, ...);
298 #else
299 #define         GIF_DEBUG(x)
300 #endif
301 
302 void*           Gif_Realloc(void* p, size_t s, size_t n,
303                             const char* file, int line);
304 void            Gif_Free(void* p);
305 #if !GIF_ALLOCATOR_DEFINED
306 # define        Gif_Free        free
307 #endif
308 
309 #ifndef Gif_New
310 # define Gif_New(t)             ((t*) Gif_Realloc(0, sizeof(t), 1, __FILE__, __LINE__))
311 # define Gif_NewArray(t, n)     ((t*) Gif_Realloc(0, sizeof(t), (n), __FILE__, __LINE__))
312 # define Gif_ReArray(p, t, n)   ((p)=(t*) Gif_Realloc((void*) (p), sizeof(t), (n), __FILE__, __LINE__))
313 # define Gif_Delete(p)          Gif_Free((void*) (p))
314 # define Gif_DeleteArray(p)     Gif_Free((void*) (p))
315 #endif
316 
317 #ifdef __cplusplus
318 }
319 #endif
320 #endif
321