move around - flatter.
[profile/ivi/evas.git] / src / modules / loaders / gif / evas_image_load_gif.c
1 #include "evas_common.h"
2 #include "evas_private.h"
3
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <fcntl.h>
7
8 #include <gif_lib.h>
9
10
11 int evas_image_load_file_head_gif(Image_Entry *ie, const char *file, const char *key);
12 int evas_image_load_file_data_gif(Image_Entry *ie, const char *file, const char *key);
13
14 Evas_Image_Load_Func evas_image_load_gif_func =
15 {
16   evas_image_load_file_head_gif,
17   evas_image_load_file_data_gif
18 };
19
20
21 int
22 evas_image_load_file_head_gif(Image_Entry *ie, const char *file, const char *key)
23 {
24    int                 fd;
25    GifFileType        *gif;
26    GifRecordType       rec;
27    int                 done;
28    int                 w;
29    int                 h;
30    int                 alpha;
31
32    done = 0;
33    w = 0;
34    h = 0;
35    alpha = -1;
36
37    if (!file) return 0;
38
39 #ifndef __EMX__
40    fd = open(file, O_RDONLY);
41 #else
42    fd = open(file, O_RDONLY | O_BINARY);
43 #endif
44    if (fd < 0)
45       return 0;
46
47    gif = DGifOpenFileHandle(fd);
48    if (!gif)
49      {
50         close(fd);
51         return 0;
52      }
53
54    do
55      {
56         if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
57           {
58              /* PrintGifError(); */
59              rec = TERMINATE_RECORD_TYPE;
60           }
61         if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
62           {
63              if (DGifGetImageDesc(gif) == GIF_ERROR)
64                {
65                   /* PrintGifError(); */
66                   rec = TERMINATE_RECORD_TYPE;
67                }
68              w = gif->Image.Width;
69              h = gif->Image.Height;
70              if ((w < 1) || (h < 1) || (w > 8192) || (h > 8192))
71                {
72                   DGifCloseFile(gif);
73                   return 0;
74                }
75              done = 1;
76           }
77         else if (rec == EXTENSION_RECORD_TYPE)
78           {
79              int                 ext_code;
80              GifByteType        *ext;
81              
82              ext = NULL;
83              DGifGetExtension(gif, &ext_code, &ext);
84              while (ext)
85                {
86                   if ((ext_code == 0xf9) && (ext[1] & 1) && (alpha < 0))
87                     {
88                        alpha = (int)ext[4];
89                     }
90                   ext = NULL;
91                   DGifGetExtensionNext(gif, &ext);
92                }
93           }
94    } while (rec != TERMINATE_RECORD_TYPE);
95
96    if (alpha >= 0) ie->flags.alpha = 1;
97    ie->w = w;
98    ie->h = h;
99
100    DGifCloseFile(gif);
101    return 1;
102 }
103
104 int
105 evas_image_load_file_data_gif(Image_Entry *ie, const char *file, const char *key)
106 {
107    int                 intoffset[] = { 0, 4, 2, 1 };
108    int                 intjump[] = { 8, 8, 4, 2 };
109    double              per;
110    double              per_inc;
111    int                 fd;
112    GifFileType        *gif;
113    GifRecordType       rec;
114    GifRowType         *rows;
115    ColorMapObject     *cmap;
116    DATA32             *ptr;
117    int                 done;
118    int                 last_y;
119    int                 last_per;
120    int                 w;
121    int                 h;
122    int                 alpha;
123    int                 i;
124    int                 j;
125    int                 bg;
126    int                 r;
127    int                 g;
128    int                 b;
129
130    rows = NULL;
131    per = 0.0;
132    done = 0;
133    last_y = 0;
134    last_per = 0;
135    w = 0;
136    h = 0;
137    alpha = -1;
138
139    if (!file) return 0;
140
141 #ifndef __EMX__
142    fd = open(file, O_RDONLY);
143 #else
144    fd = open(file, O_RDONLY | O_BINARY);
145 #endif
146    if (fd < 0)
147       return 0;
148
149    gif = DGifOpenFileHandle(fd);
150    if (!gif)
151      {
152         close(fd);
153         return 0;
154      }
155    do
156      {
157         if (DGifGetRecordType(gif, &rec) == GIF_ERROR)
158           {
159              /* PrintGifError(); */
160              rec = TERMINATE_RECORD_TYPE;
161           }
162         if ((rec == IMAGE_DESC_RECORD_TYPE) && (!done))
163           {
164              if (DGifGetImageDesc(gif) == GIF_ERROR)
165                {
166                   /* PrintGifError(); */
167                   rec = TERMINATE_RECORD_TYPE;
168                }
169              w = gif->Image.Width;
170              h = gif->Image.Height;
171              rows = malloc(h * sizeof(GifRowType *));
172              if (!rows)
173                {
174                   DGifCloseFile(gif);
175                   return 0;
176                }
177              for (i = 0; i < h; i++)
178                {
179                   rows[i] = NULL;
180                }
181              for (i = 0; i < h; i++)
182                {
183                   rows[i] = malloc(w * sizeof(GifPixelType));
184                   if (!rows[i])
185                     {
186                        DGifCloseFile(gif);
187                        for (i = 0; i < h; i++)
188                          {
189                             if (rows[i])
190                               {
191                                  free(rows[i]);
192                               }
193                          }
194                        free(rows);
195                        return 0;
196                     }
197                }
198              if (gif->Image.Interlace)
199                {
200                   for (i = 0; i < 4; i++)
201                     {
202                        for (j = intoffset[i]; j < h; j += intjump[i])
203                          {
204                             DGifGetLine(gif, rows[j], w);
205                          }
206                     }
207                }
208              else
209                {
210                   for (i = 0; i < h; i++)
211                     {
212                        DGifGetLine(gif, rows[i], w);
213                     }
214                }
215              done = 1;
216           }
217         else if (rec == EXTENSION_RECORD_TYPE)
218           {
219              int                 ext_code;
220              GifByteType        *ext;
221
222              ext = NULL;
223              DGifGetExtension(gif, &ext_code, &ext);
224              while (ext)
225                {
226                   if ((ext_code == 0xf9) && (ext[1] & 1) && (alpha < 0))
227                     {
228                        alpha = (int)ext[4];
229                     }
230                   ext = NULL;
231                   DGifGetExtensionNext(gif, &ext);
232                }
233           }
234    } while (rec != TERMINATE_RECORD_TYPE);
235
236    if (alpha >= 0) ie->flags.alpha = 1;
237    evas_cache_image_surface_alloc(ie, w, h);
238    if (!evas_cache_image_pixels(ie))
239      {
240         DGifCloseFile(gif);
241         for (i = 0; i < h; i++)
242           {
243             free(rows[i]);
244           }
245         free(rows);
246         return 0;
247      }
248
249    bg = gif->SBackGroundColor;
250    cmap = (gif->Image.ColorMap ? gif->Image.ColorMap : gif->SColorMap);
251
252    ptr = evas_cache_image_pixels(ie);
253    per_inc = 100.0 / (((double)w) * h);
254
255    for (i = 0; i < h; i++)
256      {
257        for (j = 0; j < w; j++)
258          {
259            if (rows[i][j] == alpha)
260              {
261                r = cmap->Colors[bg].Red;
262                g = cmap->Colors[bg].Green;
263                b = cmap->Colors[bg].Blue;
264                *ptr++ = 0x00ffffff & ((r << 16) | (g << 8) | b);
265              }
266            else
267              {
268                r = cmap->Colors[rows[i][j]].Red;
269                g = cmap->Colors[rows[i][j]].Green;
270                b = cmap->Colors[rows[i][j]].Blue;
271                *ptr++ = (0xff << 24) | (r << 16) | (g << 8) | b;
272              }
273            per += per_inc;
274          }
275      }
276    evas_common_image_premul(ie);
277    DGifCloseFile(gif);
278    for (i = 0; i < h; i++)
279      {
280         free(rows[i]);
281      }
282    free(rows);
283
284    return 1;
285 }
286
287 EAPI int
288 module_open(Evas_Module *em)
289 {
290    if (!em) return 0;
291    em->functions = (void *)(&evas_image_load_gif_func);
292    return 1;
293 }
294
295 EAPI void
296 module_close(void)
297 {
298    
299 }
300
301 EAPI Evas_Module_Api evas_modapi =
302 {
303    EVAS_MODULE_API_VERSION,
304      EVAS_MODULE_TYPE_IMAGE_LOADER,
305      "gif",
306      "none"
307 };