1 #include <string.h>
2 #include <stdio.h>
3 #include <unistd.h>
4 #include <sys/socket.h>
5 
6 #include "libming.h"
7 #include "ming_config.h"
8 #include "error.h"
9 
10 #if !(USE_PNG) // {
11 
newSWFDBLBitmapData_fromPngInput(SWFInput input)12 SWFDBLBitmapData newSWFDBLBitmapData_fromPngInput(SWFInput input)
13 {
14 	SWF_warn("newSWFDBLBitmapData_fromPngInput can't be used (no png compiled into this build of Ming).\n");
15 	return NULL;
16 }
17 
newSWFDBLBitmapData_fromPngFile(const char * fileName)18 SWFDBLBitmapData newSWFDBLBitmapData_fromPngFile(const char * fileName)
19 {
20 	SWF_warn("newSWFDBLBitmapData_fromPngFile can't be used (no png compiled into this build of Ming).\n");
21 	return NULL;
22 }
23 
24 #else // def USE_PNG }{
25 
26 #include "bitmap.h"
27 #include "dbl.h"
28 #include "input.h"
29 
30 
31 #ifndef __C2MAN__
32 #include <zlib.h>
33 #include <png.h>
34 #include <stdlib.h>
35 #include <math.h>
36 
37 struct pngdata
38 {
39 	png_uint_32 width;
40 	png_uint_32 height;
41 	int bit_depth;
42 	int color_type;
43 	int num_palette;
44 	int channels;
45 	png_colorp palette;
46 	unsigned char *data;
47 };
48 
49 // required - read from SWFInput
50 // png_init_io seems to be the one to change
51 
openPngFromFile(FILE * fp)52 static png_structp openPngFromFile(FILE *fp)
53 {	unsigned char header[8];
54 	png_structp result;
55 
56 	if(fread(header, 1, 8, fp) != 8)
57 		return NULL;
58 	if(png_sig_cmp(header, 0, 8))
59 		return NULL;
60 	result = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
61 	if(!result)
62 		return NULL;
63 	png_init_io(result, fp);
64 	return result;
65 }
66 
pngReadFunc(png_structp png,unsigned char * buf,int len)67 static int pngReadFunc(png_structp png, unsigned char *buf, int len)
68 {	SWFInput input = (SWFInput) png_get_io_ptr(png);
69 	return SWFInput_read(input, buf, len);
70 }
71 
openPngFromInput(SWFInput input)72 png_structp openPngFromInput(SWFInput input)
73 {	unsigned char header[8];
74 	png_structp result;
75 
76 	if(SWFInput_read(input, header, 8) != 8)
77 		return NULL;
78 	if(png_sig_cmp(header, 0, 8))
79 		return NULL;
80 	result = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
81 	if(!result)
82 		return NULL;
83 	png_set_read_fn(result, input, (png_rw_ptr) pngReadFunc);
84 	return result;
85 }
86 
87 static void
alignedcopy(struct pngdata png,unsigned char * data)88 alignedcopy(struct pngdata png, unsigned char *data)
89 {
90 	unsigned int row;
91 	int alignedrowsize;
92 	int pngrowsize;
93 	unsigned char *pngdata;
94 
95 	alignedrowsize = (png.width * png.channels + 3) & ~3;
96 	pngdata = png.data;
97 	pngrowsize = png.width * png.channels;
98 
99 	for( row = 0; row < png.height; row++ )
100 	{
101 		memcpy(data, pngdata, pngrowsize);
102 		pngdata += pngrowsize;
103 		data += alignedrowsize;
104 	}
105 }
106 
readPNG(png_structp png_ptr,dblData result)107 static int readPNG(png_structp png_ptr, dblData result)
108 {
109 	struct pngdata png;
110 	unsigned char *data;
111 
112 	png_infop info_ptr, end_info;
113 	png_bytep *row_pointers;
114 
115 	unsigned int i, rowbytes, depth, alignedsize;
116 	long outsize;
117 
118 	info_ptr = png_create_info_struct(png_ptr);
119 
120 	if(!info_ptr)
121 	{
122 		png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
123 		return 0;
124 	}
125 
126 	end_info = png_create_info_struct(png_ptr);
127 
128 	if(!end_info)
129 	{
130 		png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
131 		return 0;
132 	}
133 
134 	if(setjmp(png_jmpbuf(png_ptr)))
135 	{
136 		png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
137     	return 0;
138 	}
139 
140 	png_set_sig_bytes(png_ptr, 8);
141 	png_read_info(png_ptr, info_ptr);
142 
143 	png_get_IHDR(png_ptr, info_ptr, &png.width, &png.height,
144 	       &png.bit_depth, &png.color_type,
145 	       NULL, NULL, NULL);
146 
147 /*  if(verbose)
148   {
149     printf("size %ld/%ld color %d/%d/%ld\n",
150 	   png.width, png.height, png.bit_depth, png.color_type,
151 	   png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS));
152   }*/
153 
154 	if(png.color_type == PNG_COLOR_TYPE_PALETTE)
155 	{
156     	/*if(verbose)
157 			printf("color type: PALETTE\n");*/
158 
159 		png_get_PLTE(png_ptr, info_ptr, &png.palette, &png.num_palette);
160 	}
161 
162 	/* force bitdepth of 8 if necessary */
163 
164 	depth = png.bit_depth;
165 
166 	if(png.bit_depth < 8)
167 		png_set_packing(png_ptr);
168 
169 	if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
170 		png_set_expand(png_ptr);
171 
172 	if(png.bit_depth == 16)
173 	{
174 		/*if(verbose)
175 			printf("depth: 16\n");*/
176 
177 		png_set_strip_16(png_ptr);
178 	}
179 
180 	if(png.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
181 	{
182 		/*if(verbose)
183 			printf("color type: GRAY ALPHA\n");*/
184 
185 		png_set_gray_to_rgb(png_ptr);
186 	}
187 
188 	if(png.color_type == PNG_COLOR_TYPE_RGB)
189 	{
190 		/*if(verbose)
191 			printf("color type: RGB\n");*/
192 
193 		png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
194 	}
195 
196 
197 	/* update info w/ the set transformations */
198 	png_read_update_info(png_ptr, info_ptr);
199 
200 	png_get_IHDR(png_ptr, info_ptr, &png.width, &png.height,
201 	       &png.bit_depth, &png.color_type,
202 	       NULL, NULL, NULL);
203 
204 	result->width = png.width;
205 	result->height = png.height;
206 
207 	png.channels = png_get_channels(png_ptr, info_ptr);
208 
209 
210 	if(png.color_type == PNG_COLOR_TYPE_GRAY)
211 	{
212 		/* turn it into a palettized image, use the gray values as indices to
213        		an rgb color table */
214 
215 		int i;
216 
217 		/*if (verbose) printf("color type: GRAY\n");*/
218 
219 		png.color_type = PNG_COLOR_TYPE_PALETTE;
220 		png.num_palette = 1 << depth;
221 
222 		png.palette = (png_color*) malloc(sizeof(png_color) * png.num_palette);
223 
224 		for(i=0; i<(int)png.num_palette; ++i)
225 			png.palette[i].red = png.palette[i].green = png.palette[i].blue =
226 			 (i*255)/(png.num_palette-1);
227 	}
228 
229 
230   /* malloc stuff */
231 	row_pointers = (png_bytep*) malloc(png.height*sizeof(png_bytep));
232 	rowbytes = png_get_rowbytes(png_ptr, info_ptr);
233 
234 	png.data = (unsigned char*) malloc(png.height * rowbytes);
235 
236 	for(i=0; i<png.height; ++i)
237 		row_pointers[i] = png.data + rowbytes*i;
238 
239 	png_read_image(png_ptr, row_pointers);
240 
241 	if(png.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
242 		png.color_type == PNG_COLOR_TYPE_RGB)
243 	{
244 		/* alpha has to be pre-applied, bytes shifted */
245 
246 		unsigned int x, y;
247 		unsigned char *p;
248 		int alpha;
249 		unsigned char r, g, b;
250 
251 		/*if(verbose)
252 			printf("color type: RGB ALPHA\n");*/
253 
254 		for(y=0; y<png.height; ++y)
255 		{
256 			for(x=0; x<png.width; ++x)
257 			{
258 				p = png.data + rowbytes*y + 4*x;
259 
260 				r = p[0];
261 				g = p[1];
262 				b = p[2];
263 				alpha = p[3];
264 
265 				p[0] = alpha;
266 				p[1] = (char)((int)(r*alpha)>>8);
267 				p[2] = (char)((int)(g*alpha)>>8);
268 				p[3] = (char)((int)(b*alpha)>>8);
269 			}
270 		}
271 	}
272 
273 	alignedsize = png.height * ((png.width * png.channels + 3) & ~3);
274 
275 	if(png.color_type == PNG_COLOR_TYPE_PALETTE)
276 	{
277 		int tablesize = png.num_palette * sizeof(png_color);
278 
279 		result->format = 3;
280 		result->format2 = png.num_palette-1;
281 		data = (unsigned char*) malloc(tablesize + alignedsize);
282 		memcpy(data, png.palette, tablesize);
283 		alignedcopy(png, data + tablesize);
284 		alignedsize += tablesize;
285 	}
286 	else
287 	{
288 		result->format = 5;
289 		data = (unsigned char*) malloc(alignedsize);
290 		alignedcopy(png, data);
291 	}
292 
293 // at this point, can free
294 	png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
295 	free(row_pointers);
296 //	fclose(fp);
297 
298 	result->hasalpha = png.color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
299 						png.color_type == PNG_COLOR_TYPE_RGB_ALPHA;
300 
301 	result->data = (unsigned char*) malloc(outsize = (int)floor(alignedsize*1.01+12));
302 
303 	/* compress the RGB color table (if present) and image data one block */
304 	compress2(result->data, (uLongf *) &outsize, data, alignedsize, 9);
305 	result->length = outsize;
306 
307 	free(data);
308 	free(png.data);
309 
310 	return 1;
311 }
312 
313 
newSWFDBLBitmapData_fromPngFile(const char * fileName)314 SWFDBLBitmapData newSWFDBLBitmapData_fromPngFile(const char *fileName)
315 {
316 	SWFDBLBitmapData ret;
317 	FILE *fp;
318 	png_structp png_ptr;
319 	struct dbl_data pngdata;
320 	int ok;
321 
322 	fp = fopen(fileName, "rb");
323 	if(!fp)
324 		return NULL;
325 	png_ptr = openPngFromFile(fp);
326 	if(!png_ptr)
327 		return NULL;
328 	ok = readPNG(png_ptr, &pngdata);
329 	fclose(fp);
330 	if(!ok) return NULL;
331 	ret = newSWFDBLBitmapData_fromData(&pngdata);
332 	// ret->input = NULL;
333 	return ret;
334 }
335 
newSWFDBLBitmapData_fromPngInput(SWFInput input)336 SWFDBLBitmapData newSWFDBLBitmapData_fromPngInput(SWFInput input)
337 {
338 	SWFDBLBitmapData ret;
339 	png_structp png_ptr;
340 	struct dbl_data pngdata;
341 	int ok;
342 
343 	png_ptr = openPngFromInput(input);
344 	if(!png_ptr)
345 		return NULL;
346 	ok = readPNG(png_ptr, &pngdata);
347 	if(!ok) return NULL;
348 	ret = newSWFDBLBitmapData_fromData(&pngdata);
349 	// ret->input = NULL;
350 	return ret;
351 }
352 
353 #endif  // C2MAN
354 #endif // def USE_PNG }
355