1 #include "loader_common.h"
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <gif_lib.h>
6 
7 int
load2(ImlibImage * im,int load_data)8 load2(ImlibImage * im, int load_data)
9 {
10    static const int    intoffset[] = { 0, 4, 2, 1 };
11    static const int    intjump[] = { 8, 8, 4, 2 };
12    int                 rc;
13    DATA32             *ptr;
14    GifFileType        *gif;
15    GifRowType         *rows;
16    GifRecordType       rec;
17    ColorMapObject     *cmap;
18    int                 i, j, done, bg, r, g, b, w = 0, h = 0;
19    int                 transp;
20    int                 fd;
21    DATA32              colormap[256];
22 
23    fd = dup(fileno(im->fp));
24 
25 #if GIFLIB_MAJOR >= 5
26    gif = DGifOpenFileHandle(fd, NULL);
27 #else
28    gif = DGifOpenFileHandle(fd);
29 #endif
30    if (!gif)
31       return LOAD_FAIL;
32 
33    rc = LOAD_FAIL;
34    done = 0;
35    rows = NULL;
36    transp = -1;
37 
38    do
39      {
40         if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
41           {
42              /* PrintGifError(); */
43              rec = TERMINATE_RECORD_TYPE;
44           }
45 
46         if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
47           {
48              if (DGifGetImageDesc(gif) == GIF_ERROR)
49                {
50                   /* PrintGifError(); */
51                   rec = TERMINATE_RECORD_TYPE;
52                   break;
53                }
54 
55              im->w = w = gif->Image.Width;
56              im->h = h = gif->Image.Height;
57              if (!IMAGE_DIMENSIONS_OK(w, h))
58                 goto quit;
59 
60              rows = calloc(h, sizeof(GifRowType *));
61              if (!rows)
62                 goto quit;
63 
64              for (i = 0; i < h; i++)
65                {
66                   rows[i] = calloc(w, sizeof(GifPixelType));
67                   if (!rows[i])
68                      goto quit;
69                }
70 
71              if (gif->Image.Interlace)
72                {
73                   for (i = 0; i < 4; i++)
74                     {
75                        for (j = intoffset[i]; j < h; j += intjump[i])
76                          {
77                             DGifGetLine(gif, rows[j], w);
78                          }
79                     }
80                }
81              else
82                {
83                   for (i = 0; i < h; i++)
84                     {
85                        DGifGetLine(gif, rows[i], w);
86                     }
87                }
88              done = 1;
89           }
90         else if (rec == EXTENSION_RECORD_TYPE)
91           {
92              int                 ext_code;
93              GifByteType        *ext;
94 
95              ext = NULL;
96              DGifGetExtension(gif, &ext_code, &ext);
97              while (ext)
98                {
99                   if ((ext_code == 0xf9) && (ext[1] & 1) && (transp < 0))
100                     {
101                        transp = (int)ext[4];
102                     }
103                   ext = NULL;
104                   DGifGetExtensionNext(gif, &ext);
105                }
106           }
107      }
108    while (rec != TERMINATE_RECORD_TYPE);
109 
110    if (transp >= 0)
111       SET_FLAG(im->flags, F_HAS_ALPHA);
112    else
113       UNSET_FLAG(im->flags, F_HAS_ALPHA);
114 
115    if (!rows)
116       goto quit;
117 
118    if (!load_data)
119      {
120         rc = LOAD_SUCCESS;
121         goto quit;
122      }
123 
124    /* Load data */
125 
126    bg = gif->SBackGroundColor;
127    cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
128    memset(colormap, 0, sizeof(colormap));
129    if (cmap != NULL)
130      {
131         for (i = cmap->ColorCount > 256 ? 256 : cmap->ColorCount; i-- > 0;)
132           {
133              r = cmap->Colors[i].Red;
134              g = cmap->Colors[i].Green;
135              b = cmap->Colors[i].Blue;
136              colormap[i] = PIXEL_ARGB(0xff, r, g, b);
137           }
138         /* if bg > cmap->ColorCount, it is transparent black already */
139         if (transp >= 0 && transp < 256)
140            colormap[transp] = bg >= 0 && bg < 256 ?
141               colormap[bg] & 0x00ffffff : 0x00000000;
142      }
143 
144    ptr = __imlib_AllocateData(im);
145    if (!ptr)
146       goto quit;
147 
148    for (i = 0; i < h; i++)
149      {
150         for (j = 0; j < w; j++)
151           {
152              *ptr++ = colormap[rows[i][j]];
153           }
154 
155         if (im->lc && __imlib_LoadProgressRows(im, i, 1))
156           {
157              rc = LOAD_BREAK;
158              goto quit;
159           }
160      }
161 
162    rc = LOAD_SUCCESS;
163 
164  quit:
165    if (rows)
166      {
167         for (i = 0; i < h; i++)
168            free(rows[i]);
169         free(rows);
170      }
171 
172 #if GIFLIB_MAJOR > 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1)
173    DGifCloseFile(gif, NULL);
174 #else
175    DGifCloseFile(gif);
176 #endif
177 
178    if (rc <= 0)
179       __imlib_FreeData(im);
180 
181    return rc;
182 }
183 
184 void
formats(ImlibLoader * l)185 formats(ImlibLoader * l)
186 {
187    static const char  *const list_formats[] = { "gif" };
188    __imlib_LoaderSetFormats(l, list_formats,
189                             sizeof(list_formats) / sizeof(char *));
190 }
191