Mercurial > fife-parpg
comparison ext/libpng-1.2.29/contrib/pngminus/pnm2png.c @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /* | |
2 * pnm2png.c --- conversion from PBM/PGM/PPM-file to PNG-file | |
3 * copyright (C) 1999 by Willem van Schaik <willem@schaik.com> | |
4 * | |
5 * version 1.0 - 1999.10.15 - First version. | |
6 * | |
7 * Permission to use, copy, modify, and distribute this software and | |
8 * its documentation for any purpose and without fee is hereby granted, | |
9 * provided that the above copyright notice appear in all copies and | |
10 * that both that copyright notice and this permission notice appear in | |
11 * supporting documentation. This software is provided "as is" without | |
12 * express or implied warranty. | |
13 */ | |
14 | |
15 #include <stdio.h> | |
16 #include <stdlib.h> | |
17 #ifdef __TURBOC__ | |
18 #include <mem.h> | |
19 #include <fcntl.h> | |
20 #endif | |
21 | |
22 #ifndef BOOL | |
23 #define BOOL unsigned char | |
24 #endif | |
25 #ifndef TRUE | |
26 #define TRUE (BOOL) 1 | |
27 #endif | |
28 #ifndef FALSE | |
29 #define FALSE (BOOL) 0 | |
30 #endif | |
31 | |
32 #define STDIN 0 | |
33 #define STDOUT 1 | |
34 #define STDERR 2 | |
35 | |
36 /* to make pnm2png verbose so we can find problems (needs to be before png.h) */ | |
37 #ifndef PNG_DEBUG | |
38 #define PNG_DEBUG 0 | |
39 #endif | |
40 | |
41 #include "png.h" | |
42 | |
43 /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */ | |
44 #ifndef png_jmpbuf | |
45 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) | |
46 #endif | |
47 | |
48 /* function prototypes */ | |
49 | |
50 int main (int argc, char *argv[]); | |
51 void usage (); | |
52 BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha); | |
53 void get_token(FILE *pnm_file, char *token); | |
54 png_uint_32 get_data (FILE *pnm_file, int depth); | |
55 png_uint_32 get_value (FILE *pnm_file, int depth); | |
56 | |
57 /* | |
58 * main | |
59 */ | |
60 | |
61 int main(int argc, char *argv[]) | |
62 { | |
63 FILE *fp_rd = stdin; | |
64 FILE *fp_al = NULL; | |
65 FILE *fp_wr = stdout; | |
66 BOOL interlace = FALSE; | |
67 BOOL alpha = FALSE; | |
68 int argi; | |
69 | |
70 for (argi = 1; argi < argc; argi++) | |
71 { | |
72 if (argv[argi][0] == '-') | |
73 { | |
74 switch (argv[argi][1]) | |
75 { | |
76 case 'i': | |
77 interlace = TRUE; | |
78 break; | |
79 case 'a': | |
80 alpha = TRUE; | |
81 argi++; | |
82 if ((fp_al = fopen (argv[argi], "rb")) == NULL) | |
83 { | |
84 fprintf (stderr, "PNM2PNG\n"); | |
85 fprintf (stderr, "Error: alpha-channel file %s does not exist\n", | |
86 argv[argi]); | |
87 exit (1); | |
88 } | |
89 break; | |
90 case 'h': | |
91 case '?': | |
92 usage(); | |
93 exit(0); | |
94 break; | |
95 default: | |
96 fprintf (stderr, "PNM2PNG\n"); | |
97 fprintf (stderr, "Error: unknown option %s\n", argv[argi]); | |
98 usage(); | |
99 exit(1); | |
100 break; | |
101 } /* end switch */ | |
102 } | |
103 else if (fp_rd == stdin) | |
104 { | |
105 if ((fp_rd = fopen (argv[argi], "rb")) == NULL) | |
106 { | |
107 fprintf (stderr, "PNM2PNG\n"); | |
108 fprintf (stderr, "Error: file %s does not exist\n", argv[argi]); | |
109 exit (1); | |
110 } | |
111 } | |
112 else if (fp_wr == stdout) | |
113 { | |
114 if ((fp_wr = fopen (argv[argi], "wb")) == NULL) | |
115 { | |
116 fprintf (stderr, "PNM2PNG\n"); | |
117 fprintf (stderr, "Error: can not create PNG-file %s\n", argv[argi]); | |
118 exit (1); | |
119 } | |
120 } | |
121 else | |
122 { | |
123 fprintf (stderr, "PNM2PNG\n"); | |
124 fprintf (stderr, "Error: too many parameters\n"); | |
125 usage(); | |
126 exit (1); | |
127 } | |
128 } /* end for */ | |
129 | |
130 #ifdef __TURBOC__ | |
131 /* set stdin/stdout to binary, we're reading the PNM always! in binary format */ | |
132 if (fp_rd == stdin) | |
133 { | |
134 setmode (STDIN, O_BINARY); | |
135 } | |
136 if (fp_wr == stdout) | |
137 { | |
138 setmode (STDOUT, O_BINARY); | |
139 } | |
140 #endif | |
141 | |
142 /* call the conversion program itself */ | |
143 if (pnm2png (fp_rd, fp_wr, fp_al, interlace, alpha) == FALSE) | |
144 { | |
145 fprintf (stderr, "PNM2PNG\n"); | |
146 fprintf (stderr, "Error: unsuccessful converting to PNG-image\n"); | |
147 exit (1); | |
148 } | |
149 | |
150 /* close input file */ | |
151 fclose (fp_rd); | |
152 /* close output file */ | |
153 fclose (fp_wr); | |
154 /* close alpha file */ | |
155 if (alpha) | |
156 fclose (fp_al); | |
157 | |
158 return 0; | |
159 } | |
160 | |
161 /* | |
162 * usage | |
163 */ | |
164 | |
165 void usage() | |
166 { | |
167 fprintf (stderr, "PNM2PNG\n"); | |
168 fprintf (stderr, " by Willem van Schaik, 1999\n"); | |
169 #ifdef __TURBOC__ | |
170 fprintf (stderr, " for Turbo-C and Borland-C compilers\n"); | |
171 #else | |
172 fprintf (stderr, " for Linux (and Unix) compilers\n"); | |
173 #endif | |
174 fprintf (stderr, "Usage: pnm2png [options] <file>.<pnm> [<file>.png]\n"); | |
175 fprintf (stderr, " or: ... | pnm2png [options]\n"); | |
176 fprintf (stderr, "Options:\n"); | |
177 fprintf (stderr, " -i[nterlace] write png-file with interlacing on\n"); | |
178 fprintf (stderr, " -a[lpha] <file>.pgm read PNG alpha channel as pgm-file\n"); | |
179 fprintf (stderr, " -h | -? print this help-information\n"); | |
180 } | |
181 | |
182 /* | |
183 * pnm2png | |
184 */ | |
185 | |
186 BOOL pnm2png (FILE *pnm_file, FILE *png_file, FILE *alpha_file, BOOL interlace, BOOL alpha) | |
187 { | |
188 png_struct *png_ptr = NULL; | |
189 png_info *info_ptr = NULL; | |
190 png_byte *png_pixels = NULL; | |
191 png_byte **row_pointers = NULL; | |
192 png_byte *pix_ptr = NULL; | |
193 png_uint_32 row_bytes; | |
194 | |
195 char type_token[16]; | |
196 char width_token[16]; | |
197 char height_token[16]; | |
198 char maxval_token[16]; | |
199 int color_type; | |
200 png_uint_32 width, alpha_width; | |
201 png_uint_32 height, alpha_height; | |
202 png_uint_32 maxval; | |
203 int bit_depth = 0; | |
204 int channels; | |
205 int alpha_depth = 0; | |
206 int alpha_present; | |
207 int row, col; | |
208 BOOL raw, alpha_raw = FALSE; | |
209 png_uint_32 tmp16; | |
210 int i; | |
211 | |
212 /* read header of PNM file */ | |
213 | |
214 get_token(pnm_file, type_token); | |
215 if (type_token[0] != 'P') | |
216 { | |
217 return FALSE; | |
218 } | |
219 else if ((type_token[1] == '1') || (type_token[1] == '4')) | |
220 { | |
221 raw = (type_token[1] == '4'); | |
222 color_type = PNG_COLOR_TYPE_GRAY; | |
223 bit_depth = 1; | |
224 } | |
225 else if ((type_token[1] == '2') || (type_token[1] == '5')) | |
226 { | |
227 raw = (type_token[1] == '5'); | |
228 color_type = PNG_COLOR_TYPE_GRAY; | |
229 get_token(pnm_file, width_token); | |
230 sscanf (width_token, "%lu", &width); | |
231 get_token(pnm_file, height_token); | |
232 sscanf (height_token, "%lu", &height); | |
233 get_token(pnm_file, maxval_token); | |
234 sscanf (maxval_token, "%lu", &maxval); | |
235 if (maxval <= 1) | |
236 bit_depth = 1; | |
237 else if (maxval <= 3) | |
238 bit_depth = 2; | |
239 else if (maxval <= 15) | |
240 bit_depth = 4; | |
241 else if (maxval <= 255) | |
242 bit_depth = 8; | |
243 else /* if (maxval <= 65535) */ | |
244 bit_depth = 16; | |
245 } | |
246 else if ((type_token[1] == '3') || (type_token[1] == '6')) | |
247 { | |
248 raw = (type_token[1] == '6'); | |
249 color_type = PNG_COLOR_TYPE_RGB; | |
250 get_token(pnm_file, width_token); | |
251 sscanf (width_token, "%lu", &width); | |
252 get_token(pnm_file, height_token); | |
253 sscanf (height_token, "%lu", &height); | |
254 get_token(pnm_file, maxval_token); | |
255 sscanf (maxval_token, "%lu", &maxval); | |
256 if (maxval <= 1) | |
257 bit_depth = 1; | |
258 else if (maxval <= 3) | |
259 bit_depth = 2; | |
260 else if (maxval <= 15) | |
261 bit_depth = 4; | |
262 else if (maxval <= 255) | |
263 bit_depth = 8; | |
264 else /* if (maxval <= 65535) */ | |
265 bit_depth = 16; | |
266 } | |
267 else | |
268 { | |
269 return FALSE; | |
270 } | |
271 | |
272 /* read header of PGM file with alpha channel */ | |
273 | |
274 if (alpha) | |
275 { | |
276 if (color_type == PNG_COLOR_TYPE_GRAY) | |
277 color_type = PNG_COLOR_TYPE_GRAY_ALPHA; | |
278 if (color_type == PNG_COLOR_TYPE_RGB) | |
279 color_type = PNG_COLOR_TYPE_RGB_ALPHA; | |
280 | |
281 get_token(alpha_file, type_token); | |
282 if (type_token[0] != 'P') | |
283 { | |
284 return FALSE; | |
285 } | |
286 else if ((type_token[1] == '2') || (type_token[1] == '5')) | |
287 { | |
288 alpha_raw = (type_token[1] == '5'); | |
289 get_token(alpha_file, width_token); | |
290 sscanf (width_token, "%lu", &alpha_width); | |
291 if (alpha_width != width) | |
292 return FALSE; | |
293 get_token(alpha_file, height_token); | |
294 sscanf (height_token, "%lu", &alpha_height); | |
295 if (alpha_height != height) | |
296 return FALSE; | |
297 get_token(alpha_file, maxval_token); | |
298 sscanf (maxval_token, "%lu", &maxval); | |
299 if (maxval <= 1) | |
300 alpha_depth = 1; | |
301 else if (maxval <= 3) | |
302 alpha_depth = 2; | |
303 else if (maxval <= 15) | |
304 alpha_depth = 4; | |
305 else if (maxval <= 255) | |
306 alpha_depth = 8; | |
307 else /* if (maxval <= 65535) */ | |
308 alpha_depth = 16; | |
309 if (alpha_depth != bit_depth) | |
310 return FALSE; | |
311 } | |
312 else | |
313 { | |
314 return FALSE; | |
315 } | |
316 } /* end if alpha */ | |
317 | |
318 /* calculate the number of channels and store alpha-presence */ | |
319 if (color_type == PNG_COLOR_TYPE_GRAY) | |
320 channels = 1; | |
321 else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
322 channels = 2; | |
323 else if (color_type == PNG_COLOR_TYPE_RGB) | |
324 channels = 3; | |
325 else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) | |
326 channels = 4; | |
327 else | |
328 channels = 0; /* should not happen */ | |
329 | |
330 alpha_present = (channels - 1) % 2; | |
331 | |
332 /* row_bytes is the width x number of channels x (bit-depth / 8) */ | |
333 row_bytes = width * channels * ((bit_depth <= 8) ? 1 : 2); | |
334 | |
335 if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) | |
336 return FALSE; | |
337 | |
338 /* read data from PNM file */ | |
339 pix_ptr = png_pixels; | |
340 | |
341 for (row = 0; row < height; row++) | |
342 { | |
343 for (col = 0; col < width; col++) | |
344 { | |
345 for (i = 0; i < (channels - alpha_present); i++) | |
346 { | |
347 if (raw) | |
348 *pix_ptr++ = get_data (pnm_file, bit_depth); | |
349 else | |
350 if (bit_depth <= 8) | |
351 *pix_ptr++ = get_value (pnm_file, bit_depth); | |
352 else | |
353 { | |
354 tmp16 = get_value (pnm_file, bit_depth); | |
355 *pix_ptr = (png_byte) ((tmp16 >> 8) & 0xFF); | |
356 pix_ptr++; | |
357 *pix_ptr = (png_byte) (tmp16 & 0xFF); | |
358 pix_ptr++; | |
359 } | |
360 } | |
361 | |
362 if (alpha) /* read alpha-channel from pgm file */ | |
363 { | |
364 if (alpha_raw) | |
365 *pix_ptr++ = get_data (alpha_file, alpha_depth); | |
366 else | |
367 if (alpha_depth <= 8) | |
368 *pix_ptr++ = get_value (alpha_file, bit_depth); | |
369 else | |
370 { | |
371 tmp16 = get_value (alpha_file, bit_depth); | |
372 *pix_ptr++ = (png_byte) ((tmp16 >> 8) & 0xFF); | |
373 *pix_ptr++ = (png_byte) (tmp16 & 0xFF); | |
374 } | |
375 } /* if alpha */ | |
376 | |
377 } /* end for col */ | |
378 } /* end for row */ | |
379 | |
380 /* prepare the standard PNG structures */ | |
381 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
382 if (!png_ptr) | |
383 { | |
384 return FALSE; | |
385 } | |
386 info_ptr = png_create_info_struct (png_ptr); | |
387 if (!info_ptr) | |
388 { | |
389 png_destroy_write_struct (&png_ptr, (png_infopp) NULL); | |
390 return FALSE; | |
391 } | |
392 | |
393 /* setjmp() must be called in every function that calls a PNG-reading libpng function */ | |
394 if (setjmp (png_jmpbuf(png_ptr))) | |
395 { | |
396 png_destroy_write_struct (&png_ptr, (png_infopp) NULL); | |
397 return FALSE; | |
398 } | |
399 | |
400 /* initialize the png structure */ | |
401 png_init_io (png_ptr, png_file); | |
402 | |
403 /* we're going to write more or less the same PNG as the input file */ | |
404 png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth, color_type, | |
405 (!interlace) ? PNG_INTERLACE_NONE : PNG_INTERLACE_ADAM7, | |
406 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); | |
407 | |
408 /* write the file header information */ | |
409 png_write_info (png_ptr, info_ptr); | |
410 | |
411 /* if needed we will allocate memory for an new array of row-pointers */ | |
412 if (row_pointers == (unsigned char**) NULL) | |
413 { | |
414 if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL) | |
415 { | |
416 png_destroy_write_struct (&png_ptr, (png_infopp) NULL); | |
417 return FALSE; | |
418 } | |
419 } | |
420 | |
421 /* set the individual row_pointers to point at the correct offsets */ | |
422 for (i = 0; i < (height); i++) | |
423 row_pointers[i] = png_pixels + i * row_bytes; | |
424 | |
425 /* write out the entire image data in one call */ | |
426 png_write_image (png_ptr, row_pointers); | |
427 | |
428 /* write the additional chuncks to the PNG file (not really needed) */ | |
429 png_write_end (png_ptr, info_ptr); | |
430 | |
431 /* clean up after the write, and free any memory allocated */ | |
432 png_destroy_write_struct (&png_ptr, (png_infopp) NULL); | |
433 | |
434 if (row_pointers != (unsigned char**) NULL) | |
435 free (row_pointers); | |
436 if (png_pixels != (unsigned char*) NULL) | |
437 free (png_pixels); | |
438 | |
439 return TRUE; | |
440 } /* end of pnm2png */ | |
441 | |
442 /* | |
443 * get_token() - gets the first string after whitespace | |
444 */ | |
445 | |
446 void get_token(FILE *pnm_file, char *token) | |
447 { | |
448 int i = 0; | |
449 | |
450 /* remove white-space */ | |
451 do | |
452 { | |
453 token[i] = (unsigned char) fgetc (pnm_file); | |
454 } | |
455 while ((token[i] == '\n') || (token[i] == '\r') || (token[i] == ' ')); | |
456 | |
457 /* read string */ | |
458 do | |
459 { | |
460 i++; | |
461 token[i] = (unsigned char) fgetc (pnm_file); | |
462 } | |
463 while ((token[i] != '\n') && (token[i] != '\r') && (token[i] != ' ')); | |
464 | |
465 token[i] = '\0'; | |
466 | |
467 return; | |
468 } | |
469 | |
470 /* | |
471 * get_data() - takes first byte and converts into next pixel value, | |
472 * taking as much bits as defined by bit-depth and | |
473 * using the bit-depth to fill up a byte (0Ah -> AAh) | |
474 */ | |
475 | |
476 png_uint_32 get_data (FILE *pnm_file, int depth) | |
477 { | |
478 static int bits_left = 0; | |
479 static int old_value = 0; | |
480 static int mask = 0; | |
481 int i; | |
482 png_uint_32 ret_value; | |
483 | |
484 if (mask == 0) | |
485 for (i = 0; i < depth; i++) | |
486 mask = (mask >> 1) | 0x80; | |
487 | |
488 if (bits_left <= 0) | |
489 { | |
490 old_value = fgetc (pnm_file); | |
491 bits_left = 8; | |
492 } | |
493 | |
494 ret_value = old_value & mask; | |
495 for (i = 1; i < (8 / depth); i++) | |
496 ret_value = ret_value || (ret_value >> depth); | |
497 | |
498 old_value = (old_value << depth) & 0xFF; | |
499 bits_left -= depth; | |
500 | |
501 return ret_value; | |
502 } | |
503 | |
504 /* | |
505 * get_value() - takes first (numeric) string and converts into number, | |
506 * using the bit-depth to fill up a byte (0Ah -> AAh) | |
507 */ | |
508 | |
509 png_uint_32 get_value (FILE *pnm_file, int depth) | |
510 { | |
511 static png_uint_32 mask = 0; | |
512 png_byte token[16]; | |
513 png_uint_32 ret_value; | |
514 int i = 0; | |
515 | |
516 if (mask == 0) | |
517 for (i = 0; i < depth; i++) | |
518 mask = (mask << 1) | 0x01; | |
519 | |
520 get_token (pnm_file, (char *) token); | |
521 sscanf ((const char *) token, "%lu", &ret_value); | |
522 | |
523 ret_value &= mask; | |
524 | |
525 if (depth < 8) | |
526 for (i = 0; i < (8 / depth); i++) | |
527 ret_value = (ret_value << depth) || ret_value; | |
528 | |
529 return ret_value; | |
530 } | |
531 | |
532 /* end of source */ | |
533 |