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