WRaster: Create header for i18n helper functions
[wmaker-crm.git] / wrlib / load_gif.c
blob5921735f6f36120f56296268567dc75ea895f907
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"
33 #include "wr_i18n.h"
36 static int InterlacedOffset[] = { 0, 4, 2, 1 };
37 static int InterlacedJumps[] = { 8, 8, 4, 2 };
40 * Partially based on code in gif2rgb from giflib, by Gershon Elber.
42 RImage *RLoadGIF(const char *file, int index)
44 RImage *image = NULL;
45 unsigned char *cptr;
46 GifFileType *gif = NULL;
47 GifPixelType *buffer = NULL;
48 int i, j, k;
49 int width, height;
50 GifRecordType recType;
51 ColorMapObject *colormap;
52 unsigned char rmap[256], gmap[256], bmap[256];
53 int gif_error;
55 if (index < 0)
56 index = 0;
58 /* default error message */
59 RErrorCode = RERR_BADINDEX;
61 #if USE_GIF == 4
62 gif = DGifOpenFileName(file);
63 #else /* USE_GIF == 5 */
64 gif = DGifOpenFileName(file, &gif_error);
65 #endif
67 if (!gif) {
68 #if USE_GIF == 4
69 gif_error = GifLastError();
70 #endif
71 switch (gif_error) {
72 case D_GIF_ERR_OPEN_FAILED:
73 RErrorCode = RERR_OPEN;
74 break;
75 case D_GIF_ERR_READ_FAILED:
76 RErrorCode = RERR_READ;
77 break;
78 default:
79 RErrorCode = RERR_BADIMAGEFILE;
80 break;
82 return NULL;
85 if (gif->SWidth < 1 || gif->SHeight < 1) {
86 #if (USE_GIF == 5) && (GIFLIB_MINOR >= 1)
87 DGifCloseFile(gif, NULL);
88 #else
89 DGifCloseFile(gif);
90 #endif
91 RErrorCode = RERR_BADIMAGEFILE;
92 return NULL;
95 colormap = gif->SColorMap;
96 i = 0;
98 do {
99 int extCode;
100 GifByteType *extension;
102 if (DGifGetRecordType(gif, &recType) == GIF_ERROR)
103 goto giferr;
105 switch (recType) {
106 case IMAGE_DESC_RECORD_TYPE:
107 if (i++ != index)
108 break;
110 if (DGifGetImageDesc(gif) == GIF_ERROR)
111 goto giferr;
113 width = gif->Image.Width;
114 height = gif->Image.Height;
116 if (gif->Image.ColorMap)
117 colormap = gif->Image.ColorMap;
119 /* the gif specs talk about a default colormap, but it
120 * doesnt say what the heck is this default colormap
121 * Render anything */
122 if (colormap) {
123 for (j = 0; j < colormap->ColorCount; j++) {
124 rmap[j] = colormap->Colors[j].Red;
125 gmap[j] = colormap->Colors[j].Green;
126 bmap[j] = colormap->Colors[j].Blue;
130 buffer = malloc(width * sizeof(GifPixelType));
131 if (!buffer) {
132 RErrorCode = RERR_NOMEMORY;
133 goto bye;
136 image = RCreateImage(width, height, False);
137 if (!image)
138 goto bye;
140 if (gif->Image.Interlace) {
141 int l, pelsPerLine;
143 if (RRGBAFormat == image->format)
144 pelsPerLine = width * 4;
145 else
146 pelsPerLine = width * 3;
148 for (j = 0; j < 4; j++) {
149 for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) {
150 if (DGifGetLine(gif, buffer, width) == GIF_ERROR)
151 goto giferr;
153 cptr = image->data + (k * pelsPerLine);
154 for (l = 0; l < width; l++) {
155 int pixel = buffer[l];
156 *cptr++ = rmap[pixel];
157 *cptr++ = gmap[pixel];
158 *cptr++ = bmap[pixel];
162 } else {
163 cptr = image->data;
164 for (j = 0; j < height; j++) {
165 if (DGifGetLine(gif, buffer, width) == GIF_ERROR)
166 goto giferr;
168 for (k = 0; k < width; k++) {
169 int pixel = buffer[k];
170 *cptr++ = rmap[pixel];
171 *cptr++ = gmap[pixel];
172 *cptr++ = bmap[pixel];
173 if (RRGBAFormat == image->format)
174 cptr++;
178 break;
180 case EXTENSION_RECORD_TYPE:
181 /* skip all extension blocks */
182 if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR)
183 goto giferr;
185 while (extension)
186 if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR)
187 goto giferr;
189 break;
191 default:
192 break;
194 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
196 /* yuck! */
197 goto did_not_get_any_errors;
198 giferr:
199 #if USE_GIF == 4
200 switch (GifLastError()) {
201 case D_GIF_ERR_OPEN_FAILED:
202 RErrorCode = RERR_OPEN;
203 break;
204 case D_GIF_ERR_READ_FAILED:
205 RErrorCode = RERR_READ;
206 break;
207 default:
208 RErrorCode = RERR_BADIMAGEFILE;
209 break;
211 #else
212 /* With gif_lib v5 there's no way to know what went wrong */
213 RErrorCode = RERR_BADIMAGEFILE;
214 #endif
215 bye:
216 if (image)
217 RReleaseImage(image);
218 image = NULL;
219 did_not_get_any_errors:
221 if (buffer)
222 free(buffer);
224 if (gif)
225 #if (USE_GIF == 5) && (GIFLIB_MINOR >= 1)
226 DGifCloseFile(gif, NULL);
227 #else
228 DGifCloseFile(gif);
229 #endif
231 return image;