1 /*
2
3 rl2gif -- GIF related functions
4
5 version 0.1, 2013 April 5
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 -----------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2013
28 the Initial Developer. All Rights Reserved.
29
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41
42 */
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47
48 #include <gif_lib.h>
49
50 #include "config.h"
51
52 #ifdef LOADABLE_EXTENSION
53 #include "rasterlite2/sqlite.h"
54 #endif
55
56 #include "rasterlite2/rasterlite2.h"
57 #include "rasterlite2_private.h"
58
59 struct gif_memory_buffer
60 {
61 unsigned char *buffer;
62 size_t size;
63 size_t off;
64 };
65
66 static int
readGif(GifFileType * gif,GifByteType * buf,int len)67 readGif (GifFileType * gif, GifByteType * buf, int len)
68 {
69 struct gif_memory_buffer *p = gif->UserData;
70 size_t rd = len;
71 if (p->off + len > p->size)
72 rd = p->size - p->off;
73 if (rd != 0)
74 {
75 /* copy bytes into buffer */
76 memcpy (buf, p->buffer + p->off, rd);
77 p->off += rd;
78 }
79 return rd;
80 }
81
82 static int
writeGif(GifFileType * gif,const GifByteType * buf,int len)83 writeGif (GifFileType * gif, const GifByteType * buf, int len)
84 {
85 struct gif_memory_buffer *p = gif->UserData;
86 size_t nsize = p->size + len;
87
88 /* allocate or grow buffer */
89 if (p->buffer)
90 p->buffer = realloc (p->buffer, nsize);
91 else
92 p->buffer = malloc (nsize);
93
94 if (!p->buffer)
95 return 0;
96
97 /* copy new bytes to end of buffer */
98 memcpy (p->buffer + p->size, buf, len);
99 p->size += len;
100 return len;
101 }
102
103 static void
print_gif_error(int ErrorCode)104 print_gif_error (int ErrorCode)
105 {
106 const char *Err = NULL;
107 #ifdef GIFLIB_MAJOR
108 Err = GifErrorString (ErrorCode);
109 #endif
110 if (Err != NULL)
111 fprintf (stderr, "GIF error: %d \"%s\"\n", ErrorCode, Err);
112 else
113 fprintf (stderr, "GIF error: %d\n", ErrorCode);
114 }
115
116 static int
check_gif_compatibility(unsigned char sample_type,unsigned char pixel_type,unsigned char num_bands)117 check_gif_compatibility (unsigned char sample_type, unsigned char pixel_type,
118 unsigned char num_bands)
119 {
120 /* checks for GIF compatibility */
121 switch (sample_type)
122 {
123 case RL2_SAMPLE_1_BIT:
124 case RL2_SAMPLE_2_BIT:
125 case RL2_SAMPLE_4_BIT:
126 case RL2_SAMPLE_UINT8:
127 break;
128 default:
129 return RL2_ERROR;
130 };
131 switch (pixel_type)
132 {
133 case RL2_PIXEL_MONOCHROME:
134 case RL2_PIXEL_PALETTE:
135 case RL2_PIXEL_GRAYSCALE:
136 break;
137 default:
138 return RL2_ERROR;
139 };
140 if (num_bands != 1)
141 return RL2_ERROR;
142 if (pixel_type == RL2_PIXEL_MONOCHROME)
143 {
144 switch (sample_type)
145 {
146 case RL2_SAMPLE_1_BIT:
147 break;
148 default:
149 return RL2_ERROR;
150 };
151 }
152 if (pixel_type == RL2_PIXEL_PALETTE)
153 {
154 switch (sample_type)
155 {
156 case RL2_SAMPLE_1_BIT:
157 case RL2_SAMPLE_2_BIT:
158 case RL2_SAMPLE_4_BIT:
159 case RL2_SAMPLE_UINT8:
160 break;
161 default:
162 return RL2_ERROR;
163 };
164 }
165 if (pixel_type == RL2_PIXEL_GRAYSCALE)
166 {
167 switch (sample_type)
168 {
169 case RL2_SAMPLE_2_BIT:
170 case RL2_SAMPLE_4_BIT:
171 case RL2_SAMPLE_UINT8:
172 break;
173 default:
174 return RL2_ERROR;
175 };
176 }
177 return RL2_OK;
178 }
179
180 static int
compress_gif(rl2RasterPtr rst,unsigned char ** gif,int * gif_size)181 compress_gif (rl2RasterPtr rst, unsigned char **gif, int *gif_size)
182 {
183 /* attempting to create a GIF compressed image */
184 rl2PrivRasterPtr raster = (rl2PrivRasterPtr) rst;
185 rl2PalettePtr plt;
186 unsigned char sample_type;
187 unsigned char pixel_type;
188 unsigned char num_samples;
189 unsigned char *blob;
190 int blob_size;
191 if (rst == NULL)
192 return RL2_ERROR;
193 if (rl2_get_raster_type (rst, &sample_type, &pixel_type, &num_samples) !=
194 RL2_OK)
195 return RL2_ERROR;
196 if (check_gif_compatibility (sample_type, pixel_type, num_samples) !=
197 RL2_OK)
198 return RL2_ERROR;
199 plt = rl2_get_raster_palette (rst);
200 if (rl2_data_to_gif
201 (raster->rasterBuffer, plt, raster->width,
202 raster->height, sample_type, pixel_type, &blob, &blob_size) != RL2_OK)
203 return RL2_ERROR;
204 *gif = blob;
205 *gif_size = blob_size;
206 return RL2_OK;
207 }
208
209 RL2_PRIVATE int
rl2_data_to_gif(const unsigned char * pixels,rl2PalettePtr plt,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char ** gif,int * gif_size)210 rl2_data_to_gif (const unsigned char *pixels, rl2PalettePtr plt,
211 unsigned int width, unsigned int height,
212 unsigned char sample_type, unsigned char pixel_type,
213 unsigned char **gif, int *gif_size)
214 {
215 /* attempting to create a GIF compressed image */
216 struct gif_memory_buffer membuf;
217 GifPixelType *ScanLine = NULL;
218 GifFileType *GifFile = NULL;
219 #ifdef GIFLIB_MAJOR
220 int ErrorCode;
221 #endif
222 ColorMapObject *ColorMap = NULL;
223 int i;
224 unsigned int row;
225 unsigned int col;
226 const unsigned char *p_data;
227 rl2PrivPalettePtr palette = (rl2PrivPalettePtr) plt;
228 int max_palette;
229
230 *gif = NULL;
231 *gif_size = 0;
232 membuf.buffer = NULL;
233 membuf.size = 0;
234 membuf.off = 0;
235
236 /* allocating the GIF scanline */
237 if ((ScanLine =
238 (GifPixelType *) malloc (sizeof (GifPixelType) * width)) == NULL)
239 {
240 fprintf (stderr, "Failed to allocate GIF scan line, aborted.\n");
241 return RL2_ERROR;
242 }
243
244 /* opening the GIF */
245 #ifdef GIFLIB_MAJOR
246 GifFile = EGifOpen (&membuf, writeGif, &ErrorCode);
247 #else
248 GifFile = EGifOpen (&membuf, writeGif);
249 #endif
250 if (GifFile == NULL)
251 {
252 #ifdef GIFLIB_MAJOR
253 print_gif_error (ErrorCode);
254 #else
255 print_gif_error (GifLastError ());
256 #endif
257 goto error;
258 }
259
260 /* preparing a GIF Palette object */
261 switch (pixel_type)
262 {
263 case RL2_PIXEL_MONOCHROME:
264 #ifdef GIFLIB_MAJOR
265 ColorMap = GifMakeMapObject (2, NULL);
266 #else
267 ColorMap = MakeMapObject (2, NULL);
268 #endif
269 if (ColorMap == NULL)
270 goto error;
271 ColorMap->BitsPerPixel = 1;
272 ColorMap->Colors[0].Red = 255;
273 ColorMap->Colors[0].Green = 255;
274 ColorMap->Colors[0].Blue = 255;
275 ColorMap->Colors[1].Red = 0;
276 ColorMap->Colors[1].Green = 0;
277 ColorMap->Colors[1].Blue = 0;
278 break;
279 case RL2_PIXEL_GRAYSCALE:
280 switch (sample_type)
281 {
282 case RL2_SAMPLE_2_BIT:
283 #ifdef GIFLIB_MAJOR
284 ColorMap = GifMakeMapObject (4, NULL);
285 #else
286 ColorMap = MakeMapObject (4, NULL);
287 #endif
288 if (ColorMap == NULL)
289 goto error;
290 ColorMap->Colors[0].Red = 0;
291 ColorMap->Colors[0].Green = 0;
292 ColorMap->Colors[0].Blue = 0;
293 ColorMap->Colors[1].Red = 86;
294 ColorMap->Colors[1].Green = 86;
295 ColorMap->Colors[1].Blue = 86;
296 ColorMap->Colors[2].Red = 170;
297 ColorMap->Colors[2].Green = 170;
298 ColorMap->Colors[2].Blue = 170;
299 ColorMap->Colors[3].Red = 255;
300 ColorMap->Colors[3].Green = 255;
301 ColorMap->Colors[3].Blue = 255;
302 break;
303 case RL2_SAMPLE_4_BIT:
304 #ifdef GIFLIB_MAJOR
305 ColorMap = GifMakeMapObject (16, NULL);
306 #else
307 ColorMap = MakeMapObject (16, NULL);
308 #endif
309 if (ColorMap == NULL)
310 goto error;
311 ColorMap->Colors[0].Red = 0;
312 ColorMap->Colors[0].Green = 0;
313 ColorMap->Colors[0].Blue = 0;
314 ColorMap->Colors[1].Red = 17;
315 ColorMap->Colors[1].Green = 17;
316 ColorMap->Colors[1].Blue = 17;
317 ColorMap->Colors[2].Red = 34;
318 ColorMap->Colors[2].Green = 34;
319 ColorMap->Colors[2].Blue = 34;
320 ColorMap->Colors[3].Red = 51;
321 ColorMap->Colors[3].Green = 51;
322 ColorMap->Colors[3].Blue = 51;
323 ColorMap->Colors[4].Red = 68;
324 ColorMap->Colors[4].Green = 68;
325 ColorMap->Colors[4].Blue = 68;
326 ColorMap->Colors[5].Red = 85;
327 ColorMap->Colors[5].Green = 85;
328 ColorMap->Colors[5].Blue = 85;
329 ColorMap->Colors[6].Red = 102;
330 ColorMap->Colors[6].Green = 102;
331 ColorMap->Colors[6].Blue = 102;
332 ColorMap->Colors[7].Red = 119;
333 ColorMap->Colors[7].Green = 119;
334 ColorMap->Colors[7].Blue = 119;
335 ColorMap->Colors[8].Red = 137;
336 ColorMap->Colors[8].Green = 137;
337 ColorMap->Colors[8].Blue = 137;
338 ColorMap->Colors[9].Red = 154;
339 ColorMap->Colors[9].Green = 154;
340 ColorMap->Colors[9].Blue = 154;
341 ColorMap->Colors[10].Red = 171;
342 ColorMap->Colors[10].Green = 171;
343 ColorMap->Colors[10].Blue = 171;
344 ColorMap->Colors[11].Red = 188;
345 ColorMap->Colors[11].Green = 188;
346 ColorMap->Colors[11].Blue = 188;
347 ColorMap->Colors[12].Red = 205;
348 ColorMap->Colors[12].Green = 205;
349 ColorMap->Colors[12].Blue = 205;
350 ColorMap->Colors[13].Red = 222;
351 ColorMap->Colors[13].Green = 222;
352 ColorMap->Colors[13].Blue = 222;
353 ColorMap->Colors[14].Red = 239;
354 ColorMap->Colors[14].Green = 239;
355 ColorMap->Colors[14].Blue = 239;
356 ColorMap->Colors[15].Red = 255;
357 ColorMap->Colors[15].Green = 255;
358 ColorMap->Colors[15].Blue = 255;
359 break;
360 case RL2_SAMPLE_UINT8:
361 #ifdef GIFLIB_MAJOR
362 ColorMap = GifMakeMapObject (256, NULL);
363 #else
364 ColorMap = MakeMapObject (256, NULL);
365 #endif
366 if (ColorMap == NULL)
367 goto error;
368 for (i = 0; i < 256; i++)
369 {
370 ColorMap->Colors[i].Red = i;
371 ColorMap->Colors[i].Green = i;
372 ColorMap->Colors[i].Blue = i;
373 }
374 break;
375 };
376 break;
377 case RL2_PIXEL_PALETTE:
378 if (palette == NULL)
379 goto error;
380 /* a GIF palette should must containt a power of 2 #entries */
381 if (palette->nEntries <= 2)
382 max_palette = 2;
383 else if (palette->nEntries <= 4)
384 max_palette = 4;
385 else if (palette->nEntries <= 8)
386 max_palette = 8;
387 else if (palette->nEntries <= 16)
388 max_palette = 16;
389 else if (palette->nEntries <= 32)
390 max_palette = 32;
391 else if (palette->nEntries <= 64)
392 max_palette = 64;
393 else if (palette->nEntries <= 128)
394 max_palette = 128;
395 else
396 max_palette = 256;
397 #ifdef GIFLIB_MAJOR
398 ColorMap = GifMakeMapObject (max_palette, NULL);
399 #else
400 ColorMap = MakeMapObject (max_palette, NULL);
401 #endif
402 if (ColorMap == NULL)
403 goto error;
404 for (i = 0; i < max_palette; i++)
405 {
406 /* filling the palette with the latest entry */
407 rl2PrivPaletteEntryPtr entry =
408 palette->entries + (palette->nEntries - 1);
409 ColorMap->Colors[i].Red = entry->red;
410 ColorMap->Colors[i].Green = entry->green;
411 ColorMap->Colors[i].Blue = entry->blue;
412 }
413 for (i = 0; i < palette->nEntries; i++)
414 {
415 /* effective palette entries */
416 rl2PrivPaletteEntryPtr entry = palette->entries + i;
417 ColorMap->Colors[i].Red = entry->red;
418 ColorMap->Colors[i].Green = entry->green;
419 ColorMap->Colors[i].Blue = entry->blue;
420 }
421 break;
422 };
423
424 /* GIF headers */
425 if (EGifPutScreenDesc
426 (GifFile, width, height, ColorMap->BitsPerPixel, 0,
427 ColorMap) == GIF_ERROR)
428 {
429 #ifdef GIFLIB_MAJOR
430 print_gif_error (ErrorCode);
431 #else
432 print_gif_error (GifLastError ());
433 #endif
434 goto error;
435 }
436 if (EGifPutImageDesc (GifFile, 0, 0, width, height, 0, NULL) == GIF_ERROR)
437 {
438 #ifdef GIFLIB_MAJOR
439 print_gif_error (ErrorCode);
440 #else
441 print_gif_error (GifLastError ());
442 #endif
443 goto error;
444 }
445
446 /* compressing GIF pixels */
447 p_data = pixels;
448 for (row = 0; row < height; row++)
449 {
450 for (col = 0; col < width; col++)
451 ScanLine[col] = *p_data++;
452 if (EGifPutLine (GifFile, ScanLine, width) == GIF_ERROR)
453 {
454 #ifdef GIFLIB_MAJOR
455 print_gif_error (ErrorCode);
456 #else
457 print_gif_error (GifLastError ());
458 #endif
459 goto error;
460 }
461 }
462
463 /* closing the GIF */
464 #if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
465 if (EGifCloseFile (GifFile, NULL) == GIF_ERROR)
466 #else
467 if (EGifCloseFile (GifFile) == GIF_ERROR)
468 #endif
469 {
470 #ifdef GIFLIB_MAJOR
471 print_gif_error (ErrorCode);
472 #else
473 print_gif_error (GifLastError ());
474 #endif
475 goto error;
476 }
477
478 free (ScanLine);
479 #ifdef GIFLIB_MAJOR
480 GifFreeMapObject (ColorMap);
481 #else
482 FreeMapObject (ColorMap);
483 #endif
484 *gif = membuf.buffer;
485 *gif_size = membuf.size;
486 return RL2_OK;
487 error:
488 if (GifFile != NULL)
489 #if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
490 EGifCloseFile (GifFile, NULL);
491 #else
492 EGifCloseFile (GifFile);
493 #endif
494 if (ScanLine != NULL)
495 free (ScanLine);
496 if (ColorMap != NULL)
497 {
498 #ifdef GIFLIB_MAJOR
499 GifFreeMapObject (ColorMap);
500 #else
501 FreeMapObject (ColorMap);
502 #endif
503 }
504 if (membuf.buffer != NULL)
505 free (membuf.buffer);
506 return RL2_ERROR;
507 }
508
509 RL2_DECLARE int
rl2_section_to_gif(rl2SectionPtr scn,const char * path)510 rl2_section_to_gif (rl2SectionPtr scn, const char *path)
511 {
512 /* attempting to save a raster section into a GIF file */
513 int blob_size;
514 unsigned char *blob;
515 rl2RasterPtr rst;
516 int ret;
517
518 if (scn == NULL)
519 return RL2_ERROR;
520 rst = rl2_get_section_raster (scn);
521 if (rst == NULL)
522 return RL2_ERROR;
523 /* attempting to export as a GIF image */
524 if (rl2_raster_to_gif (rst, &blob, &blob_size) != RL2_OK)
525 return RL2_ERROR;
526 ret = rl2_blob_to_file (path, blob, blob_size);
527 free (blob);
528 if (ret != RL2_OK)
529 return RL2_ERROR;
530 return RL2_OK;
531 }
532
533 RL2_DECLARE int
rl2_raster_to_gif(rl2RasterPtr rst,unsigned char ** gif,int * gif_size)534 rl2_raster_to_gif (rl2RasterPtr rst, unsigned char **gif, int *gif_size)
535 {
536 /* creating a GIF image from a raster */
537 unsigned char *blob;
538 int blob_size;
539
540 if (rst == NULL)
541 return RL2_ERROR;
542
543 if (compress_gif (rst, &blob, &blob_size) != RL2_OK)
544 return RL2_ERROR;
545 *gif = blob;
546 *gif_size = blob_size;
547 return RL2_OK;
548 }
549
550 RL2_DECLARE rl2SectionPtr
rl2_section_from_gif(const char * path)551 rl2_section_from_gif (const char *path)
552 {
553 /* attempting to create a raster section from a GIF file */
554 int blob_size;
555 unsigned char *blob;
556 rl2SectionPtr scn;
557 rl2RasterPtr rst;
558
559 /* attempting to create a raster */
560 if (rl2_blob_from_file (path, &blob, &blob_size) != RL2_OK)
561 return NULL;
562 rst = rl2_raster_from_gif (blob, blob_size);
563 free (blob);
564 if (rst == NULL)
565 return NULL;
566
567 /* creating the raster section */
568 scn =
569 rl2_create_section (path, RL2_COMPRESSION_GIF, RL2_TILESIZE_UNDEFINED,
570 RL2_TILESIZE_UNDEFINED, rst);
571 return scn;
572 }
573
574 RL2_DECLARE rl2RasterPtr
rl2_raster_from_gif(const unsigned char * gif,int gif_size)575 rl2_raster_from_gif (const unsigned char *gif, int gif_size)
576 {
577 /* attempting to create a raster from a GIF image */
578 rl2RasterPtr rst = NULL;
579 unsigned int width;
580 unsigned int height;
581 unsigned char sample_type;
582 unsigned char pixel_type;
583 unsigned char *data = NULL;
584 int data_size;
585 rl2PalettePtr palette = NULL;
586
587 if (rl2_decode_gif
588 (gif, gif_size, &width, &height, &sample_type, &pixel_type, &data,
589 &data_size, &palette) != RL2_OK)
590 goto error;
591 rst =
592 rl2_create_raster (width, height, sample_type, pixel_type, 1, data,
593 data_size, palette, NULL, 0, NULL);
594 if (rst == NULL)
595 goto error;
596 return rst;
597
598 error:
599 if (data != NULL)
600 free (data);
601 if (palette != NULL)
602 rl2_destroy_palette (palette);
603 return NULL;
604 }
605
606 RL2_PRIVATE int
rl2_decode_gif(const unsigned char * gif,int gif_size,unsigned int * xwidth,unsigned int * xheight,unsigned char * xsample_type,unsigned char * xpixel_type,unsigned char ** blob,int * blob_sz,rl2PalettePtr * palette)607 rl2_decode_gif (const unsigned char *gif, int gif_size, unsigned int *xwidth,
608 unsigned int *xheight, unsigned char *xsample_type,
609 unsigned char *xpixel_type, unsigned char **blob, int *blob_sz,
610 rl2PalettePtr * palette)
611 {
612 /* attempting to create a raster from a GIF image - raw block */
613 struct gif_memory_buffer membuf;
614 #ifdef GIFLIB_MAJOR
615 int ErrorCode;
616 #endif
617 GifFileType *GifFile = NULL;
618 GifPixelType *Line;
619 GifRecordType RecordType;
620 GifByteType *Extension;
621 ColorMapObject *ColorMap;
622 int ExtCode;
623 unsigned int width;
624 unsigned int height;
625 int row;
626 int col;
627 int i;
628 unsigned char sample_type = RL2_SAMPLE_UNKNOWN;
629 unsigned char pixel_type = RL2_PIXEL_PALETTE;
630 unsigned char sample_typ;
631 unsigned char pixel_typ;
632 rl2PalettePtr rl_palette = NULL;
633 int nPalette = 0;
634 unsigned char *data = NULL;
635 unsigned char *p_data;
636 int data_size;
637 int already_done = 0;
638 unsigned char red[256];
639 unsigned char green[256];
640 unsigned char blue[256];
641
642 membuf.buffer = (unsigned char *) gif;
643 membuf.size = gif_size;
644 membuf.off = 0;
645
646 /* opening the GIF */
647 #ifdef GIFLIB_MAJOR
648 GifFile = DGifOpen (&membuf, readGif, &ErrorCode);
649 #else
650 GifFile = DGifOpen (&membuf, readGif);
651 #endif
652 if (GifFile == NULL)
653 {
654 #ifdef GIFLIB_MAJOR
655 print_gif_error (ErrorCode);
656 #else
657 print_gif_error (GifLastError ());
658 #endif
659 return RL2_ERROR;
660 }
661
662 do
663 {
664 /* looping on GIF chunks */
665 if (DGifGetRecordType (GifFile, &RecordType) == GIF_ERROR)
666 {
667 #ifdef GIFLIB_MAJOR
668 print_gif_error (GifFile->Error);
669 #else
670 print_gif_error (GifLastError ());
671 #endif
672 goto error;
673 }
674 switch (RecordType)
675 {
676 case IMAGE_DESC_RECORD_TYPE:
677 /* we have a valid image */
678 if (DGifGetImageDesc (GifFile) == GIF_ERROR)
679 {
680 #ifdef GIFLIB_MAJOR
681 print_gif_error (GifFile->Error);
682 #else
683 print_gif_error (GifLastError ());
684 #endif
685 goto error;
686 }
687 if (already_done)
688 {
689 /* if multiple images are found, simply the first one will be imported */
690 break;
691 }
692 /* width and height */
693 width = GifFile->Image.Width;
694 height = GifFile->Image.Height;
695 ColorMap = GifFile->SColorMap;
696 if (ColorMap->BitsPerPixel == 1)
697 sample_type = RL2_SAMPLE_1_BIT;
698 else if (ColorMap->BitsPerPixel == 2)
699 sample_type = RL2_SAMPLE_2_BIT;
700 else if (ColorMap->BitsPerPixel <= 4)
701 sample_type = RL2_SAMPLE_4_BIT;
702 else
703 sample_type = RL2_SAMPLE_UINT8;
704 /* palette */
705 ColorMap = GifFile->SColorMap;
706 if (ColorMap == NULL)
707 goto error;
708 nPalette = ColorMap->ColorCount;
709 rl_palette = rl2_create_palette (nPalette);
710 if (rl_palette == NULL)
711 goto error;
712 for (i = 0; i < nPalette; i++)
713 {
714 red[i] = ColorMap->Colors[i].Red;
715 green[i] = ColorMap->Colors[i].Green;
716 blue[i] = ColorMap->Colors[i].Blue;
717 }
718 /* creating the raster data */
719 data_size = width * height;
720 data = malloc (data_size);
721 if (data == NULL)
722 goto error;
723 p_data = data;
724 Line = (GifPixelType *) malloc (GifFile->Image.Width *
725 sizeof (GifPixelType));
726 for (row = 0; row < GifFile->Image.Height; row++)
727 {
728 if (DGifGetLine (GifFile, Line, GifFile->Image.Width)
729 == GIF_ERROR)
730 {
731 #ifdef GIFLIB_MAJOR
732 print_gif_error (GifFile->Error);
733 #else
734 print_gif_error (GifLastError ());
735 #endif
736 fprintf (stderr, "err GIF %d / %d %d\n", row,
737 GifFile->Image.Height,
738 GifFile->Image.Width);
739 goto error;
740 }
741 for (col = 0; col < GifFile->Image.Width; col++)
742 *p_data++ = Line[col];
743 }
744 free (Line);
745 /* exporting data to be returned */
746 already_done = 1;
747 break;
748 case EXTENSION_RECORD_TYPE:
749 if (DGifGetExtension (GifFile, &ExtCode, &Extension) ==
750 GIF_ERROR)
751 {
752 #ifdef GIFLIB_MAJOR
753 print_gif_error (GifFile->Error);
754 #else
755 print_gif_error (GifLastError ());
756 #endif
757 goto error;
758 }
759 for (;;)
760 {
761 if (DGifGetExtensionNext (GifFile, &Extension) ==
762 GIF_ERROR)
763 {
764 #ifdef GIFLIB_MAJOR
765 print_gif_error (GifFile->Error);
766 #else
767 print_gif_error (GifLastError ());
768 #endif
769 goto error;
770 }
771 if (Extension == NULL)
772 break;
773 }
774 break;
775 case TERMINATE_RECORD_TYPE:
776 break;
777 default: /* Should be trapped by DGifGetRecordType */
778 break;
779 }
780 }
781 while (RecordType != TERMINATE_RECORD_TYPE);
782
783 /* closing the GIF */
784 #if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
785 if (DGifCloseFile (GifFile, NULL) == GIF_ERROR)
786 #else
787 if (DGifCloseFile (GifFile) == GIF_ERROR)
788 #endif
789 {
790 #ifdef GIFLIB_MAJOR
791 print_gif_error (GifFile->Error);
792 #else
793 print_gif_error (GifLastError ());
794 #endif
795 goto error;
796 }
797 if (already_done)
798 {
799 for (i = 0; i < nPalette; i++)
800 rl2_set_palette_color (rl_palette, i, red[i], green[i], blue[i]);
801 if (rl2_get_palette_type (rl_palette, &sample_typ, &pixel_typ) !=
802 RL2_OK)
803 goto error;
804 *xwidth = width;
805 *xheight = height;
806 *xsample_type = sample_type;
807 *xpixel_type = pixel_type;
808 if (sample_type == sample_typ)
809 *xpixel_type = pixel_typ;
810 *blob = data;
811 *blob_sz = data_size;
812 *palette = rl_palette;
813 return RL2_OK;
814 }
815 error:
816 if (GifFile != NULL)
817 #if GIFLIB_MAJOR >= 5 && GIFLIB_MINOR >= 1
818 DGifCloseFile (GifFile, NULL);
819 #else
820 DGifCloseFile (GifFile);
821 #endif
822 if (rl_palette != NULL)
823 rl2_destroy_palette (rl_palette);
824 if (data != NULL)
825 free (data);
826 *palette = NULL;
827 return RL2_ERROR;
828 }
829