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