source: rtems-graphics-toolkit/libpng-1.5.11/contrib/pngminus/pnm2png.c @ 248419a

Last change on this file since 248419a was 248419a, checked in by Sebastian Huber <sebastian.huber@…>, on 07/12/12 at 07:28:02

Update libpng from 1.2.41 to 1.5.11

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