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