png2pnm.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. /*
  2. * png2pnm.c --- conversion from PNG-file to PGM/PPM-file
  3. * copyright (C) 1999 by Willem van Schaik <[email protected]>
  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. #include <stdio.h>
  15. #include <stdlib.h>
  16. #ifdef __TURBOC__
  17. #include <mem.h>
  18. #include <fcntl.h>
  19. #endif
  20. #include <zlib.h>
  21. #ifndef BOOL
  22. #define BOOL unsigned char
  23. #endif
  24. #ifndef TRUE
  25. #define TRUE (BOOL) 1
  26. #endif
  27. #ifndef FALSE
  28. #define FALSE (BOOL) 0
  29. #endif
  30. #ifdef __TURBOC__
  31. #define STDIN 0
  32. #define STDOUT 1
  33. #define STDERR 2
  34. #endif
  35. /* to make png2pnm verbose so we can find problems (needs to be before png.h) */
  36. #ifndef PNG_DEBUG
  37. #define PNG_DEBUG 0
  38. #endif
  39. #include "png.h"
  40. /* Define png_jmpbuf() in case we are using a pre-1.0.6 version of libpng */
  41. #ifndef png_jmpbuf
  42. # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
  43. #endif
  44. /* function prototypes */
  45. int main (int argc, char *argv[]);
  46. void usage ();
  47. BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha);
  48. /*
  49. * main
  50. */
  51. int main(int argc, char *argv[])
  52. {
  53. FILE *fp_rd = stdin;
  54. FILE *fp_wr = stdout;
  55. FILE *fp_al = NULL;
  56. BOOL raw = TRUE;
  57. BOOL alpha = FALSE;
  58. int argi;
  59. for (argi = 1; argi < argc; argi++)
  60. {
  61. if (argv[argi][0] == '-')
  62. {
  63. switch (argv[argi][1])
  64. {
  65. case 'n':
  66. raw = FALSE;
  67. break;
  68. case 'r':
  69. raw = TRUE;
  70. break;
  71. case 'a':
  72. alpha = TRUE;
  73. argi++;
  74. if ((fp_al = fopen (argv[argi], "wb")) == NULL)
  75. {
  76. fprintf (stderr, "PNM2PNG\n");
  77. fprintf (stderr, "Error: can not create alpha-channel file %s\n", argv[argi]);
  78. exit (1);
  79. }
  80. break;
  81. case 'h':
  82. case '?':
  83. usage();
  84. exit(0);
  85. break;
  86. default:
  87. fprintf (stderr, "PNG2PNM\n");
  88. fprintf (stderr, "Error: unknown option %s\n", argv[argi]);
  89. usage();
  90. exit(1);
  91. break;
  92. } /* end switch */
  93. }
  94. else if (fp_rd == stdin)
  95. {
  96. if ((fp_rd = fopen (argv[argi], "rb")) == NULL)
  97. {
  98. fprintf (stderr, "PNG2PNM\n");
  99. fprintf (stderr, "Error: file %s does not exist\n", argv[argi]);
  100. exit (1);
  101. }
  102. }
  103. else if (fp_wr == stdout)
  104. {
  105. if ((fp_wr = fopen (argv[argi], "wb")) == NULL)
  106. {
  107. fprintf (stderr, "PNG2PNM\n");
  108. fprintf (stderr, "Error: can not create file %s\n", argv[argi]);
  109. exit (1);
  110. }
  111. }
  112. else
  113. {
  114. fprintf (stderr, "PNG2PNM\n");
  115. fprintf (stderr, "Error: too many parameters\n");
  116. usage();
  117. exit(1);
  118. }
  119. } /* end for */
  120. #ifdef __TURBOC__
  121. /* set stdin/stdout if required to binary */
  122. if (fp_rd == stdin)
  123. {
  124. setmode (STDIN, O_BINARY);
  125. }
  126. if ((raw) && (fp_wr == stdout))
  127. {
  128. setmode (STDOUT, O_BINARY);
  129. }
  130. #endif
  131. /* call the conversion program itself */
  132. if (png2pnm (fp_rd, fp_wr, fp_al, raw, alpha) == FALSE)
  133. {
  134. fprintf (stderr, "PNG2PNM\n");
  135. fprintf (stderr, "Error: unsuccessful conversion of PNG-image\n");
  136. exit(1);
  137. }
  138. /* close input file */
  139. fclose (fp_rd);
  140. /* close output file */
  141. fclose (fp_wr);
  142. /* close alpha file */
  143. if (alpha)
  144. fclose (fp_al);
  145. return 0;
  146. }
  147. /*
  148. * usage
  149. */
  150. void usage()
  151. {
  152. fprintf (stderr, "PNG2PNM\n");
  153. fprintf (stderr, " by Willem van Schaik, 1999\n");
  154. #ifdef __TURBOC__
  155. fprintf (stderr, " for Turbo-C and Borland-C compilers\n");
  156. #else
  157. fprintf (stderr, " for Linux (and Unix) compilers\n");
  158. #endif
  159. fprintf (stderr, "Usage: png2pnm [options] <file>.png [<file>.pnm]\n");
  160. fprintf (stderr, " or: ... | png2pnm [options]\n");
  161. fprintf (stderr, "Options:\n");
  162. fprintf (stderr, " -r[aw] write pnm-file in binary format (P4/P5/P6) (default)\n");
  163. fprintf (stderr, " -n[oraw] write pnm-file in ascii format (P1/P2/P3)\n");
  164. fprintf (stderr, " -a[lpha] <file>.pgm write PNG alpha channel as pgm-file\n");
  165. fprintf (stderr, " -h | -? print this help-information\n");
  166. }
  167. /*
  168. * png2pnm
  169. */
  170. BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file, BOOL raw, BOOL alpha)
  171. {
  172. png_struct *png_ptr = NULL;
  173. png_info *info_ptr = NULL;
  174. png_byte buf[8];
  175. png_byte *png_pixels = NULL;
  176. png_byte **row_pointers = NULL;
  177. png_byte *pix_ptr = NULL;
  178. png_uint_32 row_bytes;
  179. png_uint_32 width;
  180. png_uint_32 height;
  181. int bit_depth;
  182. int channels;
  183. int color_type;
  184. int alpha_present;
  185. int row, col;
  186. int ret;
  187. int i;
  188. long dep_16;
  189. /* read and check signature in PNG file */
  190. ret = fread (buf, 1, 8, png_file);
  191. if (ret != 8)
  192. return FALSE;
  193. ret = png_sig_cmp (buf, 0, 8);
  194. if (ret)
  195. return FALSE;
  196. /* create png and info structures */
  197. png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
  198. NULL, NULL, NULL);
  199. if (!png_ptr)
  200. return FALSE; /* out of memory */
  201. info_ptr = png_create_info_struct (png_ptr);
  202. if (!info_ptr)
  203. {
  204. png_destroy_read_struct (&png_ptr, NULL, NULL);
  205. return FALSE; /* out of memory */
  206. }
  207. if (setjmp (png_jmpbuf(png_ptr)))
  208. {
  209. png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
  210. return FALSE;
  211. }
  212. /* set up the input control for C streams */
  213. png_init_io (png_ptr, png_file);
  214. png_set_sig_bytes (png_ptr, 8); /* we already read the 8 signature bytes */
  215. /* read the file information */
  216. png_read_info (png_ptr, info_ptr);
  217. /* get size and bit-depth of the PNG-image */
  218. png_get_IHDR (png_ptr, info_ptr,
  219. &width, &height, &bit_depth, &color_type,
  220. NULL, NULL, NULL);
  221. /* set-up the transformations */
  222. /* transform paletted images into full-color rgb */
  223. if (color_type == PNG_COLOR_TYPE_PALETTE)
  224. png_set_expand (png_ptr);
  225. /* expand images to bit-depth 8 (only applicable for grayscale images) */
  226. if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
  227. png_set_expand (png_ptr);
  228. /* transform transparency maps into full alpha-channel */
  229. if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
  230. png_set_expand (png_ptr);
  231. #ifdef NJET
  232. /* downgrade 16-bit images to 8 bit */
  233. if (bit_depth == 16)
  234. png_set_strip_16 (png_ptr);
  235. /* transform grayscale images into full-color */
  236. if (color_type == PNG_COLOR_TYPE_GRAY ||
  237. color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  238. png_set_gray_to_rgb (png_ptr);
  239. /* only if file has a file gamma, we do a correction */
  240. if (png_get_gAMA (png_ptr, info_ptr, &file_gamma))
  241. png_set_gamma (png_ptr, (double) 2.2, file_gamma);
  242. #endif
  243. /* all transformations have been registered; now update info_ptr data,
  244. * get rowbytes and channels, and allocate image memory */
  245. png_read_update_info (png_ptr, info_ptr);
  246. /* get the new color-type and bit-depth (after expansion/stripping) */
  247. png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
  248. NULL, NULL, NULL);
  249. /* check for 16-bit files */
  250. if (bit_depth == 16)
  251. {
  252. raw = FALSE;
  253. #ifdef __TURBOC__
  254. pnm_file->flags &= ~((unsigned) _F_BIN);
  255. #endif
  256. }
  257. /* calculate new number of channels and store alpha-presence */
  258. if (color_type == PNG_COLOR_TYPE_GRAY)
  259. channels = 1;
  260. else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
  261. channels = 2;
  262. else if (color_type == PNG_COLOR_TYPE_RGB)
  263. channels = 3;
  264. else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
  265. channels = 4;
  266. else
  267. channels = 0; /* should never happen */
  268. alpha_present = (channels - 1) % 2;
  269. /* check if alpha is expected to be present in file */
  270. if (alpha && !alpha_present)
  271. {
  272. fprintf (stderr, "PNG2PNM\n");
  273. fprintf (stderr, "Error: PNG-file doesn't contain alpha channel\n");
  274. exit (1);
  275. }
  276. /* row_bytes is the width x number of channels x (bit-depth / 8) */
  277. row_bytes = png_get_rowbytes (png_ptr, info_ptr);
  278. if ((png_pixels = (png_byte *) malloc (row_bytes * height * sizeof (png_byte))) == NULL) {
  279. png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
  280. return FALSE;
  281. }
  282. if ((row_pointers = (png_byte **) malloc (height * sizeof (png_bytep))) == NULL)
  283. {
  284. png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
  285. free (png_pixels);
  286. png_pixels = NULL;
  287. return FALSE;
  288. }
  289. /* set the individual row_pointers to point at the correct offsets */
  290. for (i = 0; i < (height); i++)
  291. row_pointers[i] = png_pixels + i * row_bytes;
  292. /* now we can go ahead and just read the whole image */
  293. png_read_image (png_ptr, row_pointers);
  294. /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
  295. png_read_end (png_ptr, info_ptr);
  296. /* clean up after the read, and free any memory allocated - REQUIRED */
  297. png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
  298. /* write header of PNM file */
  299. if ((color_type == PNG_COLOR_TYPE_GRAY) ||
  300. (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
  301. {
  302. fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2");
  303. fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
  304. fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  305. }
  306. else if ((color_type == PNG_COLOR_TYPE_RGB) ||
  307. (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
  308. {
  309. fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3");
  310. fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
  311. fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  312. }
  313. /* write header of PGM file with alpha channel */
  314. if ((alpha) &&
  315. ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
  316. (color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
  317. {
  318. fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2");
  319. fprintf (alpha_file, "%d %d\n", (int) width, (int) height);
  320. fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
  321. }
  322. /* write data to PNM file */
  323. pix_ptr = png_pixels;
  324. for (row = 0; row < height; row++)
  325. {
  326. for (col = 0; col < width; col++)
  327. {
  328. for (i = 0; i < (channels - alpha_present); i++)
  329. {
  330. if (raw)
  331. fputc ((int) *pix_ptr++ , pnm_file);
  332. else
  333. if (bit_depth == 16){
  334. dep_16 = (long) *pix_ptr++;
  335. fprintf (pnm_file, "%ld ", (dep_16 << 8) + ((long) *pix_ptr++));
  336. }
  337. else
  338. fprintf (pnm_file, "%ld ", (long) *pix_ptr++);
  339. }
  340. if (alpha_present)
  341. {
  342. if (!alpha)
  343. {
  344. pix_ptr++; /* alpha */
  345. if (bit_depth == 16)
  346. pix_ptr++;
  347. }
  348. else /* output alpha-channel as pgm file */
  349. {
  350. if (raw)
  351. fputc ((int) *pix_ptr++ , alpha_file);
  352. else
  353. if (bit_depth == 16){
  354. dep_16 = (long) *pix_ptr++;
  355. fprintf (alpha_file, "%ld ", (dep_16 << 8) + (long) *pix_ptr++);
  356. }
  357. else
  358. fprintf (alpha_file, "%ld ", (long) *pix_ptr++);
  359. }
  360. } /* if alpha_present */
  361. if (!raw)
  362. if (col % 4 == 3)
  363. fprintf (pnm_file, "\n");
  364. } /* end for col */
  365. if (!raw)
  366. if (col % 4 != 0)
  367. fprintf (pnm_file, "\n");
  368. } /* end for row */
  369. if (row_pointers != (unsigned char**) NULL)
  370. free (row_pointers);
  371. if (png_pixels != (unsigned char*) NULL)
  372. free (png_pixels);
  373. return TRUE;
  374. } /* end of source */