wmaker: fix crash when switching workspace with "Affiche.app"
[wmaker-crm.git] / wrlib / load_gif.c
blobd70d04446bf61a0d6576f414ff965b03328280bd
1 /* gif.c - load GIF image from file
3 * Raster graphics library
5 * Copyright (c) 1998-2003 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
23 #include <config.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
29 #include <gif_lib.h>
31 #include "wraster.h"
32 #include "imgformat.h"
34 static int InterlacedOffset[] = { 0, 4, 2, 1 };
35 static int InterlacedJumps[] = { 8, 8, 4, 2 };
38 * Partially based on code in gif2rgb from giflib, by Gershon Elber.
40 RImage *RLoadGIF(const char *file, int index)
42 RImage *image = NULL;
43 unsigned char *cptr;
44 GifFileType *gif = NULL;
45 GifPixelType *buffer = NULL;
46 int i, j, k;
47 int width, height;
48 GifRecordType recType;
49 ColorMapObject *colormap;
50 unsigned char rmap[256], gmap[256], bmap[256];
51 int gif_error;
53 if (index < 0)
54 index = 0;
56 /* default error message */
57 RErrorCode = RERR_BADINDEX;
59 #if USE_GIF == 4
60 gif = DGifOpenFileName(file);
61 #else /* USE_GIF == 5 */
62 gif = DGifOpenFileName(file, &gif_error);
63 #endif
65 if (!gif) {
66 #if USE_GIF == 4
67 gif_error = GifLastError();
68 #endif
69 switch (gif_error) {
70 case D_GIF_ERR_OPEN_FAILED:
71 RErrorCode = RERR_OPEN;
72 break;
73 case D_GIF_ERR_READ_FAILED:
74 RErrorCode = RERR_READ;
75 break;
76 default:
77 RErrorCode = RERR_BADIMAGEFILE;
78 break;
80 return NULL;
83 if (gif->SWidth < 1 || gif->SHeight < 1) {
84 #if (USE_GIF == 5) && (GIFLIB_MINOR >= 1)
85 DGifCloseFile(gif, NULL);
86 #else
87 DGifCloseFile(gif);
88 #endif
89 RErrorCode = RERR_BADIMAGEFILE;
90 return NULL;
93 colormap = gif->SColorMap;
94 i = 0;
96 do {
97 int extCode;
98 GifByteType *extension;
100 if (DGifGetRecordType(gif, &recType) == GIF_ERROR)
101 goto giferr;
103 switch (recType) {
104 case IMAGE_DESC_RECORD_TYPE:
105 if (i++ != index)
106 break;
108 if (DGifGetImageDesc(gif) == GIF_ERROR)
109 goto giferr;
111 width = gif->Image.Width;
112 height = gif->Image.Height;
114 if (gif->Image.ColorMap)
115 colormap = gif->Image.ColorMap;
117 /* the gif specs talk about a default colormap, but it
118 * doesnt say what the heck is this default colormap
119 * Render anything */
120 if (colormap) {
121 for (j = 0; j < colormap->ColorCount; j++) {
122 rmap[j] = colormap->Colors[j].Red;
123 gmap[j] = colormap->Colors[j].Green;
124 bmap[j] = colormap->Colors[j].Blue;
128 buffer = malloc(width * sizeof(GifPixelType));
129 if (!buffer) {
130 RErrorCode = RERR_NOMEMORY;
131 goto bye;
134 image = RCreateImage(width, height, False);
135 if (!image)
136 goto bye;
138 if (gif->Image.Interlace) {
139 int l, pelsPerLine;
141 if (RRGBAFormat == image->format)
142 pelsPerLine = width * 4;
143 else
144 pelsPerLine = width * 3;
146 for (j = 0; j < 4; j++) {
147 for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) {
148 if (DGifGetLine(gif, buffer, width) == GIF_ERROR)
149 goto giferr;
151 cptr = image->data + (k * pelsPerLine);
152 for (l = 0; l < width; l++) {
153 int pixel = buffer[l];
154 *cptr++ = rmap[pixel];
155 *cptr++ = gmap[pixel];
156 *cptr++ = bmap[pixel];
160 } else {
161 cptr = image->data;
162 for (j = 0; j < height; j++) {
163 if (DGifGetLine(gif, buffer, width) == GIF_ERROR)
164 goto giferr;
166 for (k = 0; k < width; k++) {
167 int pixel = buffer[k];
168 *cptr++ = rmap[pixel];
169 *cptr++ = gmap[pixel];
170 *cptr++ = bmap[pixel];
171 if (RRGBAFormat == image->format)
172 cptr++;
176 break;
178 case EXTENSION_RECORD_TYPE:
179 /* skip all extension blocks */
180 if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR)
181 goto giferr;
183 while (extension)
184 if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR)
185 goto giferr;
187 break;
189 default:
190 break;
192 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
194 /* yuck! */
195 goto did_not_get_any_errors;
196 giferr:
197 #if USE_GIF == 4
198 switch (GifLastError()) {
199 case D_GIF_ERR_OPEN_FAILED:
200 RErrorCode = RERR_OPEN;
201 break;
202 case D_GIF_ERR_READ_FAILED:
203 RErrorCode = RERR_READ;
204 break;
205 default:
206 RErrorCode = RERR_BADIMAGEFILE;
207 break;
209 #else
210 /* With gif_lib v5 there's no way to know what went wrong */
211 RErrorCode = RERR_BADIMAGEFILE;
212 #endif
213 bye:
214 if (image)
215 RReleaseImage(image);
216 image = NULL;
217 did_not_get_any_errors:
219 if (buffer)
220 free(buffer);
222 if (gif)
223 #if (USE_GIF == 5) && (GIFLIB_MINOR >= 1)
224 DGifCloseFile(gif, NULL);
225 #else
226 DGifCloseFile(gif);
227 #endif
229 return image;