comparison src/gifalloc.c @ 0:376386a54a3c r19-14

Import from CVS: tag r19-14
author cvs
date Mon, 13 Aug 2007 08:45:50 +0200
parents
children 43dd3413c7c7
comparison
equal deleted inserted replaced
-1:000000000000 0:376386a54a3c
1 /* Synched up with: Not in FSF. */
2
3 /*****************************************************************************
4 * "Gif-Lib" - Yet another gif library. *
5 * *
6 * Written by: Gershon Elber Ver 0.1, Jun. 1989 *
7 * Extensively hacked by: Eric S. Raymond Ver 1.?, Sep 1992 *
8 ******************************************************************************
9 * GIF construction tools *
10 ******************************************************************************
11 * History: *
12 * 15 Sep 92 - Version 1.0 by Eric Raymond. *
13 *****************************************************************************/
14 #include <stdio.h>
15 #include <string.h>
16 #include <stdlib.h>
17
18 #ifdef emacs
19 #include <config.h>
20
21 void *xmalloc (unsigned int size);
22 void *xrealloc (void *ptr, unsigned int size);
23 #ifdef ERROR_CHECK_MALLOC
24 void *xfree_1 (void *);
25 #define xfree xfree_1
26 #else
27 void *xfree (void *);
28 #endif
29 #endif
30
31 #include "gif_lib.h"
32
33 #ifndef MAX
34 #define MAX(x, y) (((x) > (y)) ? (x) : (y))
35 #endif
36
37 /******************************************************************************
38 * Miscellaneous utility functions *
39 ******************************************************************************/
40
41 int BitSize(int n)
42 /* return smallest bitfield size n will fit in */
43 {
44 register i;
45
46 for (i = 1; i <= 8; i++)
47 if ((1 << i) >= n)
48 break;
49 return(i);
50 }
51
52
53 /******************************************************************************
54 * Color map object functions *
55 ******************************************************************************/
56
57 ColorMapObject *MakeMapObject(int ColorCount, GifColorType *ColorMap)
58 /*
59 * Allocate a color map of given size; initialize with contents of
60 * ColorMap if that pointer is non-NULL.
61 */
62 {
63 ColorMapObject *Object;
64
65 if (ColorCount != (1 << BitSize(ColorCount)))
66 return((ColorMapObject *)NULL);
67
68 Object = (ColorMapObject *)xmalloc(sizeof(ColorMapObject));
69 if (Object == (ColorMapObject *)NULL)
70 return((ColorMapObject *)NULL);
71
72 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
73 if (Object->Colors == (GifColorType *)NULL)
74 return((ColorMapObject *)NULL);
75
76 Object->ColorCount = ColorCount;
77 Object->BitsPerPixel = BitSize(ColorCount);
78
79 if (ColorMap)
80 memcpy((char *)Object->Colors,
81 (char *)ColorMap, ColorCount * sizeof(GifColorType));
82
83 return(Object);
84 }
85
86 void FreeMapObject(ColorMapObject *Object)
87 /*
88 * Free a color map object
89 */
90 {
91 xfree(Object->Colors);
92 xfree(Object);
93 }
94
95 #ifdef DEBUG
96 void DumpColorMap(ColorMapObject *Object, FILE *fp)
97 {
98 if (Object)
99 {
100 int i, j, Len = Object->ColorCount;
101
102 for (i = 0; i < Len; i+=4) {
103 for (j = 0; j < 4 && j < Len; j++) {
104 fprintf(fp,
105 "%3d: %02x %02x %02x ", i + j,
106 Object->Colors[i + j].Red,
107 Object->Colors[i + j].Green,
108 Object->Colors[i + j].Blue);
109 }
110 fprintf(fp, "\n");
111 }
112 }
113 }
114 #endif /* DEBUG */
115
116 ColorMapObject *UnionColorMap(
117 ColorMapObject *ColorIn1,
118 ColorMapObject *ColorIn2,
119 GifPixelType ColorTransIn2[])
120 /*
121 * Compute the union of two given color maps and return it. If result can't
122 * fit into 256 colors, NULL is returned, the allocated union otherwise.
123 * ColorIn1 is copied as it to ColorUnion, while colors from ColorIn2 are
124 * copied iff they didn't exist before. ColorTransIn2 maps the old
125 * ColorIn2 into ColorUnion color map table.
126 */
127 {
128 int i, j, CrntSlot, RoundUpTo, NewBitSize;
129 ColorMapObject *ColorUnion;
130
131 /*
132 * Allocate table which will hold the result for sure.
133 */
134 ColorUnion
135 = MakeMapObject(MAX(ColorIn1->ColorCount,ColorIn2->ColorCount)*2,NULL);
136
137 if (ColorUnion == NULL)
138 return(NULL);
139
140 /* Copy ColorIn1 to ColorUnionSize; */
141 for (i = 0; i < ColorIn1->ColorCount; i++)
142 ColorUnion->Colors[i] = ColorIn1->Colors[i];
143 CrntSlot = ColorIn1->ColorCount;
144
145 /*
146 * Potentially obnoxious hack:
147 *
148 * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
149 * of table 1. This is very useful if your display is limited to
150 * 16 colors.
151 */
152 while (ColorIn1->Colors[CrntSlot-1].Red == 0
153 && ColorIn1->Colors[CrntSlot-1].Green == 0
154 && ColorIn1->Colors[CrntSlot-1].Red == 0)
155 CrntSlot--;
156
157 /* Copy ColorIn2 to ColorUnionSize (use old colors if they exist): */
158 for (i = 0; i < ColorIn2->ColorCount && CrntSlot<=256; i++)
159 {
160 /* Let's see if this color already exists: */
161 for (j = 0; j < ColorIn1->ColorCount; j++)
162 if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i], sizeof(GifColorType)) == 0)
163 break;
164
165 if (j < ColorIn1->ColorCount)
166 ColorTransIn2[i] = j; /* color exists in Color1 */
167 else
168 {
169 /* Color is new - copy it to a new slot: */
170 ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
171 ColorTransIn2[i] = CrntSlot++;
172 }
173 }
174
175 if (CrntSlot > 256)
176 {
177 FreeMapObject(ColorUnion);
178 return((ColorMapObject *)NULL);
179 }
180
181 NewBitSize = BitSize(CrntSlot);
182 RoundUpTo = (1 << NewBitSize);
183
184 if (RoundUpTo != ColorUnion->ColorCount)
185 {
186 register GifColorType *Map = ColorUnion->Colors;
187
188 /*
189 * Zero out slots up to next power of 2.
190 * We know these slots exist because of the way ColorUnion's
191 * start dimension was computed.
192 */
193 for (j = CrntSlot; j < RoundUpTo; j++)
194 Map[j].Red = Map[j].Green = Map[j].Blue = 0;
195
196 /* perhaps we can shrink the map? */
197 if (RoundUpTo < ColorUnion->ColorCount)
198 ColorUnion->Colors
199 = (GifColorType *)xrealloc(Map, sizeof(GifColorType)*RoundUpTo);
200 }
201
202 ColorUnion->ColorCount = RoundUpTo;
203 ColorUnion->BitsPerPixel = NewBitSize;
204
205 return(ColorUnion);
206 }
207
208 void ApplyTranslation(SavedImage *Image, GifPixelType Translation[])
209 /*
210 * Apply a given color translation to the raster bits of an image
211 */
212 {
213 register int i;
214 register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
215
216 for (i = 0; i < RasterSize; i++)
217 Image->RasterBits[i] = Translation[Image->RasterBits[i]];
218 }
219
220 /******************************************************************************
221 * Extension record functions *
222 ******************************************************************************/
223
224 void MakeExtension(SavedImage *New, int Function)
225 {
226 New->Function = Function;
227 /*
228 * Someday we might have to deal with multiple extensions.
229 */
230 }
231
232 int AddExtensionBlock(SavedImage *New, int Len, char ExtData[])
233 {
234 ExtensionBlock *ep;
235
236 if (New->ExtensionBlocks == NULL)
237 New->ExtensionBlocks = (ExtensionBlock *)xmalloc(sizeof(ExtensionBlock));
238 else
239 New->ExtensionBlocks =
240 (ExtensionBlock *)xrealloc(New->ExtensionBlocks,
241 sizeof(ExtensionBlock) * (New->ExtensionBlockCount + 1));
242
243 if (New->ExtensionBlocks == NULL)
244 return(GIF_ERROR);
245
246 ep = &New->ExtensionBlocks[New->ExtensionBlockCount++];
247
248 if ((ep->Bytes = (GifByteType *)xmalloc(ep->ByteCount = Len)) == NULL)
249 return(GIF_ERROR);
250
251 if (ExtData)
252 memcpy(ep->Bytes, ExtData, Len);
253
254 return(GIF_OK);
255 }
256
257 void FreeExtension(SavedImage *Image)
258 {
259 ExtensionBlock *ep;
260
261 for (ep = Image->ExtensionBlocks;
262 ep < Image->ExtensionBlocks + Image->ExtensionBlockCount;
263 ep++)
264 (void) xfree((char *)ep->Bytes);
265 xfree((char *)Image->ExtensionBlocks);
266 Image->ExtensionBlocks = NULL;
267 }
268
269 /******************************************************************************
270 * Image block allocation functions *
271 ******************************************************************************/
272 SavedImage *MakeSavedImage(GifFileType *GifFile, SavedImage *CopyFrom)
273 /*
274 * Append an image block to the SavedImages array
275 */
276 {
277 SavedImage *sp;
278
279 if (GifFile->SavedImages == NULL)
280 GifFile->SavedImages = (SavedImage *)xmalloc(sizeof(SavedImage));
281 else
282 GifFile->SavedImages = (SavedImage *)xrealloc(GifFile->SavedImages,
283 sizeof(SavedImage) * (GifFile->ImageCount+1));
284
285 if (GifFile->SavedImages == NULL)
286 return((SavedImage *)NULL);
287 else
288 {
289 sp = &GifFile->SavedImages[GifFile->ImageCount++];
290 memset((char *)sp, '\0', sizeof(SavedImage));
291
292 if (CopyFrom)
293 {
294 memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
295
296 /*
297 * Make our own allocated copies of the heap fields in the
298 * copied record. This guards against potential aliasing
299 * problems.
300 */
301
302 /* first, the local color map */
303 if (sp->ImageDesc.ColorMap)
304 sp->ImageDesc.ColorMap =
305 MakeMapObject(CopyFrom->ImageDesc.ColorMap->ColorCount,
306 CopyFrom->ImageDesc.ColorMap->Colors);
307
308 /* next, the raster */
309 sp->RasterBits = (GifPixelType *)xmalloc(sizeof(GifPixelType)
310 * CopyFrom->ImageDesc.Height
311 * CopyFrom->ImageDesc.Width);
312 memcpy(sp->RasterBits,
313 CopyFrom->RasterBits,
314 sizeof(GifPixelType)
315 * CopyFrom->ImageDesc.Height
316 * CopyFrom->ImageDesc.Width);
317
318 /* finally, the extension blocks */
319 if (sp->ExtensionBlocks)
320 {
321 sp->ExtensionBlocks
322 = (ExtensionBlock*)xmalloc(sizeof(ExtensionBlock)
323 * CopyFrom->ExtensionBlockCount);
324 memcpy(sp->ExtensionBlocks,
325 CopyFrom->ExtensionBlocks,
326 sizeof(ExtensionBlock)
327 * CopyFrom->ExtensionBlockCount);
328
329 /*
330 * For the moment, the actual blocks can take their
331 * chances with free(). We'll fix this later.
332 */
333 }
334 }
335
336 return(sp);
337 }
338 }
339
340 void FreeSavedImages(GifFileType *GifFile)
341 {
342 SavedImage *sp;
343
344 for (sp = GifFile->SavedImages;
345 sp < GifFile->SavedImages + GifFile->ImageCount;
346 sp++)
347 {
348 if (sp->ImageDesc.ColorMap)
349 {
350 FreeMapObject(sp->ImageDesc.ColorMap);
351 sp->ImageDesc.ColorMap = 0;
352 }
353
354 if (sp->RasterBits)
355 {
356 xfree((char *)sp->RasterBits);
357 sp->RasterBits = 0;
358 }
359
360 if (sp->ExtensionBlocks)
361 {
362 FreeExtension(sp);
363 sp->ExtensionBlocks = 0;
364 }
365 }
366 xfree((char *) GifFile->SavedImages);
367 }
368
369
370