1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/socket.h>
7
8 #include <ming_config.h>
9
10 #include <png.h>
11
12 #include <zlib.h>
13
14 int verbose = 0;
15 typedef unsigned char byte;
16
error(char * s,...)17 void error(char *s, ...)
18 {
19 va_list ap;
20 va_start(ap, s);
21 vprintf(s, ap);
22 va_end(ap);
23 putchar('\n');
24 exit(1);
25 }
26
usage()27 void usage()
28 {
29 printf("dbl2png - convert a dbl file to an png file\n");
30 printf("\nUsage: dbl2png [--verbose] <file.dbl>\n");
31 printf("where file.dbl is your dbl file. Writes to file.png.\n");
32 exit(1);
33 }
34
35 struct pngdata
36 {
37 png_uint_32 width;
38 png_uint_32 height;
39 int bit_depth;
40 int color_type;
41 int num_palette;
42 int channels;
43 png_colorp palette;
44 unsigned char *data;
45 };
46
47
readDBL(FILE * fp)48 struct pngdata readDBL(FILE *fp)
49 {
50 struct pngdata png;
51 byte header[13],*data;
52 unsigned long outsize,readsize=0,datsize;
53 int i, ret;
54
55 if(!fp)
56 error("Couldn't open file!\n");
57
58 ret = fread(header, 1, 13, fp);
59 if(ret != 13)
60 error("Couldn't read header\n");
61
62 if (header[3]==2)
63 {
64 if(verbose)
65 printf("image data RGBA\n");
66 png.color_type=PNG_COLOR_TYPE_RGB_ALPHA;
67 }
68 else
69 {
70 if (header[3]==1)
71 {
72 if(verbose)
73 printf("image data RGB\n");
74 png.color_type=PNG_COLOR_TYPE_RGB;
75 }
76 else
77 error("unexpected 3rd byte in header");
78 }
79 outsize=(header[4]<<24)+(header[5]<<16)+(header[6]<<8)+header[7];
80 if(verbose)
81 printf("outsize=%ld \n",outsize);
82
83 png.bit_depth=8; // Can't deal with bit depth !=8
84 png.width= header[9] +(header[10]<<8);
85 png.height=header[11]+(header[12]<<8);
86
87 if (header[8]==3)
88 {
89 png.color_type=PNG_COLOR_TYPE_PALETTE;
90 readsize=outsize-6 ;
91 png.num_palette=0;
92 i= fread(&png.num_palette, 1, 1 ,fp);
93 if (verbose)
94 {
95 printf("image has PALETTE\npalette size=%d\n",png.num_palette+1);
96 printf("size %d x %d\n", (int)png.width, (int)png.height);
97 }
98 }
99 else
100 {
101 if (header[8]!=5)
102 error("unexpected 8th byte in header");
103 else
104 {
105 readsize=outsize-5 ;
106 if(verbose)
107 {
108 printf("size %d x %d\n", (int)png.width, (int)png.height);
109 }
110 }
111 }
112 if (!readsize)
113 error("internal error");
114 //
115 // ------ now we go --------
116 //
117 data=malloc( readsize );
118 if (!data)
119 {
120 error("memory allocation");
121 }
122 datsize=fread(data, 1, readsize, fp);
123 fclose(fp);
124 if (datsize != readsize)
125 {
126 free(data);
127 error("Didn't read all of the file! %d vs %d",datsize , readsize);
128 }
129 if (png.color_type==PNG_COLOR_TYPE_PALETTE) // for palette bit_depth==8
130 datsize = (png.num_palette+1) * 3 + png.width * png.height; // palette of RGB style
131 else
132 datsize = png.width * png.height * 4; // RGBA
133 png.data=malloc(datsize);
134 if (!png.data)
135 {
136 free(data);
137 error("memory allocation");
138 }
139
140 /* uncompress the data */
141 i=uncompress (png.data, &datsize, data, readsize );
142 if (i)
143 {
144 printf("uncompress call result = %d\n",i);
145 free(data);
146 error("uncompress error");
147 }
148 if(verbose)
149 {
150 printf("unpacked data size t=%ld byte\n",datsize);
151 }
152 free(data);
153 return png;
154 }
155
156 // callback function:
157 // reverse apply alpha, bytes shifting (see png2dbl.c for details)
158 // expecting pixel_depth==32, bit_depth==8, color_type==PNG_COLOR_TYPE_RGB_ALPHA
alpha_apply(png_structp png_ptr,png_row_infop row_info,png_bytep p)159 void alpha_apply(png_structp png_ptr, png_row_infop row_info, png_bytep p)
160 {
161 int i;
162 byte a, r, g, b;
163 for(i=0;i<row_info->width;i++)
164 {
165 a = p[0];
166 r = p[1];
167 g = p[2];
168 b = p[3];
169 *p++ = (r<<8)/(a+1);
170 *p++ = (g<<8)/(a+1);
171 *p++ = (b<<8)/(a+1);
172 *p++ = a;
173 }
174 }
175
176
writePNG(FILE * fp,struct pngdata png)177 void writePNG(FILE *fp, struct pngdata png)
178 {
179 png_structp png_ptr;
180 png_infop info_ptr;
181 int i,chan;
182 byte *ptr=png.data;
183
184 if(!fp)
185 error("Couldn't open file!\n");
186
187 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
188 if(!png_ptr)
189 error("Couldn't create png_ptr\n");
190
191 info_ptr = png_create_info_struct(png_ptr);
192 if(!info_ptr)
193 {
194 png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
195 error("Couldn't create info_ptr\n");
196 }
197
198 if (setjmp(png_jmpbuf(png_ptr)))
199 {
200 png_destroy_write_struct(&png_ptr, &info_ptr);
201 fclose(fp);
202 error("Mystery error (longjmp called)\n");
203 }
204
205 png_init_io(png_ptr, fp);
206 png_set_IHDR(png_ptr, info_ptr, png.width, png.height,
207 png.bit_depth, png.color_type, PNG_INTERLACE_NONE,
208 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
209 if (png.color_type==PNG_COLOR_TYPE_PALETTE)
210 png_set_PLTE(png_ptr, info_ptr,(png_colorp)png.data, png.num_palette+1);
211 png_write_info(png_ptr, info_ptr);
212
213 //
214 // ------ now we go --------
215 //
216 chan=png_get_channels(png_ptr, info_ptr);
217 if (verbose)
218 printf("channel count=%d\n",chan);
219
220 if(png.color_type == PNG_COLOR_TYPE_RGB_ALPHA )
221 {
222 png_set_write_user_transform_fn(png_ptr, alpha_apply);
223 for (i=0;i<png.height;i++)
224 {
225 png_write_row(png_ptr,ptr);
226 ptr+=png.width * chan; // 4
227 }
228 }
229 if(png.color_type == PNG_COLOR_TYPE_RGB)
230 {
231 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
232 for (i=0;i<png.height;i++)
233 {
234 png_write_row(png_ptr,ptr);
235 ptr+=png.width * 4;
236 }
237 }
238 if(png.color_type == PNG_COLOR_TYPE_PALETTE)
239 {
240 ptr+=(png.num_palette+1) * 3; // for palette bit_depth==8 of RGB style
241 for (i=0;i<png.height;i++)
242 {
243 png_write_row(png_ptr,ptr);
244 ptr+=png.width * chan; // 1
245 }
246 }
247
248 png_write_end(png_ptr,NULL);
249 png_destroy_write_struct(&png_ptr, &info_ptr);
250 free(png.data);
251 fclose(fp);
252 }
253
254
main(int argc,char * argv[])255 int main(int argc, char *argv[])
256 {
257 int len;
258 char *outfile;
259 struct pngdata png;
260
261 if (argc > 2 && strcmp(argv[1], "--verbose")==0) {
262 verbose = 1;
263 argc--;
264 argv++;
265 }
266
267 if(argc < 2)
268 usage();
269
270 len = strlen(argv[1]);
271
272 if(strcmp(argv[1]+len-4, ".dbl") != 0)
273 usage();
274
275 if(argc < 3)
276 {
277 outfile = strdup(argv[1]);
278 outfile[len-3] = 'p';
279 outfile[len-2] = 'n';
280 outfile[len-1] = 'g';
281 }
282 else
283 outfile = argv[2];
284
285 png = readDBL(fopen(argv[1], "rb"));
286 writePNG(fopen(outfile, "wb"), png);
287 exit(0);
288 }
289