png2pnm.c
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:12k
源码类别:

界面编程

开发平台:

Visual C++

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