png2pnm.c 11 KB

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