Mercurial > hg > xemacs-beta
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 |