Real-time dock left-right swapping
[wmaker-crm.git] / wrlib / gif.c
blob081f1ee5275db6c133298ce987ff90ea646511ea
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 #ifdef USE_GIF
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
31 #include <gif_lib.h>
33 #include "wraster.h"
35 static int InterlacedOffset[] = { 0, 4, 2, 1 };
36 static int InterlacedJumps[] = { 8, 8, 4, 2 };
39 * Partially based on code in gif2rgb from giflib, by Gershon Elber.
41 RImage *RLoadGIF(char *file, int index)
43 RImage *image = NULL;
44 unsigned char *cptr;
45 GifFileType *gif = NULL;
46 GifPixelType *buffer = NULL;
47 int i, j, k;
48 int width, height;
49 GifRecordType recType;
50 ColorMapObject *colormap;
51 unsigned char rmap[256];
52 unsigned char gmap[256];
53 unsigned char bmap[256];
55 if (index < 0)
56 index = 0;
58 /* default error message */
59 RErrorCode = RERR_BADINDEX;
61 gif = DGifOpenFileName(file);
63 if (!gif) {
64 switch (GifLastError()) {
65 case D_GIF_ERR_OPEN_FAILED:
66 RErrorCode = RERR_OPEN;
67 break;
68 case D_GIF_ERR_READ_FAILED:
69 RErrorCode = RERR_READ;
70 break;
71 default:
72 RErrorCode = RERR_BADIMAGEFILE;
73 break;
75 return NULL;
78 if (gif->SWidth < 1 || gif->SHeight < 1) {
79 DGifCloseFile(gif);
80 RErrorCode = RERR_BADIMAGEFILE;
81 return NULL;
84 colormap = gif->SColorMap;
86 i = 0;
88 do {
89 int extCode;
90 GifByteType *extension;
92 if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
93 goto giferr;
95 switch (recType) {
96 case IMAGE_DESC_RECORD_TYPE:
97 if (i++ != index)
98 break;
100 if (DGifGetImageDesc(gif) == GIF_ERROR) {
101 goto giferr;
104 width = gif->Image.Width;
105 height = gif->Image.Height;
107 if (gif->Image.ColorMap)
108 colormap = gif->Image.ColorMap;
110 /* the gif specs talk about a default colormap, but it
111 * doesnt say what the heck is this default colormap */
112 if (!colormap) {
114 * Well, since the spec says the colormap can be anything,
115 * lets just render it with whatever garbage the stack
116 * has :)
119 goto bye;
121 } else {
122 for (j = 0; j < colormap->ColorCount; j++) {
123 rmap[j] = colormap->Colors[j].Red;
124 gmap[j] = colormap->Colors[j].Green;
125 bmap[j] = colormap->Colors[j].Blue;
129 buffer = malloc(width * sizeof(GifColorType));
130 if (!buffer) {
131 RErrorCode = RERR_NOMEMORY;
132 goto bye;
135 image = RCreateImage(width, height, False);
136 if (!image) {
137 goto bye;
140 if (gif->Image.Interlace) {
141 int l;
142 int pelsPerLine;
144 if (RRGBAFormat == image->format)
145 pelsPerLine = width * 4;
146 else
147 pelsPerLine = width * 3;
149 for (j = 0; j < 4; j++) {
150 for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) {
151 if (DGifGetLine(gif, buffer, width) == GIF_ERROR) {
152 goto giferr;
154 cptr = image->data + (k * pelsPerLine);
155 for (l = 0; l < width; l++) {
156 int pixel = buffer[l];
157 *cptr++ = rmap[pixel];
158 *cptr++ = gmap[pixel];
159 *cptr++ = bmap[pixel];
163 } else {
164 cptr = image->data;
165 for (j = 0; j < height; j++) {
166 if (DGifGetLine(gif, buffer, width) == GIF_ERROR) {
167 goto giferr;
169 for (k = 0; k < width; k++) {
170 int pixel = buffer[k];
171 *cptr++ = rmap[pixel];
172 *cptr++ = gmap[pixel];
173 *cptr++ = bmap[pixel];
174 if (RRGBAFormat == image->format)
175 cptr++;
179 break;
181 case EXTENSION_RECORD_TYPE:
182 /* skip all extension blocks */
183 if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR) {
184 goto giferr;
186 while (extension) {
187 if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR) {
188 goto giferr;
191 break;
193 default:
194 break;
196 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
198 /* yuck! */
199 goto did_not_get_any_errors;
200 giferr:
201 switch (GifLastError()) {
202 case D_GIF_ERR_OPEN_FAILED:
203 RErrorCode = RERR_OPEN;
204 break;
205 case D_GIF_ERR_READ_FAILED:
206 RErrorCode = RERR_READ;
207 break;
208 default:
209 RErrorCode = RERR_BADIMAGEFILE;
210 break;
212 bye:
213 if (image)
214 RReleaseImage(image);
215 image = NULL;
216 did_not_get_any_errors:
218 if (buffer)
219 free(buffer);
221 if (gif)
222 DGifCloseFile(gif);
224 return image;
227 #endif /* USE_GIF */