1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <math.h>
5 #include <unistd.h>
6 #include <string.h>
7 #include <sys/socket.h>
8
9 #include <ming_config.h>
10
11 #include <png.h>
12
13 #include <zlib.h>
14
15 int verbose = 0;
16 typedef unsigned char byte;
17
error(char * s,...)18 void error(char *s, ...)
19 {
20 va_list ap;
21 va_start(ap, s);
22 vprintf(s, ap);
23 va_end(ap);
24 putchar('\n');
25 exit(1);
26 }
27
usage()28 void usage()
29 {
30 printf("png2dbl - convert a png file to an SWF DefineBitsLossless\n");
31 printf(" or DefineBitsLossless2 block\n");
32 printf("\nUsage: png2bmap [--verbose] <file.png>\n");
33 printf("where file.png is your png file. Writes to file.dbl.\n");
34 exit(1);
35 }
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
readPNG(FILE * fp)49 struct pngdata readPNG(FILE *fp)
50 {
51 struct pngdata png;
52 unsigned char header[8];
53 unsigned int x, y;
54 unsigned char *p;
55 byte alpha;
56 byte r, g, b;
57 int ret;
58
59 png_structp png_ptr;
60 png_infop info_ptr, end_info;
61 png_bytep *row_pointers;
62
63 unsigned int i, rowbytes, depth;
64
65 if(!fp)
66 error("Couldn't open file!\n");
67
68 ret = fread(header, 1, 8, fp);
69 if(ret != 8)
70 error("failed read header\n");
71
72 /*
73 if(png_check_sig(header, 8))
74 error("File doesn't appear to be a proper PNG file\n");
75 */
76 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
77
78 if(!png_ptr)
79 error("Couldn't create png_ptr\n");
80
81 info_ptr = png_create_info_struct(png_ptr);
82
83 if(!info_ptr)
84 {
85 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
86 error("Couldn't create info_ptr\n");
87 }
88
89 end_info = png_create_info_struct(png_ptr);
90
91 if(!end_info)
92 {
93 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
94 error("Couldn't create end_info\n");
95 }
96
97 if(setjmp(png_jmpbuf(png_ptr)))
98 {
99 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
100 fclose(fp);
101 error("Mystery error (longjmp called)\n");
102 }
103
104 png_init_io(png_ptr, fp);
105 png_set_sig_bytes(png_ptr, 8);
106 png_read_info(png_ptr, info_ptr);
107
108 png_get_IHDR(png_ptr, info_ptr, &png.width, &png.height,
109 &png.bit_depth, &png.color_type,
110 NULL, NULL, NULL);
111
112 if(verbose)
113 {
114 printf("size %ld/%ld color %d/%d/%ld\n",
115 png.width, png.height, png.bit_depth, png.color_type,
116 png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS));
117 }
118
119 if(png.color_type == PNG_COLOR_TYPE_PALETTE)
120 {
121 if(verbose)
122 printf("color type: PALETTE\n");
123
124 png_get_PLTE(png_ptr, info_ptr, &png.palette, &png.num_palette);
125 }
126
127 /* force bitdepth of 8 if necessary */
128
129 depth = png.bit_depth;
130
131 if(png.bit_depth < 8)
132 png_set_packing(png_ptr);
133
134 if(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
135 png_set_expand(png_ptr);
136
137 if(png.bit_depth == 16)
138 {
139 if(verbose)
140 printf("depth: 16\n");
141
142 png_set_strip_16(png_ptr);
143 }
144
145 if(png.color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
146 {
147 if(verbose)
148 printf("color type: GRAY ALPHA\n");
149
150 png_set_gray_to_rgb(png_ptr);
151 }
152
153 if(png.color_type == PNG_COLOR_TYPE_RGB)
154 {
155 if(verbose)
156 printf("color type: RGB\n");
157
158 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
159 }
160
161
162 /* update info w/ the set transformations */
163 png_read_update_info(png_ptr, info_ptr);
164
165 png_get_IHDR(png_ptr, info_ptr, &png.width, &png.height,
166 &png.bit_depth, &png.color_type,
167 NULL, NULL, NULL);
168
169 png.channels = png_get_channels(png_ptr, info_ptr);
170
171
172 if(png.color_type == PNG_COLOR_TYPE_GRAY)
173 {
174 /* turn it into a palettized image, use the gray values as indices to
175 an rgb color table */
176
177 int i;
178
179 if (verbose) printf("color type: GRAY\n");
180
181 png.color_type = PNG_COLOR_TYPE_PALETTE;
182 png.num_palette = 1 << depth;
183
184 png.palette = (png_color*) malloc(sizeof(png_color) * png.num_palette);
185
186 for(i=0; i<(int)png.num_palette; ++i)
187 png.palette[i].red = png.palette[i].green = png.palette[i].blue =
188 (png_byte) ( (i*255)/(png.num_palette-1) );
189 }
190
191
192 /* malloc stuff */
193 row_pointers = (png_bytep*) malloc(png.height*sizeof(png_bytep));
194 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
195
196 png.data = (unsigned char*) malloc(png.height * rowbytes);
197
198 for(i=0; i<png.height; ++i)
199 row_pointers[i] = png.data + rowbytes*i;
200
201 png_read_image(png_ptr, row_pointers);
202
203 if(png.color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
204 png.color_type == PNG_COLOR_TYPE_RGB)
205 {
206 /* alpha has to be pre-applied, bytes shifted */
207
208 if(verbose)
209 printf("color type: RGB ALPHA\n");
210
211 for(y=0; y<png.height; ++y)
212 {
213 for(x=0; x<png.width; ++x)
214 {
215 p = png.data + rowbytes*y + 4*x;
216
217 r = p[0];
218 g = p[1];
219 b = p[2];
220
221 alpha = p[3];
222
223 p[0] = alpha;
224 p[1] = (char)((int)(r*alpha)>>8);
225 p[2] = (char)((int)(g*alpha)>>8);
226 p[3] = (char)((int)(b*alpha)>>8);
227 }
228 }
229 }
230
231 return png;
232 }
233
234 static void
alignedcopy(struct pngdata png,unsigned char * data)235 alignedcopy(struct pngdata png, unsigned char *data)
236 {
237 unsigned int row;
238 int alignedrowsize;
239 int pngrowsize;
240 unsigned char *pngdata;
241
242 alignedrowsize = (png.width * png.channels + 3) & ~3;
243 pngdata = png.data;
244 pngrowsize = png.width * png.channels;
245
246 for( row = 0; row < png.height; row++ )
247 {
248 memcpy(data, pngdata, pngrowsize);
249 pngdata += pngrowsize;
250 data += alignedrowsize;
251 }
252 }
253
writeDBL(FILE * f,struct pngdata png)254 void writeDBL(FILE *f, struct pngdata png)
255 {
256 unsigned char *data, *outdata;
257 int alignedsize;
258 unsigned long outsize;
259 int hasAlpha =
260 png.color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
261 png.color_type == PNG_COLOR_TYPE_RGB_ALPHA;
262
263 fputc('D', f);
264 fputc('B', f);
265 fputc('l', f);
266 fputc(hasAlpha ? 2 : 1, f);
267
268 alignedsize = png.height * ((png.width * png.channels + 3) & ~3);
269
270 if(png.color_type == PNG_COLOR_TYPE_PALETTE)
271 {
272 int tablesize = png.num_palette * sizeof(png_color);
273
274 data = (unsigned char*) malloc(tablesize + alignedsize);
275 memcpy(data, png.palette, tablesize);
276 alignedcopy(png, data + tablesize);
277 alignedsize += tablesize;
278 }
279 else
280 {
281 data = (unsigned char*) malloc(alignedsize);
282 alignedcopy(png, data);
283 }
284
285 outdata = (unsigned char*) malloc(outsize = (int)floor(alignedsize*1.01+12));
286 /* compress the RGB color table (if present) and image data one block */
287 compress2(outdata, &outsize, data, alignedsize, 9);
288 #ifndef USE_ZLIB
289 outsize = alignedsize; /* if using zlib use the compress2() result value! */
290 #endif
291 /* write the remaining file size */
292
293 if(png.color_type == PNG_COLOR_TYPE_PALETTE)
294 {
295 fputc(((outsize+6)>>24)&0xff, f);
296 fputc(((outsize+6)>>16)&0xff, f);
297 fputc(((outsize+6)>>8)&0xff, f);
298 fputc((outsize+6)&0xff, f);
299 }
300 else
301 {
302 fputc(((outsize+5)>>24)&0xff, f);
303 fputc(((outsize+5)>>16)&0xff, f);
304 fputc(((outsize+5)>>8)&0xff, f);
305 fputc((outsize+5)&0xff, f);
306 }
307
308 /* UInt8 format
309 3: 8bit data
310 4: 16bit data
311 5: 32bit data */
312
313 if(png.bit_depth != 8)
314 error("Can't deal with bit depth %i!", png.bit_depth);
315
316 if(png.color_type == PNG_COLOR_TYPE_PALETTE)
317 fputc(3, f);
318 else
319 fputc(5, f);
320
321 fputc(png.width&0xff, f);
322 fputc((png.width>>8)&0xff, f);
323
324 fputc(png.height&0xff, f);
325 fputc((png.height>>8)&0xff, f);
326
327 if(png.color_type == PNG_COLOR_TYPE_PALETTE)
328 fputc(png.num_palette-1, f);
329
330 if(fwrite(outdata, sizeof(char), outsize, f) != outsize)
331 error("Didn't write all of the file!");
332 }
333
main(int argc,char * argv[])334 int main(int argc, char *argv[])
335 {
336 int len;
337 char *outfile;
338 struct pngdata png;
339
340 if (argc > 2 && strcmp(argv[1], "--verbose")==0) {
341 verbose = 1;
342 argc--;
343 argv++;
344 }
345
346 if(argc < 2)
347 usage();
348
349 len = strlen(argv[1]);
350
351 if(strcmp(argv[1]+len-4, ".png") != 0)
352 usage();
353
354 if(argc < 3)
355 {
356 outfile = strdup(argv[1]);
357
358 outfile[len-3] = 'd';
359 outfile[len-2] = 'b';
360 outfile[len-1] = 'l';
361 }
362 else
363 outfile = argv[2];
364
365 png = readPNG(fopen(argv[1], "rb"));
366 writeDBL(fopen(outfile, "wb"), png);
367
368 exit(0);
369 }
370