- Fixed crashing bug in menu.c
[wmaker-crm.git] / wrlib / gif.c
blobfe8fbd0056017029b5d426ea9dae0f998c409435
1 /* gif.c - load GIF image from file
2 *
3 * Raster graphics library
4 *
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., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <config.h>
25 #ifdef USE_GIF
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
31 #include <gif_lib.h>
33 #include "wraster.h"
36 static int InterlacedOffset[] = { 0, 4, 2, 1 };
37 static int InterlacedJumps[] = { 8, 8, 4, 2 };
41 * Partially based on code in gif2rgb from giflib, by Gershon Elber.
43 RImage*
44 RLoadGIF(RContext *context, char *file, int index)
46 RImage *image = NULL;
47 unsigned char *cptr;
48 GifFileType *gif = NULL;
49 GifPixelType *buffer = NULL;
50 int i, j, k;
51 int width, height;
52 GifRecordType recType;
53 ColorMapObject *colormap;
54 unsigned char rmap[256];
55 unsigned char gmap[256];
56 unsigned char bmap[256];
58 if (index < 0)
59 index = 0;
61 /* default error message */
62 RErrorCode = RERR_BADINDEX;
64 gif = DGifOpenFileName(file);
66 if (!gif) {
67 switch (GifLastError()) {
68 case D_GIF_ERR_OPEN_FAILED:
69 RErrorCode = RERR_OPEN;
70 break;
71 case D_GIF_ERR_READ_FAILED:
72 RErrorCode = RERR_READ;
73 break;
74 default:
75 RErrorCode = RERR_BADIMAGEFILE;
76 break;
78 return NULL;
81 if (gif->SWidth<1 || gif->SHeight<1) {
82 DGifCloseFile(gif);
83 RErrorCode = RERR_BADIMAGEFILE;
84 return NULL;
87 colormap = gif->SColorMap;
89 i = 0;
91 do {
92 int extCode;
93 GifByteType *extension;
95 if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
96 goto giferr;
98 switch (recType) {
99 case IMAGE_DESC_RECORD_TYPE:
100 if (i++ != index)
101 break;
103 if (DGifGetImageDesc(gif)==GIF_ERROR) {
104 goto giferr;
107 width = gif->Image.Width;
108 height = gif->Image.Height;
110 if (gif->Image.ColorMap)
111 colormap = gif->Image.ColorMap;
113 /* the gif specs talk about a default colormap, but it
114 * doesnt say what the heck is this default colormap */
115 if (!colormap) {
117 * Well, since the spec says the colormap can be anything,
118 * lets just render it with whatever garbage the stack
119 * has :)
122 goto bye;
124 } else {
125 for (j = 0; j < colormap->ColorCount; j++) {
126 rmap[j] = colormap->Colors[j].Red;
127 gmap[j] = colormap->Colors[j].Green;
128 bmap[j] = colormap->Colors[j].Blue;
132 buffer = malloc(width * sizeof(GifColorType));
133 if (!buffer) {
134 RErrorCode = RERR_NOMEMORY;
135 goto bye;
138 image = RCreateImage(width, height, False);
139 if (!image) {
140 goto bye;
143 if (gif->Image.Interlace) {
144 int l;
145 int pelsPerLine;
147 if (RRGBAFormat==image->format)
148 pelsPerLine = width * 4;
149 else
150 pelsPerLine = width * 3;
152 for (j = 0; j < 4; j++) {
153 for (k = InterlacedOffset[j]; k < height;
154 k += InterlacedJumps[j]) {
155 if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
156 goto giferr;
158 cptr = image->data + (k*pelsPerLine);
159 for (l = 0; l < width; l++) {
160 int pixel = buffer[l];
161 *cptr++ = rmap[pixel];
162 *cptr++ = gmap[pixel];
163 *cptr++ = bmap[pixel];
167 } else {
168 cptr = image->data;
169 for (j = 0; j < height; j++) {
170 if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
171 goto giferr;
173 for (k = 0; k < width; k++) {
174 int pixel = buffer[k];
175 *cptr++ = rmap[pixel];
176 *cptr++ = gmap[pixel];
177 *cptr++ = bmap[pixel];
178 if (RRGBAFormat==image->format)
179 cptr++;
183 break;
185 case EXTENSION_RECORD_TYPE:
186 /* skip all extension blocks */
187 if (DGifGetExtension(gif, &extCode, &extension)==GIF_ERROR) {
188 goto giferr;
190 while (extension) {
191 if (DGifGetExtensionNext(gif, &extension)==GIF_ERROR) {
192 goto giferr;
195 break;
197 default:
198 break;
200 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
202 /* yuck! */
203 goto did_not_get_any_errors;
204 giferr:
205 switch (GifLastError()) {
206 case D_GIF_ERR_OPEN_FAILED:
207 RErrorCode = RERR_OPEN;
208 break;
209 case D_GIF_ERR_READ_FAILED:
210 RErrorCode = RERR_READ;
211 break;
212 default:
213 RErrorCode = RERR_BADIMAGEFILE;
214 break;
216 bye:
217 if (image)
218 RReleaseImage(image);
219 image = NULL;
220 did_not_get_any_errors:
222 if (buffer)
223 free(buffer);
225 if (gif)
226 DGifCloseFile(gif);
228 return image;
231 #endif /* USE_GIF */