1 /*
2  * in_gif.cpp -- read a Compuserve GIF file
3  * by pts@fazekas.hu at Fri Mar  1 22:28:46 CET 2002
4  *
5  */
6 
7 /*The creators of the GIF format require the following
8   acknowledgement:
9   The Graphics Interchange Format(c) is the Copyright property of
10   CompuServe Incorporated. GIF(sm) is a Service Mark property of
11   CompuServe Incorporated.
12 */
13 
14 #ifdef __GNUC__
15 #ifndef __clang__
16 #pragma implementation
17 #endif
18 #endif
19 
20 #ifdef USE_GNU_SOURCE_INSTEAD_OF_POSIX_SOURCE
21 #define _GNU_SOURCE 1  /* Implies _POSIX_C_SOURCE and _POSIX_C_SOURCE >= 2. */
22 #else
23 #define _POSIX_SOURCE 1
24 #define _POSIX_C_SOURCE 2
25 #endif
26 
27 #include "config2.h" /* SUXX, ignores features.h */
28 
29 #if USE_IN_GIF
30 
31 #include "cgif.h"
32 #include "cgif.c" /* _POSIX_SOURCE */
33 #include "image.hpp"
34 #include "error.hpp"
35 #include "gensio.hpp"
36 
37 #undef CGIFFF
38 #define CGIFFF CGIF::
39 
in_gif_reader(Image::Loader::UFD * ufd,SimBuffer::Flat const &)40 static Image::Sampled *in_gif_reader(Image::Loader::UFD *ufd, SimBuffer::Flat const&) {
41   Image::Indexed *img;
42   CGIFFF GifFileType *giff;
43   CGIFFF SavedImage *sp;
44   CGIFFF ColorMapObject *cm;
45   char const *err;
46 
47   /* Dat: (CGIFFF GetGifError() || "unknown error") doesn't work like in Perl or Ruby */
48   if (0==(giff=CGIFFF DGifOpenFILE(((Filter::UngetFILED*)ufd)->getFILE(/*seekable:*/false))) || GIF_ERROR==CGIFFF DGifSlurp(giff))
49     Error::sev(Error::EERROR) << "GIF: " << ((err=CGIFFF GetGifError()) ? err : "unknown error") << (Error*)0;
50   if (giff->ImageCount<1)
51     Error::sev(Error::EERROR) << "GIF: no image in file" << (Error*)0;
52 
53   sp=giff->SavedImages+0;
54   cm = (sp->ImageDesc.ColorMap ? sp->ImageDesc.ColorMap : giff->SColorMap);
55   img=new Image::Indexed(sp->ImageDesc.Width, sp->ImageDesc.Height, cm->ColorCount, 8);
56   CGIFFF GifColorType *co=cm->Colors, *ce=co+cm->ColorCount;
57   char *p=img->getHeadp();
58   while (co!=ce) { *p++=(char)co->Red; *p++=(char)co->Green; *p++=(char)co->Blue; co++; }
59   // fprintf(stderr, "transp=%d\n", sp->transp);
60   if (sp->transp!=-1) img->setTransp(sp->transp);
61   /* ^^^ comment out this line to ignore transparency of the GIF file */
62 
63   assert(1L*sp->ImageDesc.Width*sp->ImageDesc.Height<=img->end_()-img->getRowbeg());
64   memcpy(img->getRowbeg(), sp->RasterBits, (slen_t)sp->ImageDesc.Width*sp->ImageDesc.Height);
65 
66   CGIFFF DGifCloseFile(giff); /* also frees memory structure */
67 
68   return img;
69 }
70 
in_gif_checker(char buf[Image::Loader::MAGIC_LEN],char[Image::Loader::MAGIC_LEN],SimBuffer::Flat const &,Image::Loader::UFD *)71 static Image::Loader::reader_t in_gif_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
72   return (0==memcmp(buf,"GIF87a",6) || 0==memcmp(buf,"GIF89a",6)) ? in_gif_reader : 0;
73 }
74 
75 #define in_gif_name "GIF"
76 
77 #else
78 #include <string.h>
79 #include "image.hpp"
80 #include "error.hpp"
81 #define in_gif_name (char const*)NULLP
82 /* #define in_gif_checker (Image::Loader::checker_t)NULLP */
in_gif_checker(char buf[Image::Loader::MAGIC_LEN],char[Image::Loader::MAGIC_LEN],SimBuffer::Flat const &,Image::Loader::UFD *)83 static Image::Loader::reader_t in_gif_checker(char buf[Image::Loader::MAGIC_LEN], char [Image::Loader::MAGIC_LEN], SimBuffer::Flat const&, Image::Loader::UFD*) {
84   if (0==memcmp(buf,"GIF87a",6) || 0==memcmp(buf,"GIF89a",6)) {
85     Error::sev(Error::WARNING) << "loader: please `configure --enable-gif' for loading GIF files" << (Error*)0;
86   }
87   return 0;
88 }
89 #endif /* USE_IN_GIF */
90 
91 Image::Loader in_gif_loader = { in_gif_name, in_gif_checker, 0 };
92