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,
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
)
44 GifFileType
*gif
= NULL
;
45 GifPixelType
*buffer
= NULL
;
48 GifRecordType recType
;
49 ColorMapObject
*colormap
;
50 unsigned char rmap
[256], gmap
[256], bmap
[256];
56 /* default error message */
57 RErrorCode
= RERR_BADINDEX
;
60 gif
= DGifOpenFileName(file
);
61 #else /* USE_GIF == 5 */
62 gif
= DGifOpenFileName(file
, &gif_error
);
67 gif_error
= GifLastError();
70 case D_GIF_ERR_OPEN_FAILED
:
71 RErrorCode
= RERR_OPEN
;
73 case D_GIF_ERR_READ_FAILED
:
74 RErrorCode
= RERR_READ
;
77 RErrorCode
= RERR_BADIMAGEFILE
;
83 if (gif
->SWidth
< 1 || gif
->SHeight
< 1) {
84 #if (USE_GIF == 5) && (GIFLIB_MINOR >= 1)
85 DGifCloseFile(gif
, NULL
);
89 RErrorCode
= RERR_BADIMAGEFILE
;
93 colormap
= gif
->SColorMap
;
98 GifByteType
*extension
;
100 if (DGifGetRecordType(gif
, &recType
) == GIF_ERROR
)
104 case IMAGE_DESC_RECORD_TYPE
:
108 if (DGifGetImageDesc(gif
) == GIF_ERROR
)
111 width
= gif
->Image
.Width
;
112 height
= gif
->Image
.Height
;
114 if (gif
->Image
.ColorMap
)
115 colormap
= gif
->Image
.ColorMap
;
117 /* the gif specs talk about a default colormap, but it
118 * doesnt say what the heck is this default colormap
121 for (j
= 0; j
< colormap
->ColorCount
; j
++) {
122 rmap
[j
] = colormap
->Colors
[j
].Red
;
123 gmap
[j
] = colormap
->Colors
[j
].Green
;
124 bmap
[j
] = colormap
->Colors
[j
].Blue
;
128 buffer
= malloc(width
* sizeof(GifPixelType
));
130 RErrorCode
= RERR_NOMEMORY
;
134 image
= RCreateImage(width
, height
, False
);
138 if (gif
->Image
.Interlace
) {
141 if (RRGBAFormat
== image
->format
)
142 pelsPerLine
= width
* 4;
144 pelsPerLine
= width
* 3;
146 for (j
= 0; j
< 4; j
++) {
147 for (k
= InterlacedOffset
[j
]; k
< height
; k
+= InterlacedJumps
[j
]) {
148 if (DGifGetLine(gif
, buffer
, width
) == GIF_ERROR
)
151 cptr
= image
->data
+ (k
* pelsPerLine
);
152 for (l
= 0; l
< width
; l
++) {
153 int pixel
= buffer
[l
];
154 *cptr
++ = rmap
[pixel
];
155 *cptr
++ = gmap
[pixel
];
156 *cptr
++ = bmap
[pixel
];
162 for (j
= 0; j
< height
; j
++) {
163 if (DGifGetLine(gif
, buffer
, width
) == GIF_ERROR
)
166 for (k
= 0; k
< width
; k
++) {
167 int pixel
= buffer
[k
];
168 *cptr
++ = rmap
[pixel
];
169 *cptr
++ = gmap
[pixel
];
170 *cptr
++ = bmap
[pixel
];
171 if (RRGBAFormat
== image
->format
)
178 case EXTENSION_RECORD_TYPE
:
179 /* skip all extension blocks */
180 if (DGifGetExtension(gif
, &extCode
, &extension
) == GIF_ERROR
)
184 if (DGifGetExtensionNext(gif
, &extension
) == GIF_ERROR
)
192 } while (recType
!= TERMINATE_RECORD_TYPE
&& i
<= index
);
195 goto did_not_get_any_errors
;
198 switch (GifLastError()) {
199 case D_GIF_ERR_OPEN_FAILED
:
200 RErrorCode
= RERR_OPEN
;
202 case D_GIF_ERR_READ_FAILED
:
203 RErrorCode
= RERR_READ
;
206 RErrorCode
= RERR_BADIMAGEFILE
;
210 /* With gif_lib v5 there's no way to know what went wrong */
211 RErrorCode
= RERR_BADIMAGEFILE
;
215 RReleaseImage(image
);
217 did_not_get_any_errors
:
223 #if (USE_GIF == 5) && (GIFLIB_MINOR >= 1)
224 DGifCloseFile(gif
, NULL
);