1 |
robbat2 13/12/27 22:55:08 |
2 |
|
3 |
Added: xplanet-1.3.0-giflib.patch |
4 |
Log: |
5 |
Bug #488406: newer giflib compile fixes. |
6 |
|
7 |
(Portage version: 2.2.7/cvs/Linux x86_64, unsigned Manifest commit) |
8 |
|
9 |
Revision Changes Path |
10 |
1.1 x11-misc/xplanet/files/xplanet-1.3.0-giflib.patch |
11 |
|
12 |
file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/x11-misc/xplanet/files/xplanet-1.3.0-giflib.patch?rev=1.1&view=markup |
13 |
plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/x11-misc/xplanet/files/xplanet-1.3.0-giflib.patch?rev=1.1&content-type=text/plain |
14 |
|
15 |
Index: xplanet-1.3.0-giflib.patch |
16 |
=================================================================== |
17 |
Fixes from upstream SVN, to support giflib-4.2 and giflib-5. |
18 |
|
19 |
Index: src/libimage/gif.c |
20 |
=================================================================== |
21 |
--- src/libimage/gif.c (revision 184) |
22 |
+++ src/libimage/gif.c (revision 186) |
23 |
@@ -20,222 +20,581 @@ |
24 |
|
25 |
#include <stdio.h> |
26 |
#include <stdlib.h> |
27 |
+#include <string.h> |
28 |
|
29 |
#include <gif_lib.h> |
30 |
|
31 |
/* |
32 |
- A lot of this is based on the gif2rgb and rgb2gif codes in the libungif |
33 |
- distribution. |
34 |
+ Based on the gif2rgb and rgb2gif codes in the libgif distribution. |
35 |
*/ |
36 |
|
37 |
int |
38 |
read_gif(const char *filename, int *width, int *height, unsigned char **rgb) |
39 |
{ |
40 |
- int interlace_offset[] = { 0, 4, 2, 1 }; |
41 |
- int interlace_jump[] = { 8, 8, 4, 2 }; |
42 |
- GifColorType *colormap; |
43 |
- GifFileType *infile; |
44 |
- GifRecordType record_type; |
45 |
- GifRowType *buffer = NULL; |
46 |
+ int BackGround = 0; |
47 |
+ /* The way Interlaced image should be read - offsets and |
48 |
+ jumps... */ |
49 |
+ int InterlacedOffset[] = { 0, 4, 2, 1 }; |
50 |
+ int InterlacedJumps[] = { 8, 8, 4, 2 }; |
51 |
+ ColorMapObject *ColorMap; |
52 |
|
53 |
- int i, j; |
54 |
- int color_index; |
55 |
- unsigned char *ptr = NULL; |
56 |
+ int i, j, Size, Row, Col, Width, Height, ExtCode, Count; |
57 |
+ GifRecordType RecordType; |
58 |
+ GifByteType *Extension; |
59 |
+ GifRowType *ScreenBuffer; |
60 |
|
61 |
- infile = DGifOpenFileName(filename); |
62 |
+ GifRowType GifRow; |
63 |
+ GifColorType *ColorMapEntry; |
64 |
+ unsigned char *BufferP; |
65 |
|
66 |
- if (infile == NULL) |
67 |
+ GifFileType *GifFile; |
68 |
+#if GIFLIB_MAJOR >= 5 |
69 |
+ GifFile = DGifOpenFileName(filename, NULL); |
70 |
+#else |
71 |
+ GifFile = DGifOpenFileName(filename); |
72 |
+#endif |
73 |
+ if (GifFile == NULL) { |
74 |
+ fprintf(stderr, "Can't open GIF file %s\n", filename); |
75 |
+ return(0); |
76 |
+ } |
77 |
+ /* (Following comment was probably written on a 286 running under DOS.) */ |
78 |
+ /* Allocate the screen as vector of column of rows. We can't allocate the*/ |
79 |
+ /* whole screen at once, as this broken minded CPU can allocate up to */ |
80 |
+ /* 64k at a time and our image can be bigger than that: */ |
81 |
+ /* Note this screen is device independent - it's the screen defined by */ |
82 |
+ /* the GIF file parameters. */ |
83 |
+ if ((ScreenBuffer = (GifRowType *) |
84 |
+ malloc(GifFile->SHeight * sizeof(GifRowType))) == NULL) |
85 |
{ |
86 |
- PrintGifError(); |
87 |
- return(0); |
88 |
+ fprintf(stderr, "Failed to allocate memory required, aborted."); |
89 |
+ return(0); |
90 |
} |
91 |
|
92 |
- do |
93 |
+ Size = GifFile->SWidth * sizeof(GifPixelType);/* Size in bytes one row.*/ |
94 |
+ if ((ScreenBuffer[0] = (GifRowType) malloc(Size)) == NULL) /* First row. */ |
95 |
{ |
96 |
- if (DGifGetRecordType(infile, &record_type) == GIF_ERROR) |
97 |
- { |
98 |
- PrintGifError(); |
99 |
- return(0); |
100 |
+ fprintf(stderr, "Failed to allocate memory required, aborted."); |
101 |
+ return(0); |
102 |
+ } |
103 |
+ |
104 |
+ for (i = 0; i < GifFile->SWidth; i++) /* Set its color to BackGround. */ |
105 |
+ ScreenBuffer[0][i] = GifFile->SBackGroundColor; |
106 |
+ for (i = 1; i < GifFile->SHeight; i++) { |
107 |
+ /* Allocate the other rows, and set their color to background too: */ |
108 |
+ if ((ScreenBuffer[i] = (GifRowType) malloc(Size)) == NULL) |
109 |
+ { |
110 |
+ fprintf(stderr, "Failed to allocate memory required, aborted.\n"); |
111 |
+ return(0); |
112 |
+ } |
113 |
+ |
114 |
+ memcpy(ScreenBuffer[i], ScreenBuffer[0], Size); |
115 |
+ } |
116 |
+ |
117 |
+ /* Scan the content of the GIF file and load the image(s) in: */ |
118 |
+ do { |
119 |
+ if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) { |
120 |
+ fprintf(stderr, "Can't read GIF file\n"); |
121 |
+ return(0); |
122 |
+ } |
123 |
+ switch (RecordType) { |
124 |
+ case IMAGE_DESC_RECORD_TYPE: |
125 |
+ if (DGifGetImageDesc(GifFile) == GIF_ERROR) { |
126 |
+ return(0); |
127 |
+ } |
128 |
+ Row = GifFile->Image.Top; /* Image Position relative to Screen. */ |
129 |
+ Col = GifFile->Image.Left; |
130 |
+ Width = GifFile->Image.Width; |
131 |
+ Height = GifFile->Image.Height; |
132 |
+ if (GifFile->Image.Left + GifFile->Image.Width > GifFile->SWidth || |
133 |
+ GifFile->Image.Top + GifFile->Image.Height > GifFile->SHeight) { |
134 |
+ return(0); |
135 |
+ } |
136 |
+ if (GifFile->Image.Interlace) { |
137 |
+ /* Need to perform 4 passes on the images: */ |
138 |
+ for (Count = i = 0; i < 4; i++) |
139 |
+ for (j = Row + InterlacedOffset[i]; j < Row + Height; |
140 |
+ j += InterlacedJumps[i]) { |
141 |
+ if (DGifGetLine(GifFile, &ScreenBuffer[j][Col], |
142 |
+ Width) == GIF_ERROR) { |
143 |
+ return(0); |
144 |
+ } |
145 |
+ } |
146 |
+ } |
147 |
+ else { |
148 |
+ for (i = 0; i < Height; i++) { |
149 |
+ if (DGifGetLine(GifFile, &ScreenBuffer[Row++][Col], |
150 |
+ Width) == GIF_ERROR) { |
151 |
+ return(0); |
152 |
+ } |
153 |
+ } |
154 |
+ } |
155 |
+ break; |
156 |
+ case EXTENSION_RECORD_TYPE: |
157 |
+ /* Skip any extension blocks in file: */ |
158 |
+ if (DGifGetExtension(GifFile, &ExtCode, &Extension) == GIF_ERROR) { |
159 |
+ return(0); |
160 |
+ } |
161 |
+ while (Extension != NULL) { |
162 |
+ if (DGifGetExtensionNext(GifFile, &Extension) == GIF_ERROR) { |
163 |
+ return(0); |
164 |
+ } |
165 |
+ } |
166 |
+ break; |
167 |
+ case TERMINATE_RECORD_TYPE: |
168 |
+ break; |
169 |
+ default: /* Should be traps by DGifGetRecordType. */ |
170 |
+ break; |
171 |
+ } |
172 |
+ } while (RecordType != TERMINATE_RECORD_TYPE); |
173 |
+ |
174 |
+ /* Lets dump it - set the global variables required and do it: */ |
175 |
+ BackGround = GifFile->SBackGroundColor; |
176 |
+ ColorMap = (GifFile->Image.ColorMap |
177 |
+ ? GifFile->Image.ColorMap |
178 |
+ : GifFile->SColorMap); |
179 |
+ if (ColorMap == NULL) { |
180 |
+ fprintf(stderr, "Gif Image does not have a colormap\n"); |
181 |
+ return(0); |
182 |
+ } |
183 |
+ |
184 |
+ *width = GifFile->SWidth; |
185 |
+ *height = GifFile->SHeight; |
186 |
+ |
187 |
+ rgb[0] = malloc(3 * *width * *height); |
188 |
+ if (rgb[0] == NULL) |
189 |
+ { |
190 |
+ fprintf(stderr, "Can't allocate memory for GIF file.\n"); |
191 |
+ return(0); |
192 |
+ } |
193 |
+ |
194 |
+ BufferP = rgb[0]; |
195 |
+ |
196 |
+ for (i = 0; i < *height; i++) { |
197 |
+ GifRow = ScreenBuffer[i]; |
198 |
+ for (j = 0; j < *width; j++) { |
199 |
+ ColorMapEntry = &ColorMap->Colors[GifRow[j]]; |
200 |
+ *BufferP++ = ColorMapEntry->Red; |
201 |
+ *BufferP++ = ColorMapEntry->Green; |
202 |
+ *BufferP++ = ColorMapEntry->Blue; |
203 |
+ } |
204 |
+ } |
205 |
+ |
206 |
+ if (DGifCloseFile(GifFile) == GIF_ERROR) { |
207 |
+ return(0); |
208 |
+ } |
209 |
+ |
210 |
+ return(1); |
211 |
+} |
212 |
+ |
213 |
+/* Make some variables global, so we could access them faster: */ |
214 |
+static int |
215 |
+ ExpNumOfColors = 8, |
216 |
+ ColorMapSize = 256; |
217 |
+ |
218 |
+/****************************************************************************** |
219 |
+ * Code to quantize high resolution image into lower one. You may want to |
220 |
+ * peek into the following article this code is based on: |
221 |
+ * "Color Image Quantization for frame buffer Display", by Paul Heckbert |
222 |
+ * SIGGRAPH 1982 page 297-307. |
223 |
+ ****************************************************************************** |
224 |
+ * History: |
225 |
+ * 5 Jan 90 - Version 1.0 by Gershon Elber. |
226 |
+ *****************************************************************************/ |
227 |
+ |
228 |
+#define ABS(x) ((x) > 0 ? (x) : (-(x))) |
229 |
+ |
230 |
+#define COLOR_ARRAY_SIZE 32768 |
231 |
+#define BITS_PER_PRIM_COLOR 5 |
232 |
+#define MAX_PRIM_COLOR 0x1f |
233 |
+ |
234 |
+static int SortRGBAxis; |
235 |
+ |
236 |
+typedef struct QuantizedColorType { |
237 |
+ GifByteType RGB[3]; |
238 |
+ GifByteType NewColorIndex; |
239 |
+ long Count; |
240 |
+ struct QuantizedColorType *Pnext; |
241 |
+} QuantizedColorType; |
242 |
+ |
243 |
+typedef struct NewColorMapType { |
244 |
+ GifByteType RGBMin[3], RGBWidth[3]; |
245 |
+ unsigned int NumEntries; /* # of QuantizedColorType in linked list below */ |
246 |
+ unsigned long Count; /* Total number of pixels in all the entries */ |
247 |
+ QuantizedColorType *QuantizedColors; |
248 |
+} NewColorMapType; |
249 |
+ |
250 |
+static int SubdivColorMap(NewColorMapType * NewColorSubdiv, |
251 |
+ unsigned int ColorMapSize, |
252 |
+ unsigned int *NewColorMapSize); |
253 |
+static int SortCmpRtn(const void *Entry1, const void *Entry2); |
254 |
+ |
255 |
+/****************************************************************************** |
256 |
+ * Quantize high resolution image into lower one. Input image consists of a |
257 |
+ * 2D array for each of the RGB colors with size Width by Height. There is no |
258 |
+ * Color map for the input. Output is a quantized image with 2D array of |
259 |
+ * indexes into the output color map. |
260 |
+ * Note input image can be 24 bits at the most (8 for red/green/blue) and |
261 |
+ * the output has 256 colors at the most (256 entries in the color map.). |
262 |
+ * ColorMapSize specifies size of color map up to 256 and will be updated to |
263 |
+ * real size before returning. |
264 |
+ * Also non of the parameter are allocated by this routine. |
265 |
+ * This function returns GIF_OK if succesfull, GIF_ERROR otherwise. |
266 |
+ ******************************************************************************/ |
267 |
+static int |
268 |
+QuantizeBuffer(unsigned int Width, |
269 |
+ unsigned int Height, |
270 |
+ int *ColorMapSize, |
271 |
+ GifByteType * RedInput, |
272 |
+ GifByteType * GreenInput, |
273 |
+ GifByteType * BlueInput, |
274 |
+ GifByteType * OutputBuffer, |
275 |
+ GifColorType * OutputColorMap) { |
276 |
+ |
277 |
+ unsigned int Index, NumOfEntries; |
278 |
+ int i, j, MaxRGBError[3]; |
279 |
+ unsigned int NewColorMapSize; |
280 |
+ long Red, Green, Blue; |
281 |
+ NewColorMapType NewColorSubdiv[256]; |
282 |
+ QuantizedColorType *ColorArrayEntries, *QuantizedColor; |
283 |
+ |
284 |
+ ColorArrayEntries = (QuantizedColorType *)malloc( |
285 |
+ sizeof(QuantizedColorType) * COLOR_ARRAY_SIZE); |
286 |
+ if (ColorArrayEntries == NULL) { |
287 |
+ return GIF_ERROR; |
288 |
+ } |
289 |
+ |
290 |
+ for (i = 0; i < COLOR_ARRAY_SIZE; i++) { |
291 |
+ ColorArrayEntries[i].RGB[0] = i >> (2 * BITS_PER_PRIM_COLOR); |
292 |
+ ColorArrayEntries[i].RGB[1] = (i >> BITS_PER_PRIM_COLOR) & |
293 |
+ MAX_PRIM_COLOR; |
294 |
+ ColorArrayEntries[i].RGB[2] = i & MAX_PRIM_COLOR; |
295 |
+ ColorArrayEntries[i].Count = 0; |
296 |
+ } |
297 |
+ |
298 |
+ /* Sample the colors and their distribution: */ |
299 |
+ for (i = 0; i < (int)(Width * Height); i++) { |
300 |
+ Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) << |
301 |
+ (2 * BITS_PER_PRIM_COLOR)) + |
302 |
+ ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) << |
303 |
+ BITS_PER_PRIM_COLOR) + |
304 |
+ (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR)); |
305 |
+ ColorArrayEntries[Index].Count++; |
306 |
+ } |
307 |
+ |
308 |
+ /* Put all the colors in the first entry of the color map, and call the |
309 |
+ * recursive subdivision process. */ |
310 |
+ for (i = 0; i < 256; i++) { |
311 |
+ NewColorSubdiv[i].QuantizedColors = NULL; |
312 |
+ NewColorSubdiv[i].Count = NewColorSubdiv[i].NumEntries = 0; |
313 |
+ for (j = 0; j < 3; j++) { |
314 |
+ NewColorSubdiv[i].RGBMin[j] = 0; |
315 |
+ NewColorSubdiv[i].RGBWidth[j] = 255; |
316 |
} |
317 |
+ } |
318 |
|
319 |
- switch (record_type) |
320 |
- { |
321 |
- case IMAGE_DESC_RECORD_TYPE: |
322 |
- if (DGifGetImageDesc(infile) == GIF_ERROR) |
323 |
- { |
324 |
- PrintGifError(); |
325 |
- return(0); |
326 |
+ /* Find the non empty entries in the color table and chain them: */ |
327 |
+ for (i = 0; i < COLOR_ARRAY_SIZE; i++) |
328 |
+ if (ColorArrayEntries[i].Count > 0) |
329 |
+ break; |
330 |
+ QuantizedColor = NewColorSubdiv[0].QuantizedColors = &ColorArrayEntries[i]; |
331 |
+ NumOfEntries = 1; |
332 |
+ while (++i < COLOR_ARRAY_SIZE) |
333 |
+ if (ColorArrayEntries[i].Count > 0) { |
334 |
+ QuantizedColor->Pnext = &ColorArrayEntries[i]; |
335 |
+ QuantizedColor = &ColorArrayEntries[i]; |
336 |
+ NumOfEntries++; |
337 |
+ } |
338 |
+ QuantizedColor->Pnext = NULL; |
339 |
+ |
340 |
+ NewColorSubdiv[0].NumEntries = NumOfEntries; /* Different sampled colors */ |
341 |
+ NewColorSubdiv[0].Count = ((long)Width) * Height; /* Pixels */ |
342 |
+ NewColorMapSize = 1; |
343 |
+ if (SubdivColorMap(NewColorSubdiv, *ColorMapSize, &NewColorMapSize) != |
344 |
+ GIF_OK) { |
345 |
+ free((char *)ColorArrayEntries); |
346 |
+ return GIF_ERROR; |
347 |
+ } |
348 |
+ if (NewColorMapSize < *ColorMapSize) { |
349 |
+ /* And clear rest of color map: */ |
350 |
+ for (i = NewColorMapSize; i < *ColorMapSize; i++) |
351 |
+ OutputColorMap[i].Red = OutputColorMap[i].Green = |
352 |
+ OutputColorMap[i].Blue = 0; |
353 |
+ } |
354 |
+ |
355 |
+ /* Average the colors in each entry to be the color to be used in the |
356 |
+ * output color map, and plug it into the output color map itself. */ |
357 |
+ for (i = 0; i < NewColorMapSize; i++) { |
358 |
+ if ((j = NewColorSubdiv[i].NumEntries) > 0) { |
359 |
+ QuantizedColor = NewColorSubdiv[i].QuantizedColors; |
360 |
+ Red = Green = Blue = 0; |
361 |
+ while (QuantizedColor) { |
362 |
+ QuantizedColor->NewColorIndex = i; |
363 |
+ Red += QuantizedColor->RGB[0]; |
364 |
+ Green += QuantizedColor->RGB[1]; |
365 |
+ Blue += QuantizedColor->RGB[2]; |
366 |
+ QuantizedColor = QuantizedColor->Pnext; |
367 |
} |
368 |
+ OutputColorMap[i].Red = (Red << (8 - BITS_PER_PRIM_COLOR)) / j; |
369 |
+ OutputColorMap[i].Green = (Green << (8 - BITS_PER_PRIM_COLOR)) / j; |
370 |
+ OutputColorMap[i].Blue = (Blue << (8 - BITS_PER_PRIM_COLOR)) / j; |
371 |
+ } else |
372 |
+ fprintf(stderr, |
373 |
+ "Null entry in quantized color map - that's weird.\n"); |
374 |
+ } |
375 |
|
376 |
- *width = infile->Image.Width; |
377 |
- *height = infile->Image.Height; |
378 |
+ /* Finally scan the input buffer again and put the mapped index in the |
379 |
+ * output buffer. */ |
380 |
+ MaxRGBError[0] = MaxRGBError[1] = MaxRGBError[2] = 0; |
381 |
+ for (i = 0; i < (int)(Width * Height); i++) { |
382 |
+ Index = ((RedInput[i] >> (8 - BITS_PER_PRIM_COLOR)) << |
383 |
+ (2 * BITS_PER_PRIM_COLOR)) + |
384 |
+ ((GreenInput[i] >> (8 - BITS_PER_PRIM_COLOR)) << |
385 |
+ BITS_PER_PRIM_COLOR) + |
386 |
+ (BlueInput[i] >> (8 - BITS_PER_PRIM_COLOR)); |
387 |
+ Index = ColorArrayEntries[Index].NewColorIndex; |
388 |
+ OutputBuffer[i] = Index; |
389 |
+ if (MaxRGBError[0] < ABS(OutputColorMap[Index].Red - RedInput[i])) |
390 |
+ MaxRGBError[0] = ABS(OutputColorMap[Index].Red - RedInput[i]); |
391 |
+ if (MaxRGBError[1] < ABS(OutputColorMap[Index].Green - GreenInput[i])) |
392 |
+ MaxRGBError[1] = ABS(OutputColorMap[Index].Green - GreenInput[i]); |
393 |
+ if (MaxRGBError[2] < ABS(OutputColorMap[Index].Blue - BlueInput[i])) |
394 |
+ MaxRGBError[2] = ABS(OutputColorMap[Index].Blue - BlueInput[i]); |
395 |
+ } |
396 |
|
397 |
- buffer = malloc(*height * sizeof(GifRowType *)); |
398 |
- if (buffer == NULL) |
399 |
- { |
400 |
- fprintf(stderr, "Can't allocate memory for GIF file.\n"); |
401 |
- return(0); |
402 |
- } |
403 |
- |
404 |
- for (i = 0; i < *height; i++) |
405 |
- { |
406 |
- buffer[i] = malloc(*width * sizeof(GifPixelType)); |
407 |
- if (buffer[i] == NULL) |
408 |
- { |
409 |
- fprintf(stderr, "Can't allocate memory for GIF line.\n"); |
410 |
- return(0); |
411 |
+ free((char *)ColorArrayEntries); |
412 |
+ |
413 |
+ *ColorMapSize = NewColorMapSize; |
414 |
+ |
415 |
+ return GIF_OK; |
416 |
+} |
417 |
+ |
418 |
+/****************************************************************************** |
419 |
+ * Routine to subdivide the RGB space recursively using median cut in each |
420 |
+ * axes alternatingly until ColorMapSize different cubes exists. |
421 |
+ * The biggest cube in one dimension is subdivide unless it has only one entry. |
422 |
+ * Returns GIF_ERROR if failed, otherwise GIF_OK. |
423 |
+ ******************************************************************************/ |
424 |
+static int |
425 |
+SubdivColorMap(NewColorMapType * NewColorSubdiv, |
426 |
+ unsigned int ColorMapSize, |
427 |
+ unsigned int *NewColorMapSize) { |
428 |
+ |
429 |
+ int MaxSize; |
430 |
+ unsigned int i, j, Index = 0, NumEntries, MinColor, MaxColor; |
431 |
+ long Sum, Count; |
432 |
+ QuantizedColorType *QuantizedColor, **SortArray; |
433 |
+ |
434 |
+ while (ColorMapSize > *NewColorMapSize) { |
435 |
+ /* Find candidate for subdivision: */ |
436 |
+ MaxSize = -1; |
437 |
+ for (i = 0; i < *NewColorMapSize; i++) { |
438 |
+ for (j = 0; j < 3; j++) { |
439 |
+ if ((((int)NewColorSubdiv[i].RGBWidth[j]) > MaxSize) && |
440 |
+ (NewColorSubdiv[i].NumEntries > 1)) { |
441 |
+ MaxSize = NewColorSubdiv[i].RGBWidth[j]; |
442 |
+ Index = i; |
443 |
+ SortRGBAxis = j; |
444 |
} |
445 |
} |
446 |
- |
447 |
- if (infile->Image.Interlace) |
448 |
- { |
449 |
- for (i = 0; i < 4; i++) |
450 |
- for (j = interlace_offset[i]; j < *height; |
451 |
- j += interlace_jump[i]) |
452 |
- DGifGetLine(infile, buffer[j], *width); |
453 |
- } |
454 |
- else |
455 |
- { |
456 |
- for (i = 0; i < *height; i++) |
457 |
- DGifGetLine(infile, buffer[i], *width); |
458 |
- } |
459 |
- break; |
460 |
- case EXTENSION_RECORD_TYPE: |
461 |
- { |
462 |
- /* Skip extension blocks */ |
463 |
- int ext_code; |
464 |
- GifByteType *ext; |
465 |
- if (DGifGetExtension(infile, &ext_code, &ext) == GIF_ERROR) |
466 |
- { |
467 |
- PrintGifError(); |
468 |
- return(0); |
469 |
- } |
470 |
- while (ext != NULL) |
471 |
- { |
472 |
- if (DGifGetExtensionNext(infile, &ext) == GIF_ERROR) |
473 |
- { |
474 |
- PrintGifError(); |
475 |
- return(0); |
476 |
- } |
477 |
- } |
478 |
} |
479 |
- break; |
480 |
- case TERMINATE_RECORD_TYPE: |
481 |
- break; |
482 |
- default: |
483 |
- fprintf(stderr, "unknown record type in GIF file\n"); |
484 |
- break; |
485 |
- } |
486 |
- } while (record_type != TERMINATE_RECORD_TYPE); |
487 |
|
488 |
- colormap = (infile->Image.ColorMap ? infile->Image.ColorMap->Colors |
489 |
- : infile->SColorMap->Colors); |
490 |
+ if (MaxSize == -1) |
491 |
+ return GIF_OK; |
492 |
|
493 |
- rgb[0] = malloc(3 * *width * *height); |
494 |
- if (rgb[0] == NULL) |
495 |
- { |
496 |
- fprintf(stderr, "Can't allocate memory for GIF file.\n"); |
497 |
- return(0); |
498 |
- } |
499 |
+ /* Split the entry Index into two along the axis SortRGBAxis: */ |
500 |
|
501 |
- ptr = rgb[0]; |
502 |
+ /* Sort all elements in that entry along the given axis and split at |
503 |
+ * the median. */ |
504 |
+ SortArray = (QuantizedColorType **)malloc( |
505 |
+ sizeof(QuantizedColorType *) * |
506 |
+ NewColorSubdiv[Index].NumEntries); |
507 |
+ if (SortArray == NULL) |
508 |
+ return GIF_ERROR; |
509 |
+ for (j = 0, QuantizedColor = NewColorSubdiv[Index].QuantizedColors; |
510 |
+ j < NewColorSubdiv[Index].NumEntries && QuantizedColor != NULL; |
511 |
+ j++, QuantizedColor = QuantizedColor->Pnext) |
512 |
+ SortArray[j] = QuantizedColor; |
513 |
|
514 |
- for (j = 0; j < *height; j++) |
515 |
- { |
516 |
- for (i = 0; i < *width; i++) |
517 |
- { |
518 |
- color_index = (int) buffer[j][i]; |
519 |
- *ptr++ = (unsigned char) colormap[color_index].Red; |
520 |
- *ptr++ = (unsigned char) colormap[color_index].Green; |
521 |
- *ptr++ = (unsigned char) colormap[color_index].Blue; |
522 |
+ qsort(SortArray, NewColorSubdiv[Index].NumEntries, |
523 |
+ sizeof(QuantizedColorType *), SortCmpRtn); |
524 |
+ |
525 |
+ /* Relink the sorted list into one: */ |
526 |
+ for (j = 0; j < NewColorSubdiv[Index].NumEntries - 1; j++) |
527 |
+ SortArray[j]->Pnext = SortArray[j + 1]; |
528 |
+ SortArray[NewColorSubdiv[Index].NumEntries - 1]->Pnext = NULL; |
529 |
+ NewColorSubdiv[Index].QuantizedColors = QuantizedColor = SortArray[0]; |
530 |
+ free((char *)SortArray); |
531 |
+ |
532 |
+ /* Now simply add the Counts until we have half of the Count: */ |
533 |
+ Sum = NewColorSubdiv[Index].Count / 2 - QuantizedColor->Count; |
534 |
+ NumEntries = 1; |
535 |
+ Count = QuantizedColor->Count; |
536 |
+ while (QuantizedColor->Pnext != NULL && |
537 |
+ (Sum -= QuantizedColor->Pnext->Count) >= 0 && |
538 |
+ QuantizedColor->Pnext->Pnext != NULL) { |
539 |
+ QuantizedColor = QuantizedColor->Pnext; |
540 |
+ NumEntries++; |
541 |
+ Count += QuantizedColor->Count; |
542 |
} |
543 |
- free(buffer[j]); |
544 |
+ /* Save the values of the last color of the first half, and first |
545 |
+ * of the second half so we can update the Bounding Boxes later. |
546 |
+ * Also as the colors are quantized and the BBoxes are full 0..255, |
547 |
+ * they need to be rescaled. |
548 |
+ */ |
549 |
+ MaxColor = QuantizedColor->RGB[SortRGBAxis]; /* Max. of first half */ |
550 |
+ /* coverity[var_deref_op] */ |
551 |
+ MinColor = QuantizedColor->Pnext->RGB[SortRGBAxis]; /* of second */ |
552 |
+ MaxColor <<= (8 - BITS_PER_PRIM_COLOR); |
553 |
+ MinColor <<= (8 - BITS_PER_PRIM_COLOR); |
554 |
+ |
555 |
+ /* Partition right here: */ |
556 |
+ NewColorSubdiv[*NewColorMapSize].QuantizedColors = |
557 |
+ QuantizedColor->Pnext; |
558 |
+ QuantizedColor->Pnext = NULL; |
559 |
+ NewColorSubdiv[*NewColorMapSize].Count = Count; |
560 |
+ NewColorSubdiv[Index].Count -= Count; |
561 |
+ NewColorSubdiv[*NewColorMapSize].NumEntries = |
562 |
+ NewColorSubdiv[Index].NumEntries - NumEntries; |
563 |
+ NewColorSubdiv[Index].NumEntries = NumEntries; |
564 |
+ for (j = 0; j < 3; j++) { |
565 |
+ NewColorSubdiv[*NewColorMapSize].RGBMin[j] = |
566 |
+ NewColorSubdiv[Index].RGBMin[j]; |
567 |
+ NewColorSubdiv[*NewColorMapSize].RGBWidth[j] = |
568 |
+ NewColorSubdiv[Index].RGBWidth[j]; |
569 |
+ } |
570 |
+ NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] = |
571 |
+ NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] + |
572 |
+ NewColorSubdiv[*NewColorMapSize].RGBWidth[SortRGBAxis] - MinColor; |
573 |
+ NewColorSubdiv[*NewColorMapSize].RGBMin[SortRGBAxis] = MinColor; |
574 |
+ |
575 |
+ NewColorSubdiv[Index].RGBWidth[SortRGBAxis] = |
576 |
+ MaxColor - NewColorSubdiv[Index].RGBMin[SortRGBAxis]; |
577 |
+ |
578 |
+ (*NewColorMapSize)++; |
579 |
} |
580 |
- |
581 |
- free(buffer); |
582 |
|
583 |
- DGifCloseFile(infile); |
584 |
- return(1); |
585 |
+ return GIF_OK; |
586 |
} |
587 |
|
588 |
+/**************************************************************************** |
589 |
+ * Routine called by qsort to compare two entries. |
590 |
+ ****************************************************************************/ |
591 |
+static int |
592 |
+SortCmpRtn(const void *Entry1, |
593 |
+ const void *Entry2) { |
594 |
+ |
595 |
+ return (*((QuantizedColorType **) Entry1))->RGB[SortRGBAxis] - |
596 |
+ (*((QuantizedColorType **) Entry2))->RGB[SortRGBAxis]; |
597 |
+} |
598 |
+ |
599 |
+/****************************************************************************** |
600 |
+* Close output file (if open), and exit. |
601 |
+******************************************************************************/ |
602 |
+static void QuitGifError(GifFileType *GifFile) |
603 |
+{ |
604 |
+ fprintf(stderr, "Error writing GIF file\n"); |
605 |
+ if (GifFile != NULL) EGifCloseFile(GifFile); |
606 |
+} |
607 |
+ |
608 |
int |
609 |
write_gif(const char *filename, int width, int height, char *rgb) |
610 |
{ |
611 |
int i; |
612 |
- int colormap_size = 256; |
613 |
- GifByteType *red, *green, *blue, *buffer, *ptr; |
614 |
- GifFileType *outfile; |
615 |
- ColorMapObject *colormap; |
616 |
+ GifByteType *red, *green, *blue; |
617 |
|
618 |
+ GifByteType *OutputBuffer = NULL; |
619 |
+ ColorMapObject *OutputColorMap = NULL; |
620 |
+ |
621 |
+ GifFileType *GifFile; |
622 |
+ GifByteType *Ptr; |
623 |
+ |
624 |
+ bool GifTestExistance = false; |
625 |
+ |
626 |
+ ColorMapSize = 1 << ExpNumOfColors; |
627 |
+ |
628 |
+#if GIFLIB_MAJOR >= 5 |
629 |
+ OutputColorMap = GifMakeMapObject(ColorMapSize, NULL); |
630 |
+#else |
631 |
+ OutputColorMap = MakeMapObject(ColorMapSize, NULL); |
632 |
+#endif |
633 |
+ |
634 |
+ if (OutputColorMap == NULL || |
635 |
+ (OutputBuffer = (GifByteType *) malloc(width * height * |
636 |
+ sizeof(GifByteType))) == NULL) |
637 |
+ { |
638 |
+ fprintf(stderr,"Failed to allocate memory required, aborted."); |
639 |
+ return(0); |
640 |
+ } |
641 |
+ |
642 |
red = malloc(width * height * sizeof(GifByteType)); |
643 |
green = malloc(width * height * sizeof(GifByteType)); |
644 |
blue = malloc(width * height * sizeof(GifByteType)); |
645 |
- buffer = malloc(width * height * sizeof(GifByteType)); |
646 |
- |
647 |
- if (red == NULL || green == NULL || blue == NULL || buffer == NULL) |
648 |
+ if (red == NULL || green == NULL || blue == NULL) |
649 |
{ |
650 |
- fprintf(stderr, "Can't allocate memory for GIF file.\n"); |
651 |
- return(0); |
652 |
+ fprintf(stderr, "Can't allocate memory for GIF file.\n"); |
653 |
+ return(0); |
654 |
} |
655 |
- |
656 |
- colormap = MakeMapObject(colormap_size, NULL); |
657 |
- |
658 |
for (i = 0; i < width * height; i++) |
659 |
{ |
660 |
- red[i] = (GifByteType) rgb[3*i ]; |
661 |
- green[i] = (GifByteType) rgb[3*i+1]; |
662 |
- blue[i] = (GifByteType) rgb[3*i+2]; |
663 |
+ red[i] = (GifByteType) rgb[3*i ]; |
664 |
+ green[i] = (GifByteType) rgb[3*i+1]; |
665 |
+ blue[i] = (GifByteType) rgb[3*i+2]; |
666 |
} |
667 |
- |
668 |
- if (QuantizeBuffer(width, height, &colormap_size, red, green, blue, |
669 |
- buffer, colormap->Colors) == GIF_ERROR) |
670 |
+ |
671 |
+ if (QuantizeBuffer(width, height, &ColorMapSize, |
672 |
+ red, green, blue, |
673 |
+ OutputBuffer, OutputColorMap->Colors) == GIF_ERROR) |
674 |
+ |
675 |
{ |
676 |
- PrintGifError(); |
677 |
- return(0); |
678 |
+ QuitGifError(NULL); |
679 |
+ return(0); |
680 |
} |
681 |
|
682 |
free(red); |
683 |
free(green); |
684 |
free(blue); |
685 |
|
686 |
- outfile = EGifOpenFileName((char *) filename, FALSE); |
687 |
- if (outfile == NULL) |
688 |
+ Ptr = OutputBuffer; |
689 |
+ |
690 |
+#if GIFLIB_MAJOR >= 5 |
691 |
+ GifFile = EGifOpenFileName(filename, GifTestExistance, NULL); |
692 |
+#else |
693 |
+ GifFile = EGifOpenFileName(filename, GifTestExistance); |
694 |
+#endif |
695 |
+ /* Open stdout for the output file: */ |
696 |
+ if (GifFile == NULL) |
697 |
{ |
698 |
- PrintGifError(); |
699 |
- return(0); |
700 |
+ QuitGifError(GifFile); |
701 |
+ return(0); |
702 |
} |
703 |
|
704 |
- if (EGifPutScreenDesc(outfile, width, height, colormap_size, 0, colormap) |
705 |
- == GIF_ERROR) |
706 |
+ if (EGifPutScreenDesc(GifFile, |
707 |
+ width, height, ExpNumOfColors, 0, |
708 |
+ OutputColorMap) == GIF_ERROR || |
709 |
+ EGifPutImageDesc(GifFile, |
710 |
+ 0, 0, width, height, false, NULL) == GIF_ERROR) |
711 |
+ |
712 |
{ |
713 |
- PrintGifError(); |
714 |
- return(0); |
715 |
+ QuitGifError(GifFile); |
716 |
+ return(0); |
717 |
} |
718 |
|
719 |
- if (EGifPutImageDesc(outfile, 0, 0, width, height, FALSE, NULL) |
720 |
- == GIF_ERROR) |
721 |
- { |
722 |
- PrintGifError(); |
723 |
- return(0); |
724 |
+ for (i = 0; i < height; i++) { |
725 |
+ if (EGifPutLine(GifFile, Ptr, width) == GIF_ERROR) |
726 |
+ |
727 |
+ { |
728 |
+ QuitGifError(GifFile); |
729 |
+ return(0); |
730 |
+ } |
731 |
+ Ptr += width; |
732 |
} |
733 |
|
734 |
- ptr = buffer; |
735 |
- for (i = 0; i < height; i++) |
736 |
+ if (EGifCloseFile(GifFile) == GIF_ERROR) |
737 |
+ |
738 |
{ |
739 |
- if (EGifPutLine(outfile, ptr, width) == GIF_ERROR) |
740 |
- { |
741 |
- PrintGifError(); |
742 |
- return(0); |
743 |
- } |
744 |
- ptr += width; |
745 |
+ QuitGifError(GifFile); |
746 |
+ return(0); |
747 |
} |
748 |
|
749 |
- EGifSpew(outfile); |
750 |
- |
751 |
- if (EGifCloseFile(outfile) == GIF_ERROR) |
752 |
- PrintGifError(); |
753 |
- |
754 |
- free(buffer); |
755 |
- |
756 |
return(1); |
757 |
} |