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