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