1 /* $Id$ */
2
3
4 #include "ming_config.h"
5 #include "libming.h"
6 #include "error.h"
7
8 #if !(USE_GIF) // {
9
newSWFDBLBitmapData_fromGifInput(SWFInput input)10 SWFDBLBitmapData newSWFDBLBitmapData_fromGifInput(SWFInput input)
11 {
12 (void) input;
13 SWF_error("newSWFDBLBitmapData_fromGifInput can't be used (no gif compiled into this build of Ming).\n");
14 return NULL;
15 }
16
newSWFDBLBitmapData_fromGifFile(const char * fileName)17 SWFDBLBitmapData newSWFDBLBitmapData_fromGifFile(const char * fileName)
18 {
19 (void) fileName;
20 SWF_error("newSWFDBLBitmapData_fromGifFile can't be used (no gif compiled into this build of Ming).\n");
21 return NULL;
22 }
23
24 #else // def USE_GIF }{
25
26 #include "bitmap.h"
27 #include "dbl.h"
28 #include "input.h"
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <math.h>
34 #include <gif_lib.h>
35 #include <zlib.h>
36
37
38 /*void error(char *msg)
39 {
40 printf("%s:\n\n", msg);
41 PrintGifError();
42 exit(-1);
43 }*/
44
45 /**
46 * Get transparency color from graphic extension block
47 *
48 * Return: transparency color or -1
49 */
getTransparentColor(GifFileType * file)50 int getTransparentColor(GifFileType * file)
51 {
52 int i,returnvalue=-1;
53 ExtensionBlock * ext = file->SavedImages[0].ExtensionBlocks;
54
55 for (i=0; i < file->SavedImages[0].ExtensionBlockCount; i++, ext++) {
56
57 if (ext->Function == GRAPHICS_EXT_FUNC_CODE) {
58 if (ext->Bytes[0] & 1){ /* there is a transparent color */
59 if (!ext->Bytes[3]) returnvalue=255; // exception
60 else returnvalue=ext->Bytes[3]&0xff;
61 }
62 }
63 }
64 return returnvalue;
65 }
66
67 int
readGif(GifFileType * file,dblData result)68 readGif(GifFileType *file, dblData result)
69 {
70 ColorMapObject *colorMap;
71 unsigned char *bits;
72 unsigned char *data;
73 unsigned char *p;
74 int i, nColors, size, alpha, bgColor, alignedWidth, bytesPerColor;
75 unsigned long outsize;
76
77 if(DGifSlurp(file) != GIF_OK)
78 // error("Error slurping file");
79 return 0;
80
81 /* data should now be available */
82
83 /* Local colormap has precedence over Global colormap */
84 colorMap = file->Image.ColorMap ? file->Image.ColorMap : file->SColorMap;
85
86 nColors = colorMap->ColorCount;
87 alpha = getTransparentColor(file);
88
89 /* bgColor is the background color to fill the bitmap with
90 * if an image is smaller than screen coordinates
91 */
92 if (file->SColorMap) /* There is a GlobalColorMap */
93 bgColor = file->SBackGroundColor; /* The BackGroundColor is meaningful */
94 else
95 if (alpha >= 0) /* There is a transparency color */
96 bgColor = alpha; /* set the bgColor to tranparent */
97 else
98 bgColor = 0; /* Don't know what to do here.
99 * If this doesn't work, we could
100 * create a new color and set the
101 * alpha-channel to transparent
102 * (unless we are using all the 256
103 * colors, in which case either we
104 * give up, or move to 16-bits palette
105 */
106 result->hasalpha = 0;
107 bytesPerColor = 3;
108 if (alpha >= 0) {
109 bytesPerColor += 1; /* if tranparent color, use the alpha
110 * channel (RGBA instead of RGB)
111 */
112 result->hasalpha = 1;
113 }
114
115 /* Ah! The Flash specs says scanlines must be DWORD ALIGNED!
116 * (but image width is the correct number of pixels)
117 */
118 alignedWidth = (file->SWidth + 3) & ~3;
119
120 /* size = size-of-colormap + size-of-bitmap */
121 size = (nColors * bytesPerColor) + (alignedWidth * file->SHeight);
122 data = malloc(size);
123
124 result->format = 3;
125 result->width = file->SWidth;
126 result->height = file->SHeight;
127 result->format2 = nColors-1; /* size(colorMap) - 1 */
128
129 p = data;
130
131 /* create ColorMap */
132 for(i=0; i<nColors; ++i)
133 {
134 GifColorType c = colorMap->Colors[i];
135
136 if (bytesPerColor == 3) { /* RGB */
137 *p++ = c.Red;
138 *p++ = c.Green;
139 *p++ = c.Blue;
140 } else { /* RGBA */
141 #if 1 /* You would think that an alpha value of 0
142 * would mean fully transparent, but Flash
143 * player doesn't seem to think so.
144 * So, we just set the transparency color
145 * as 0,0,0,0
146 */
147 if (i != alpha) {
148 *p++ = c.Red;
149 *p++ = c.Green;
150 *p++ = c.Blue;
151 *p++ = 255; /* Fully opaque */
152 } else {
153 *p++ = 0; /* red */
154 *p++ = 0; /* green */
155 *p++ = 0; /* blue */
156 *p++ = 0; /* Fully transparent */
157 }
158 #else
159 *p++ = c.Red;
160 *p++ = c.Green;
161 *p++ = c.Blue;
162 *p++ = (i != alpha) ? 255 : 0; /* set alpha to 0 for transparent color */
163 #endif
164 }
165 }
166
167 bits = file->SavedImages[0].RasterBits;
168
169 if (alignedWidth == file->SWidth
170 && file->Image.Width == file->SWidth
171 && file->Image.Height == file->SHeight) {
172
173 /* we are all nicely aligned and don't need to move the bitmap around.
174 * Just copy the bits into the output buffer.
175 */
176 memcpy(p, bits, file->SWidth * file->SHeight);
177
178 } else {
179 /* here we need to pad the scanline or to move the bitmap around
180 * (if the image is not at 0,0 in the logical screen)
181 */
182 int screenWidth = file->SWidth;
183 int screenHeight = file->SHeight;
184
185 int imageTop = file->Image.Top;
186 int imageBottom = file->Image.Top + file->Image.Height;
187 int imageLeft = file->Image.Left;
188 int imageWidth = file->Image.Width;
189
190 for (i=0; i < screenHeight; i++, p += alignedWidth) {
191
192 /* the image is smaller than the logical "screen":
193 * Fill the reminder with the background color.
194 */
195 if (imageWidth != screenWidth)
196 memset(p, bgColor, screenWidth);
197
198 /* finally, copy scanline
199 */
200 if (i >= imageTop && i < imageBottom) {
201 memcpy(p + imageLeft, bits, imageWidth);
202 bits += imageWidth;
203 }
204 }
205 }
206
207 /* Done! */
208 DGifCloseFile(file);
209
210 result->data = malloc(outsize = (int)floor(size*1.01+12));
211
212 /* zlib-compress the gif data */
213 compress2(result->data, &outsize, data, size, 9);
214 result->length = outsize;
215
216 free(data);
217 return 1;
218 }
219
220 /*
221 * giflib provides
222 * DGifOpenFileName - use for open from file
223 * DGifOpenFileHandle
224 * DGifOpen - use for open from input
225 */
226
newSWFDBLBitmapData_fromGifFile(const char * fileName)227 SWFDBLBitmapData newSWFDBLBitmapData_fromGifFile(const char *fileName)
228 { GifFileType *file;
229 SWFDBLBitmapData ret;
230 struct dbl_data gifdata;
231
232 if((file = DGifOpenFileName(fileName)) == NULL)
233 return NULL;
234 if(!readGif(file, &gifdata))
235 return NULL;
236 ret = newSWFDBLBitmapData_fromData(&gifdata);
237 // ret->input = NULL;
238 return ret;
239 }
240
gifReadFunc(GifFileType * gif,unsigned char * buf,int len)241 static int gifReadFunc(GifFileType *gif, unsigned char *buf, int len)
242 { SWFInput input = gif->UserData;
243 return SWFInput_read(input, buf, len);
244 }
245
newSWFDBLBitmapData_fromGifInput(SWFInput input)246 SWFDBLBitmapData newSWFDBLBitmapData_fromGifInput(SWFInput input)
247 { GifFileType *file;
248 SWFDBLBitmapData ret;
249 struct dbl_data gifdata;
250
251 if((file = DGifOpen(input, (InputFunc) gifReadFunc)) == NULL)
252 return NULL;
253 if(!readGif(file, &gifdata))
254 return NULL;
255 ret = newSWFDBLBitmapData_fromData(&gifdata);
256 // ret->input = NULL;
257 return ret;
258 }
259
260 #endif // def USE_GIF }
261