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

界面编程

开发平台:

Visual C++

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