summaryrefslogtreecommitdiff
path: root/apps/plugins/imageviewer/gif/gifalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/imageviewer/gif/gifalloc.c')
-rw-r--r--apps/plugins/imageviewer/gif/gifalloc.c405
1 files changed, 405 insertions, 0 deletions
diff --git a/apps/plugins/imageviewer/gif/gifalloc.c b/apps/plugins/imageviewer/gif/gifalloc.c
new file mode 100644
index 0000000000..5810559320
--- /dev/null
+++ b/apps/plugins/imageviewer/gif/gifalloc.c
@@ -0,0 +1,405 @@
1/*****************************************************************************
2
3 GIF construction tools
4
5****************************************************************************/
6
7#include <stdlib.h>
8/* #include <stdio.h> */
9#include <string.h>
10
11#include "gif_lib.h"
12
13#ifndef MAX
14#define MAX(x, y) (((x) > (y)) ? (x) : (y))
15#endif
16
17/******************************************************************************
18 Miscellaneous utility functions
19******************************************************************************/
20
21/* return smallest bitfield size n will fit in */
22int
23GifBitSize(int n)
24{
25 register int i;
26
27 for (i = 1; i <= 8; i++)
28 if ((1 << i) >= n)
29 break;
30 return (i);
31}
32
33/******************************************************************************
34 Color map object functions
35******************************************************************************/
36
37/*
38 * Allocate a color map of given size; initialize with contents of
39 * ColorMap if that pointer is non-NULL.
40 */
41ColorMapObject *
42GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)
43{
44 ColorMapObject *Object;
45
46 /*** FIXME: Our ColorCount has to be a power of two. Is it necessary to
47 * make the user know that or should we automatically round up instead? */
48 if (ColorCount != (1 << GifBitSize(ColorCount))) {
49 return ((ColorMapObject *) NULL);
50 }
51
52 Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
53 if (Object == (ColorMapObject *) NULL) {
54 return ((ColorMapObject *) NULL);
55 }
56
57 Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
58 if (Object->Colors == (GifColorType *) NULL) {
59 free(Object);
60 return ((ColorMapObject *) NULL);
61 }
62
63 Object->ColorCount = ColorCount;
64 Object->BitsPerPixel = GifBitSize(ColorCount);
65
66 if (ColorMap != NULL) {
67 memcpy((char *)Object->Colors,
68 (char *)ColorMap, ColorCount * sizeof(GifColorType));
69 }
70
71 return (Object);
72}
73
74/*******************************************************************************
75Free a color map object
76*******************************************************************************/
77void
78GifFreeMapObject(ColorMapObject *Object)
79{
80 if (Object != NULL) {
81 (void)free(Object->Colors);
82 (void)free(Object);
83 }
84}
85
86/* #ifdef DEBUG */
87#if 0
88void
89DumpColorMap(ColorMapObject *Object,
90 FILE * fp)
91{
92 if (Object != NULL) {
93 int i, j, Len = Object->ColorCount;
94
95 for (i = 0; i < Len; i += 4) {
96 for (j = 0; j < 4 && j < Len; j++) {
97 (void)fprintf(fp, "%3d: %02x %02x %02x ", i + j,
98 Object->Colors[i + j].Red,
99 Object->Colors[i + j].Green,
100 Object->Colors[i + j].Blue);
101 }
102 (void)fprintf(fp, "\n");
103 }
104 }
105}
106#endif /* DEBUG */
107
108/*******************************************************************************
109 Compute the union of two given color maps and return it. If result can't
110 fit into 256 colors, NULL is returned, the allocated union otherwise.
111 ColorIn1 is copied as is to ColorUnion, while colors from ColorIn2 are
112 copied iff they didn't exist before. ColorTransIn2 maps the old
113 ColorIn2 into the ColorUnion color map table./
114*******************************************************************************/
115ColorMapObject *
116GifUnionColorMap(const ColorMapObject *ColorIn1,
117 const ColorMapObject *ColorIn2,
118 GifPixelType ColorTransIn2[])
119{
120 int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
121 ColorMapObject *ColorUnion;
122
123 /*
124 * We don't worry about duplicates within either color map; if
125 * the caller wants to resolve those, he can perform unions
126 * with an empty color map.
127 */
128
129 /* Allocate table which will hold the result for sure. */
130 ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,
131 ColorIn2->ColorCount) * 2, NULL);
132
133 if (ColorUnion == NULL)
134 return (NULL);
135
136 /*
137 * Copy ColorIn1 to ColorUnion.
138 */
139 for (i = 0; i < ColorIn1->ColorCount; i++)
140 ColorUnion->Colors[i] = ColorIn1->Colors[i];
141 CrntSlot = ColorIn1->ColorCount;
142
143 /*
144 * Potentially obnoxious hack:
145 *
146 * Back CrntSlot down past all contiguous {0, 0, 0} slots at the end
147 * of table 1. This is very useful if your display is limited to
148 * 16 colors.
149 */
150 while (ColorIn1->Colors[CrntSlot - 1].Red == 0
151 && ColorIn1->Colors[CrntSlot - 1].Green == 0
152 && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
153 CrntSlot--;
154
155 /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */
156 for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
157 /* Let's see if this color already exists: */
158 for (j = 0; j < ColorIn1->ColorCount; j++)
159 if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],
160 sizeof(GifColorType)) == 0)
161 break;
162
163 if (j < ColorIn1->ColorCount)
164 ColorTransIn2[i] = j; /* color exists in Color1 */
165 else {
166 /* Color is new - copy it to a new slot: */
167 ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
168 ColorTransIn2[i] = CrntSlot++;
169 }
170 }
171
172 if (CrntSlot > 256) {
173 GifFreeMapObject(ColorUnion);
174 return ((ColorMapObject *) NULL);
175 }
176
177 NewGifBitSize = GifBitSize(CrntSlot);
178 RoundUpTo = (1 << NewGifBitSize);
179
180 if (RoundUpTo != ColorUnion->ColorCount) {
181 register GifColorType *Map = ColorUnion->Colors;
182
183 /*
184 * Zero out slots up to next power of 2.
185 * We know these slots exist because of the way ColorUnion's
186 * start dimension was computed.
187 */
188 for (j = CrntSlot; j < RoundUpTo; j++)
189 Map[j].Red = Map[j].Green = Map[j].Blue = 0;
190
191 /* perhaps we can shrink the map? */
192 if (RoundUpTo < ColorUnion->ColorCount)
193 ColorUnion->Colors = (GifColorType *)realloc(Map,
194 sizeof(GifColorType) * RoundUpTo);
195 }
196
197 ColorUnion->ColorCount = RoundUpTo;
198 ColorUnion->BitsPerPixel = NewGifBitSize;
199
200 return (ColorUnion);
201}
202
203/*******************************************************************************
204 Apply a given color translation to the raster bits of an image
205*******************************************************************************/
206void
207GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])
208{
209 register int i;
210 register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
211
212 for (i = 0; i < RasterSize; i++)
213 Image->RasterBits[i] = Translation[Image->RasterBits[i]];
214}
215
216/******************************************************************************
217 Extension record functions
218******************************************************************************/
219int
220GifAddExtensionBlock(int *ExtensionBlockCount,
221 ExtensionBlock **ExtensionBlocks,
222 int Function,
223 unsigned int Len,
224 unsigned char ExtData[])
225{
226 ExtensionBlock *ep;
227
228 if (*ExtensionBlocks == NULL)
229 *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
230 else
231 *ExtensionBlocks = (ExtensionBlock *)realloc(*ExtensionBlocks,
232 sizeof(ExtensionBlock) *
233 (*ExtensionBlockCount + 1));
234
235 if (*ExtensionBlocks == NULL)
236 return (GIF_ERROR);
237
238 ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];
239
240 ep->Function = Function;
241 ep->ByteCount=Len;
242 ep->Bytes = (GifByteType *)malloc(ep->ByteCount);
243 if (ep->Bytes == NULL)
244 return (GIF_ERROR);
245
246 if (ExtData != NULL) {
247 memcpy(ep->Bytes, ExtData, Len);
248 }
249
250 return (GIF_OK);
251}
252
253void
254GifFreeExtensions(int *ExtensionBlockCount,
255 ExtensionBlock **ExtensionBlocks)
256{
257 ExtensionBlock *ep;
258
259 if (*ExtensionBlocks == NULL)
260 return;
261
262 for (ep = *ExtensionBlocks;
263 ep < (*ExtensionBlocks + *ExtensionBlockCount);
264 ep++)
265 (void)free((char *)ep->Bytes);
266 (void)free((char *)*ExtensionBlocks);
267 *ExtensionBlocks = NULL;
268 *ExtensionBlockCount = 0;
269}
270
271/******************************************************************************
272 Image block allocation functions
273******************************************************************************/
274
275/* Private Function:
276 * Frees the last image in the GifFile->SavedImages array
277 */
278void
279FreeLastSavedImage(GifFileType *GifFile)
280{
281 SavedImage *sp;
282
283 if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
284 return;
285
286 /* Remove one SavedImage from the GifFile */
287 GifFile->ImageCount--;
288 sp = &GifFile->SavedImages[GifFile->ImageCount];
289
290 /* Deallocate its Colormap */
291 if (sp->ImageDesc.ColorMap != NULL) {
292 GifFreeMapObject(sp->ImageDesc.ColorMap);
293 sp->ImageDesc.ColorMap = NULL;
294 }
295
296 /* Deallocate the image data */
297 if (sp->RasterBits != NULL)
298 free((char *)sp->RasterBits);
299
300 /* Deallocate any extensions */
301 GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
302
303 /*** FIXME: We could realloc the GifFile->SavedImages structure but is
304 * there a point to it? Saves some memory but we'd have to do it every
305 * time. If this is used in GifFreeSavedImages then it would be inefficient
306 * (The whole array is going to be deallocated.) If we just use it when
307 * we want to free the last Image it's convenient to do it here.
308 */
309}
310
311/*
312 * Append an image block to the SavedImages array
313 */
314SavedImage *
315GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
316{
317 SavedImage *sp;
318
319 if (GifFile->SavedImages == NULL)
320 GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
321 else
322 GifFile->SavedImages = (SavedImage *)realloc(GifFile->SavedImages,
323 sizeof(SavedImage) * (GifFile->ImageCount + 1));
324
325 if (GifFile->SavedImages == NULL)
326 return ((SavedImage *)NULL);
327 else {
328 sp = &GifFile->SavedImages[GifFile->ImageCount++];
329 memset((char *)sp, '\0', sizeof(SavedImage));
330
331 if (CopyFrom != NULL) {
332 memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
333
334 /*
335 * Make our own allocated copies of the heap fields in the
336 * copied record. This guards against potential aliasing
337 * problems.
338 */
339
340 /* first, the local color map */
341 if (sp->ImageDesc.ColorMap != NULL) {
342 sp->ImageDesc.ColorMap = GifMakeMapObject(
343 CopyFrom->ImageDesc.ColorMap->ColorCount,
344 CopyFrom->ImageDesc.ColorMap->Colors);
345 if (sp->ImageDesc.ColorMap == NULL) {
346 FreeLastSavedImage(GifFile);
347 return (SavedImage *)(NULL);
348 }
349 }
350
351 /* next, the raster */
352 sp->RasterBits = (unsigned char *)malloc(sizeof(GifPixelType) *
353 CopyFrom->ImageDesc.Height *
354 CopyFrom->ImageDesc.Width);
355 if (sp->RasterBits == NULL) {
356 FreeLastSavedImage(GifFile);
357 return (SavedImage *)(NULL);
358 }
359 memcpy(sp->RasterBits, CopyFrom->RasterBits,
360 sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
361 CopyFrom->ImageDesc.Width);
362
363 /* finally, the extension blocks */
364 if (sp->ExtensionBlocks != NULL) {
365 sp->ExtensionBlocks = (ExtensionBlock *)malloc(
366 sizeof(ExtensionBlock) *
367 CopyFrom->ExtensionBlockCount);
368 if (sp->ExtensionBlocks == NULL) {
369 FreeLastSavedImage(GifFile);
370 return (SavedImage *)(NULL);
371 }
372 memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
373 sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
374 }
375 }
376
377 return (sp);
378 }
379}
380
381void
382GifFreeSavedImages(GifFileType *GifFile)
383{
384 SavedImage *sp;
385
386 if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
387 return;
388 }
389 for (sp = GifFile->SavedImages;
390 sp < GifFile->SavedImages + GifFile->ImageCount; sp++) {
391 if (sp->ImageDesc.ColorMap != NULL) {
392 GifFreeMapObject(sp->ImageDesc.ColorMap);
393 sp->ImageDesc.ColorMap = NULL;
394 }
395
396 if (sp->RasterBits != NULL)
397 free((char *)sp->RasterBits);
398
399 GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
400 }
401 free((char *)GifFile->SavedImages);
402 GifFile->SavedImages = NULL;
403}
404
405/* end */