wmaker: Replaced local 'extern' definition of wPreferences by proper header usage
[wmaker-crm.git] / wrlib / gif.c
blob1242daaf35d781cb84d17b8da139db86836ad15e
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"
34 #include "imgformat.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];
53 unsigned char gmap[256];
54 unsigned char bmap[256];
56 if (index < 0)
57 index = 0;
59 /* default error message */
60 RErrorCode = RERR_BADINDEX;
62 gif = DGifOpenFileName(file);
64 if (!gif) {
65 switch (GifLastError()) {
66 case D_GIF_ERR_OPEN_FAILED:
67 RErrorCode = RERR_OPEN;
68 break;
69 case D_GIF_ERR_READ_FAILED:
70 RErrorCode = RERR_READ;
71 break;
72 default:
73 RErrorCode = RERR_BADIMAGEFILE;
74 break;
76 return NULL;
79 if (gif->SWidth < 1 || gif->SHeight < 1) {
80 DGifCloseFile(gif);
81 RErrorCode = RERR_BADIMAGEFILE;
82 return NULL;
85 colormap = gif->SColorMap;
87 i = 0;
89 do {
90 int extCode;
91 GifByteType *extension;
93 if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
94 goto giferr;
96 switch (recType) {
97 case IMAGE_DESC_RECORD_TYPE:
98 if (i++ != index)
99 break;
101 if (DGifGetImageDesc(gif) == GIF_ERROR) {
102 goto giferr;
105 width = gif->Image.Width;
106 height = gif->Image.Height;
108 if (gif->Image.ColorMap)
109 colormap = gif->Image.ColorMap;
111 /* the gif specs talk about a default colormap, but it
112 * doesnt say what the heck is this default colormap */
113 if (!colormap) {
115 * Well, since the spec says the colormap can be anything,
116 * lets just render it with whatever garbage the stack
117 * has :)
120 goto bye;
122 } else {
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(GifColorType));
131 if (!buffer) {
132 RErrorCode = RERR_NOMEMORY;
133 goto bye;
136 image = RCreateImage(width, height, False);
137 if (!image) {
138 goto bye;
141 if (gif->Image.Interlace) {
142 int l;
143 int pelsPerLine;
145 if (RRGBAFormat == image->format)
146 pelsPerLine = width * 4;
147 else
148 pelsPerLine = width * 3;
150 for (j = 0; j < 4; j++) {
151 for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) {
152 if (DGifGetLine(gif, buffer, width) == GIF_ERROR) {
153 goto giferr;
155 cptr = image->data + (k * pelsPerLine);
156 for (l = 0; l < width; l++) {
157 int pixel = buffer[l];
158 *cptr++ = rmap[pixel];
159 *cptr++ = gmap[pixel];
160 *cptr++ = bmap[pixel];
164 } else {
165 cptr = image->data;
166 for (j = 0; j < height; j++) {
167 if (DGifGetLine(gif, buffer, width) == GIF_ERROR) {
168 goto giferr;
170 for (k = 0; k < width; k++) {
171 int pixel = buffer[k];
172 *cptr++ = rmap[pixel];
173 *cptr++ = gmap[pixel];
174 *cptr++ = bmap[pixel];
175 if (RRGBAFormat == image->format)
176 cptr++;
180 break;
182 case EXTENSION_RECORD_TYPE:
183 /* skip all extension blocks */
184 if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR) {
185 goto giferr;
187 while (extension) {
188 if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR) {
189 goto giferr;
192 break;
194 default:
195 break;
197 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
199 /* yuck! */
200 goto did_not_get_any_errors;
201 giferr:
202 switch (GifLastError()) {
203 case D_GIF_ERR_OPEN_FAILED:
204 RErrorCode = RERR_OPEN;
205 break;
206 case D_GIF_ERR_READ_FAILED:
207 RErrorCode = RERR_READ;
208 break;
209 default:
210 RErrorCode = RERR_BADIMAGEFILE;
211 break;
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 DGifCloseFile(gif);
225 return image;
228 #endif /* USE_GIF */