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