wrlib: Use a Conditional for GIF in the makefile instead of #if in source
[wmaker-crm.git] / wrlib / gif.c
blobe1b1a7329231a235c59739a90da12038da5c10e2
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];
52 if (index < 0)
53 index = 0;
55 /* default error message */
56 RErrorCode = RERR_BADINDEX;
58 gif = DGifOpenFileName(file);
60 if (!gif) {
61 switch (GifLastError()) {
62 case D_GIF_ERR_OPEN_FAILED:
63 RErrorCode = RERR_OPEN;
64 break;
65 case D_GIF_ERR_READ_FAILED:
66 RErrorCode = RERR_READ;
67 break;
68 default:
69 RErrorCode = RERR_BADIMAGEFILE;
70 break;
72 return NULL;
75 if (gif->SWidth < 1 || gif->SHeight < 1) {
76 DGifCloseFile(gif);
77 RErrorCode = RERR_BADIMAGEFILE;
78 return NULL;
81 colormap = gif->SColorMap;
82 i = 0;
84 do {
85 int extCode;
86 GifByteType *extension;
88 if (DGifGetRecordType(gif, &recType) == GIF_ERROR)
89 goto giferr;
91 switch (recType) {
92 case IMAGE_DESC_RECORD_TYPE:
93 if (i++ != index)
94 break;
96 if (DGifGetImageDesc(gif) == GIF_ERROR)
97 goto giferr;
99 width = gif->Image.Width;
100 height = gif->Image.Height;
102 if (gif->Image.ColorMap)
103 colormap = gif->Image.ColorMap;
105 /* the gif specs talk about a default colormap, but it
106 * doesnt say what the heck is this default colormap
107 * Render anything */
108 if (colormap) {
109 for (j = 0; j < colormap->ColorCount; j++) {
110 rmap[j] = colormap->Colors[j].Red;
111 gmap[j] = colormap->Colors[j].Green;
112 bmap[j] = colormap->Colors[j].Blue;
116 buffer = malloc(width * sizeof(GifColorType));
117 if (!buffer) {
118 RErrorCode = RERR_NOMEMORY;
119 goto bye;
122 image = RCreateImage(width, height, False);
123 if (!image)
124 goto bye;
126 if (gif->Image.Interlace) {
127 int l, pelsPerLine;
129 if (RRGBAFormat == image->format)
130 pelsPerLine = width * 4;
131 else
132 pelsPerLine = width * 3;
134 for (j = 0; j < 4; j++) {
135 for (k = InterlacedOffset[j]; k < height; k += InterlacedJumps[j]) {
136 if (DGifGetLine(gif, buffer, width) == GIF_ERROR)
137 goto giferr;
139 cptr = image->data + (k * pelsPerLine);
140 for (l = 0; l < width; l++) {
141 int pixel = buffer[l];
142 *cptr++ = rmap[pixel];
143 *cptr++ = gmap[pixel];
144 *cptr++ = bmap[pixel];
148 } else {
149 cptr = image->data;
150 for (j = 0; j < height; j++) {
151 if (DGifGetLine(gif, buffer, width) == GIF_ERROR)
152 goto giferr;
154 for (k = 0; k < width; k++) {
155 int pixel = buffer[k];
156 *cptr++ = rmap[pixel];
157 *cptr++ = gmap[pixel];
158 *cptr++ = bmap[pixel];
159 if (RRGBAFormat == image->format)
160 cptr++;
164 break;
166 case EXTENSION_RECORD_TYPE:
167 /* skip all extension blocks */
168 if (DGifGetExtension(gif, &extCode, &extension) == GIF_ERROR)
169 goto giferr;
171 while (extension)
172 if (DGifGetExtensionNext(gif, &extension) == GIF_ERROR)
173 goto giferr;
175 break;
177 default:
178 break;
180 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
182 /* yuck! */
183 goto did_not_get_any_errors;
184 giferr:
185 switch (GifLastError()) {
186 case D_GIF_ERR_OPEN_FAILED:
187 RErrorCode = RERR_OPEN;
188 break;
189 case D_GIF_ERR_READ_FAILED:
190 RErrorCode = RERR_READ;
191 break;
192 default:
193 RErrorCode = RERR_BADIMAGEFILE;
194 break;
196 bye:
197 if (image)
198 RReleaseImage(image);
199 image = NULL;
200 did_not_get_any_errors:
202 if (buffer)
203 free(buffer);
205 if (gif)
206 DGifCloseFile(gif);
208 return image;