Initial revision
[wmaker-crm.git] / wrlib / gif.c
blob35030e69d339041d265295cda8d92a53601adab7
1 /* gif.c - load GIF image from file
2 *
3 * Raster graphics library
4 *
5 * Copyright (c) 1998 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 GifFileType *gif = NULL;
48 GifPixelType *buffer = NULL;
49 int i, j, k, ofs = 0;
50 int width, height;
51 GifRecordType recType;
52 ColorMapObject *colormap;
53 unsigned char rmap[256];
54 unsigned char gmap[256];
55 unsigned char bmap[256];
57 if (index < 0)
58 index = 0;
60 /* default error message */
61 sprintf(RErrorString, "file does not contain image of index %i", index);
63 gif = DGifOpenFileName(file);
65 if (!gif) {
66 sprintf(RErrorString, "could not load gif file");
67 return NULL;
70 colormap = gif->SColorMap;
72 i = 0;
74 do {
75 int extCode;
76 GifByteType *extension;
78 if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
79 sprintf(RErrorString, "error while loading gif");
80 goto bye;
82 switch (recType) {
83 case IMAGE_DESC_RECORD_TYPE:
84 if (i++ != index)
85 break;
87 if (DGifGetImageDesc(gif)==GIF_ERROR) {
88 sprintf(RErrorString, "error while loading gif");
89 goto bye;
92 width = gif->Image.Width;
93 height = gif->Image.Height;
95 if (gif->Image.ColorMap)
96 colormap = gif->Image.ColorMap;
98 /* the gif specs talk about a default colormap, but it
99 * doesnt say what the heck is this default colormap */
100 if (!colormap) {
102 * Well, since the spec says the colormap can be anything,
103 * lets just render it with whatever garbage the stack
104 * has :)
106 sprintf(RErrorString, "bad gif file");
108 goto bye;
110 } else {
111 for (j = 0; j < colormap->ColorCount; j++) {
112 rmap[j] = colormap->Colors[j].Red;
113 gmap[j] = colormap->Colors[j].Green;
114 bmap[j] = colormap->Colors[j].Blue;
118 buffer = malloc(width * sizeof(GifColorType));
119 if (!buffer) {
120 sprintf(RErrorString, "out of memory while loading gif");
121 goto bye;
124 image = RCreateImage(width, height, False);
125 if (!image) {
126 sprintf(RErrorString, "out of memory while loading gif");
127 goto bye;
130 if (gif->Image.Interlace) {
131 int l;
133 for (j = 0; j < 4; j++) {
134 for (k = InterlacedOffset[j]; k < height;
135 k += InterlacedJumps[j]) {
136 if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
137 sprintf(RErrorString, "error while loading gif");
138 goto bye;
140 ofs = k*width;
141 for (l = 0; l < width; l++, ofs++) {
142 int pixel = buffer[l];
143 image->data[0][ofs] = rmap[pixel];
144 image->data[1][ofs] = gmap[pixel];
145 image->data[2][ofs] = bmap[pixel];
149 } else {
150 for (j = 0; j < height; j++) {
151 if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
152 sprintf(RErrorString, "error while loading gif");
153 goto bye;
155 for (k = 0; k < width; k++, ofs++) {
156 int pixel = buffer[k];
157 image->data[0][ofs] = rmap[pixel];
158 image->data[1][ofs] = gmap[pixel];
159 image->data[2][ofs] = bmap[pixel];
163 break;
165 case EXTENSION_RECORD_TYPE:
166 /* skip all extension blocks */
167 if (DGifGetExtension(gif, &extCode, &extension)==GIF_ERROR) {
168 sprintf(RErrorString, "error while loading gif");
169 goto bye;
171 while (extension) {
172 if (DGifGetExtensionNext(gif, &extension)==GIF_ERROR) {
173 sprintf(RErrorString, "error while loading gif");
174 goto bye;
177 break;
179 default:
180 break;
182 } while (recType != TERMINATE_RECORD_TYPE && i <= index);
184 /* yuck! */
185 goto did_not_get_any_errors;
186 bye:
187 if (image)
188 RDestroyImage(image);
189 image = NULL;
190 did_not_get_any_errors:
192 if (buffer)
193 free(buffer);
195 if (gif)
196 DGifCloseFile(gif);
198 return image;
201 #endif /* USE_GIF */