w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

pnmtopng.c
Go to the documentation of this file.
1 /*
2 ** pnmtopng.c -
3 ** read a portable anymap and produce a Portable Network Graphics file
4 **
5 ** derived from pnmtorast.c (c) 1990,1991 by Jef Poskanzer and some
6 ** parts derived from ppmtogif.c by Marcel Wijkstra <wijkstra@fwi.uva.nl>
7 ** thanks to Greg Roelofs <newt@pobox.com> for contributions and bug-fixes
8 **
9 ** Copyright (C) 1995-1998 by Alexander Lehmann <alex@hal.rhein-main.de>
10 ** and Willem van Schaik <willem@schaik.com>
11 **
12 ** Permission to use, copy, modify, and distribute this software and its
13 ** documentation for any purpose and without fee is hereby granted, provided
14 ** that the above copyright notice appear in all copies and that both that
15 ** copyright notice and this permission notice appear in supporting
16 ** documentation. This software is provided "as is" without express or
17 ** implied warranty.
18 */
19 
20 #define VERSION "2.37.3 (13 July 1999) +netpbm"
21 
22 /*
23  BJH 20000408: remove BIGGRAYS stuff -- it's not an option anymore.
24  MAXMAXVAL renamed to OVERALLMAXVAL.
25  BJH 20000303: fix include statement so dependencies work out right.
26 */
27 
28 /* GRR 19990713: fixed redundant freeing of png_ptr and info_ptr in setjmp()
29  * blocks and added png_destroy_write_struct() and pm_close(ifp) in each
30  * pm_error() block. */
31 
32 /* GRR 19990308: declared "clobberable" automatic variables in convertpnm()
33  * static to fix Solaris/gcc stack-corruption bug. Also installed custom
34  * error-handler to avoid jmp_buf size-related problems (i.e., jmp_buf
35  * compiled with one size in libpng and another size here). */
36 
37 /* GRR 19980621: moved some if-tests out of full-image loops; added fix for
38  * following problem discovered by Magnus Holmgren and debugged by Glenn:
39  *
40  * The pnm has three colors: 0 0 0, 204 204 204, and 255 255 255.
41  * These were apparently scaled to 0 0 0, 12 12 12, and 15 15 15.
42  * That would have been OK if the file had been written as color-type
43  * 0 (grayscale), but it was written as an indexed-color file, in
44  * which the colors from the pnm file should have been used rather
45  * than the scaled colors. What appears in the PLTE chunk is
46  * 0 0 0, 12 12 12, and 15 15 15, which of course results in a
47  * very dark image.
48  *
49  * (temporarily ifdef'd for easier inspection and before/after testing)
50  */
51 #define GRR_GRAY_PALETTE_FIX
52 
53 #include <png.h> /* includes zlib.h and setjmp.h */
54 #include "pnm.h"
55 
56 #include "ppmcmap.h"
57 
58 typedef struct _jmpbuf_wrapper {
59  jmp_buf jmpbuf;
61 
62 #ifndef TRUE
63 # define TRUE 1
64 #endif
65 #ifndef FALSE
66 # define FALSE 0
67 #endif
68 #ifndef NONE
69 # define NONE 0
70 #endif
71 #define MAXCOLORS 256
72 #define MAXCOMMENTS 256
73 
74 /* function prototypes */
75 #ifdef __STDC__
76 static int closestcolor (pixel color, colorhist_vector chv, int colors,
77  xelval maxval);
78 static void read_text (png_info *info_ptr, FILE *tfp);
80 static void convertpnm (FILE *ifp, FILE *afp, FILE *tfp);
81 int main (int argc, char *argv[]);
82 #endif
83 
84 static int verbose = FALSE;
85 static int interlace = FALSE;
86 static int downscale = FALSE;
87 static int transparent = -1;
88 static char *transstring;
89 static int alpha = FALSE;
90 static char *alpha_file;
91 static int background = -1;
92 static char *backstring;
93 static float gamma = -1.0;
94 static int hist = FALSE;
95 static float chroma_wx = -1.0;
96 static float chroma_wy = -1.0;
97 static float chroma_rx = -1.0;
98 static float chroma_ry = -1.0;
99 static float chroma_gx = -1.0;
100 static float chroma_gy = -1.0;
101 static float chroma_bx = -1.0;
102 static float chroma_by = -1.0;
103 static int phys_x = -1.0;
104 static int phys_y = -1.0;
105 static int phys_unit = -1.0;
106 static int text = FALSE;
107 static int ztxt = FALSE;
108 static char *text_file;
109 static int mtime = FALSE;
110 static char *date_string;
111 static char *time_string;
112 static struct tm time_struct;
113 static int filter = -1;
114 static int compression = -1;
115 static int force = FALSE;
117 
118 #ifdef __STDC__
120 #else
121 static int closestcolor (color, chv, colors, maxval)
122 pixel color;
123 colorhist_vector chv;
124 int colors;
125 xelval maxval;
126 #endif
127 {
128  int i, r, g, b, d;
129  int imin, dmin;
130 
131  r = (int)PPM_GETR (color) * 255 / maxval;
132  g = (int)PPM_GETG (color) * 255 / maxval;
133  b = (int)PPM_GETB (color) * 255 / maxval;
134 
135  imin = 0;
136  dmin = 1000000;
137  for (i = 0 ; i < colors ; i++) {
138  d = (r - PPM_GETR (chv[i].color)) * (r - PPM_GETR (chv[i].color))+
139  (g - PPM_GETG (chv[i].color)) * (g - PPM_GETG (chv[i].color))+
140  (b - PPM_GETB (chv[i].color)) * (b - PPM_GETB (chv[i].color));
141  if (d < dmin) {
142  dmin = d;
143  imin = i;
144  }
145  }
146  return imin;
147 }
148 
149 #ifdef __STDC__
150 static void read_text (png_info *info_ptr, FILE *tfp)
151 #else
152 static void read_text (info_ptr, tfp)
153 png_info *info_ptr;
154 FILE *tfp;
155 #endif
156 {
157  char textline[256];
158  int textpos;
159  int i, j;
160  int c;
161  char *cp;
162 
163  /* GRR: need to check for malloc failure here */
164  info_ptr->text = (png_text *)malloc (MAXCOMMENTS * sizeof (png_text));
165  j = 0;
166  textpos = 0;
167  while ((c = getc (tfp)) != EOF) {
168  if (c != '\n' && c != EOF) {
169  textline[textpos++] = c;
170  } else {
171  textline[textpos++] = '\0';
172  if ((textline[0] != ' ') && (textline[0] != '\t')) {
173  /* the following is a not that accurate check on Author or Title */
174  if ((!ztxt) || (textline[0] == 'A') || (textline[0] == 'T'))
175  info_ptr->text[j].compression = -1;
176  else
177  info_ptr->text[j].compression = 0;
178  cp = malloc (textpos);
179  info_ptr->text[j].key = cp;
180  i = 0;
181  if (textline[0] == '"') {
182  i++;
183  while (textline[i] != '"' && textline[i] != '\n')
184  *(cp++) = textline[i++];
185  i++;
186  } else {
187  while (textline[i] != ' ' && textline[i] != '\t' && textline[i] != '\n')
188  *(cp++) = textline[i++];
189  }
190  *(cp++) = '\0';
191  cp = malloc (textpos);
192  info_ptr->text[j].text = cp;
193  while (textline[i] == ' ' || textline[i] == '\t')
194  i++;
195  strcpy (cp, &textline[i]);
196  info_ptr->text[j].text_length = strlen (cp);
197  j++;
198  } else {
199  j--;
200  cp = malloc (info_ptr->text[j].text_length + textpos);
201  strcpy (cp, info_ptr->text[j].text);
202  strcat (cp, "\n");
203  info_ptr->text[j].text = cp;
204  i = 0;
205  while (textline[i] == ' ' || textline[i] == '\t')
206  i++;
207  strcat (cp, &textline[i]);
208  info_ptr->text[j].text_length = strlen (cp);
209  j++;
210  }
211  textpos = 0;
212  }
213  } /* end while */
214  info_ptr->num_text = j;
215 }
216 
217 #ifdef __STDC__
219 #else
223 #endif
224 {
225  jmpbuf_wrapper *jmpbuf_ptr;
226 
227  /* this function, aside from the extra step of retrieving the "error
228  * pointer" (below) and the fact that it exists within the application
229  * rather than within libpng, is essentially identical to libpng's
230  * default error handler. The second point is critical: since both
231  * setjmp() and longjmp() are called from the same code, they are
232  * guaranteed to have compatible notions of how big a jmp_buf is,
233  * regardless of whether _BSD_SOURCE or anything else has (or has not)
234  * been defined. */
235 
236  fprintf(stderr, "pnmtopng: fatal libpng error: %s\n", msg);
237  fflush(stderr);
238 
239  jmpbuf_ptr = png_get_error_ptr(png_ptr);
240  if (jmpbuf_ptr == NULL) { /* we are completely hosed now */
241  fprintf(stderr,
242  "pnmtopng: EXTREMELY fatal error: jmpbuf unrecoverable; terminating.\n");
243  fflush(stderr);
244  exit(99);
245  }
246 
247  longjmp(jmpbuf_ptr->jmpbuf, 1);
248 }
249 
250 #ifdef __STDC__
251 static void convertpnm (FILE *ifp, FILE *afp, FILE *tfp)
252 #else
253 static void convertpnm (ifp, afp, tfp)
254 FILE *ifp;
255 FILE *afp;
256 FILE *tfp;
257 #endif
258 {
259  xel **xels; /* GRR: a xel is always a pixel; pixel may be ulg or struct */
260  xel p; /* (pnm.h) (ppm.h) */
261  int rows, cols, format;
262  xelval maxval;
263  long int scaleval;
264  /* bjh changed type of scaleval to avoid compiler warnings 00.03.02 */
265  xelval value;
266  pixel transcolor;
267  int mayscale;
269 
271  png_info *info_ptr;
272 
273  png_color palette[MAXCOLORS];
275  png_uint_16 histogram[MAXCOLORS];
276  png_byte *line;
277  png_byte *pp;
278  int pass;
279  int color;
280  gray alpha_maxval;
281  int alpha_rows;
282  int alpha_cols;
283  int alpha_trans;
284  gray *alphas_of_color[MAXCOLORS];
285  int alphas_of_color_cnt[MAXCOLORS];
286  int alphas_first_index[MAXCOLORS+1];
287  int mapping[MAXCOLORS];
288  int colors;
289  int fulldepth;
290  int x, y;
291  int i, j;
292 
293  /* these variables are declared static because gcc wasn't kidding
294  * about "variable XXX might be clobbered by `longjmp' or `vfork'"
295  * (stack corruption observed on Solaris 2.6 with gcc 2.8.1, even
296  * in the absence of any other error condition) */
297  static int pnm_type;
298  static xelval maxmaxval;
299  static int sbitval;
300  static gray **alpha_mask;
301  static int alpha_sbitval;
302  static int num_alphas_of_color;
303  static int palette_size;
304  static colorhist_vector chv;
305  static colorhash_table cht;
306  static int depth;
307 
308 
309  /* these guys are initialized to quiet compiler warnings: */
310  maxmaxval = 255;
311  num_alphas_of_color = 0;
312  alpha_mask = NULL;
313  alpha_sbitval = 0;
314  palette_size = 0;
315  cht = NULL;
316  depth = 0;
317 
320  if (png_ptr == NULL) {
321  pm_close (ifp);
322  pm_error ("cannot allocate LIBPNG structure");
323  }
324 
325  info_ptr = png_create_info_struct (png_ptr);
326  if (info_ptr == NULL) {
328  pm_close (ifp);
329  pm_error ("cannot allocate LIBPNG structures");
330  }
331 
332  if (setjmp (pnmtopng_jmpbuf_struct.jmpbuf)) {
333  png_destroy_write_struct (&png_ptr, &info_ptr);
334  pm_close (ifp);
335  pm_error ("setjmp returns error condition (1)");
336  }
337 
338  xels = pnm_readpnm (ifp, &cols, &rows, &maxval, &format);
339  pnm_type = PNM_FORMAT_TYPE (format);
340 
341  if (verbose) {
342  if (pnm_type == PBM_TYPE)
343  pm_message ("reading a PBM file (maxval=%d)", maxval);
344  else if (pnm_type == PGM_TYPE)
345  pm_message ("reading a PGM file (maxval=%d)", maxval);
346  else if (pnm_type == PPM_TYPE)
347  pm_message ("reading a PPM file (maxval=%d)", maxval);
348  }
349 
350  if (pnm_type == PGM_TYPE)
352  else if (pnm_type == PPM_TYPE)
354 
355  if (transparent > 0) /* -1 or 1 are the only possibilities so far */
356  transcolor = ppm_parsecolor (transstring, maxmaxval);
357 
358  if (alpha) {
359  alpha_mask = pgm_readpgm (afp, &alpha_cols, &alpha_rows, &alpha_maxval);
360  if (alpha_cols != cols || alpha_rows != rows) {
361  png_destroy_write_struct (&png_ptr, &info_ptr);
362  pm_close (ifp);
363  pm_error ("dimensions for image and alpha mask do not agree");
364  }
365  /* check if the alpha mask can be represented by a single transparency
366  value (i.e. all colors fully opaque except one fully transparent;
367  the transparent color may not also occur as fully opaque.
368  we have to do this before any scaling occurs, since alpha is only
369  possible with 8 and 16-bit */
370  /* first find the possible candidate */
371  alpha_trans = FALSE;
372  for (y = 0 ; y < rows && !alpha_trans ; y++)
373  for (x = 0 ; x < cols && !alpha_trans ; x++) {
374  if (alpha_mask[y][x] == 0) {
375  if (transparent < 0) {
376  alpha_trans = TRUE;
377  transparent = 2;
378  transcolor = xels[y][x];
379  }
380  }
381  }
382  /* if alpha_trans is TRUE check the whole image */
383  for (y = 0 ; y < rows && alpha_trans ; y++)
384  for (x = 0 ; x < cols && alpha_trans ; x++) {
385  if (alpha_mask[y][x] == 0) { /* transparent one */
386  if (pnm_type == PPM_TYPE) {
387  if (!PPM_EQUAL (xels[y][x], transcolor))
388  alpha_trans = FALSE;
389  } else {
390  if (PNM_GET1 (xels[y][x]) != PNM_GET1 (transcolor))
391  alpha_trans = FALSE;
392  }
393  } else /* is it fully opaque ? */
394  if (alpha_mask[y][x] != alpha_maxval) {
395  alpha_trans = FALSE;
396  } else /* does the transparent color also exists fully opaque */
397  if (pnm_type == PPM_TYPE) {
398  if (PPM_EQUAL (xels[y][x], transcolor))
399  alpha_trans = FALSE;
400  } else {
401  if (PNM_GET1 (xels[y][x]) == PNM_GET1 (transcolor))
402  alpha_trans = FALSE;
403  }
404  }
405  if (alpha_trans && !force) {
406  if (verbose)
407  pm_message ("converting alpha mask to transparency index");
408  alpha = FALSE;
409  } else {
410  transparent = -1;
411  }
412  }
413 
414  /* gcc 2.7.0 -fomit-frame-pointer causes stack corruption here */
415  if (background > -1) /* scale to maxval later: */
417 
418  /* first of all, check if we have a grayscale image written as PPM */
419 
420  if (pnm_type == PPM_TYPE && !force) {
421  int isgray = TRUE;
422 
423  for (y = 0 ; y < rows && isgray ; y++)
424  for (x = 0 ; x < cols && isgray ; x++) {
425  p = xels[y][x];
426  if (PPM_GETR (p) != PPM_GETG (p) || PPM_GETG (p) != PPM_GETB (p))
427  isgray = FALSE;
428  }
429  if (isgray)
430  pnm_type = PGM_TYPE;
431  }
432 
433  /* handle `odd' maxvalues */
434 
435  sbitval = 0;
436  if (pnm_type != PBM_TYPE || alpha) {
437  if (maxval > 65535 && !downscale) {
438  png_destroy_write_struct (&png_ptr, &info_ptr);
439  pm_close (ifp);
440  pm_error ("can only handle files up to 16-bit (use -downscale to override");
441  }
442 
443  if (maxval < 65536) {
444  sbitval = pm_maxvaltobits (maxval);
445  if (maxval != pm_bitstomaxval (sbitval))
446  sbitval = 0;
447  }
448 
449  if (maxval != 255 && maxval != 65535 &&
450  (alpha || pnm_type != PGM_TYPE ||
451  (maxval != 1 && maxval != 3 && maxval != 15))) {
452  if (!alpha && maxval == 7 && pnm_type == PGM_TYPE) {
453  if (verbose)
454  pm_message ("rescaling to 4-bit");
455  scaleval = 15;
456  } else
457  if (maxval < 255) {
458  if (verbose)
459  pm_message ("rescaling to 8-bit");
460  scaleval = 255;
461  } else {
462  /* to do: this can fail; xels aren't big enough - larger pixels &
463  * maxvals are needed */
464  if (sizeof(maxval) < 2) { /* unsigned char by default */
465  pm_message ("cannot rescale to 16-bit; "
466  "rescaling to 8-bit instead (maxval = %d)",
467  maxval);
468  scaleval = 255;
469  } else {
470  if (verbose)
471  pm_message ("rescaling to 16-bit");
472  scaleval = 65535;
473  }
474  }
475  for (y = 0 ; y < rows ; y++)
476  for (x = 0 ; x < cols ; x++) {
477  p = xels[y][x];
478  PPM_DEPTH (xels[y][x], p, maxval, scaleval);
479  }
480  if (transparent == 2) { /* "1" case (-transparent) handled below */
481  PPM_DEPTH (transcolor, transcolor, maxval, scaleval);
482  }
483  maxval = scaleval;
484  } else {
485  sbitval = 0; /* no scaling happened */
486  }
487  }
488 
489  /* now do a real scaling (better than ppm_parsecolor()) */
490 
491  if (maxval != 65535) {
492  if (background > -1)
494  if (transparent == 1) /* "2" case (-alpha) already done */
495  PPM_DEPTH (transcolor, transcolor, maxmaxval, maxval);
496  }
497 
498  /* check for 16-bit entries that are just scaled 8-bit entries, e.g.,
499  when converting an 8-bit palette TIFF to PPM */
500 
501  if (pnm_type != PBM_TYPE && maxval == 65535 && !force) {
502  mayscale = TRUE;
503  if (pnm_type == PGM_TYPE)
504  for (y = 0 ; y < rows && mayscale ; y++)
505  for (x = 0 ; x < cols && mayscale ; x++) {
506  p = xels[y][x];
507  if ( (PNM_GET1 (p)&0xff)*0x101 != PNM_GET1 (p) )
508  mayscale = FALSE;
509  }
510  else /* PPM_TYPE */
511  for (y = 0 ; y < rows && mayscale ; y++)
512  for (x = 0 ; x < cols && mayscale ; x++) {
513  p = xels[y][x];
514  if ( (PPM_GETR (p)&0xff)*0x101 != PPM_GETR (p) ||
515  (PPM_GETG (p)&0xff)*0x101 != PPM_GETG (p) ||
516  (PPM_GETB (p)&0xff)*0x101 != PPM_GETB (p) )
517  mayscale = FALSE;
518  }
519  if (mayscale) {
520  if (verbose)
521  pm_message ("scaling to 8-bit (superfluous 16-bit data)");
522  maxval = 255;
523  if (pnm_type == PGM_TYPE) {
524  for (y = 0 ; y < rows ; y++)
525  for (x = 0 ; x < cols ; x++) {
526  p = xels[y][x];
527  PNM_ASSIGN1 (xels[y][x], PNM_GET1 (p)&0xff);
528  }
529  } else { /* PPM_TYPE */
530  for (y = 0 ; y < rows ; y++)
531  for (x = 0 ; x < cols ; x++) {
532  p = xels[y][x];
533  PPM_ASSIGN (xels[y][x], PPM_GETR (p)&0xff, PPM_GETG (p)&0xff,
534  PPM_GETB (p)&0xff);
535  }
536  }
537  if (transparent > 0) {
538  p = transcolor;
539  if (pnm_type == PGM_TYPE) {
540  PNM_ASSIGN1 (transcolor, PNM_GET1 (p)&0xff);
541  } else {
542  PPM_ASSIGN (transcolor, PPM_GETR (p)&0xff, PPM_GETG (p)&0xff,
543  PPM_GETB (p)&0xff);
544  }
545  }
546 
547  if (sbitval > 0) sbitval >>= 1;
548  }
549  }
550 
551  /* scale alpha mask to match bit depth of image */
552 
553  if (alpha) {
554  if (alpha_maxval < 65536) {
555  alpha_sbitval = pm_maxvaltobits (alpha_maxval);
556  if (alpha_maxval != pm_bitstomaxval (alpha_sbitval))
557  alpha_sbitval = 0;
558  } else
559  alpha_sbitval = 0;
560 
561  if (alpha_maxval != maxval) {
562  if (verbose)
563  pm_message ("rescaling alpha mask to match image bit depth");
564  for (y = 0 ; y < rows ; y++)
565  for (x = 0 ; x < cols ; x++)
566  alpha_mask[y][x] = (alpha_mask[y][x] * maxval + alpha_maxval / 2) /
567  alpha_maxval;
568  alpha_maxval = maxval;
569  } else {
570  alpha_sbitval = 0; /* no scaling happened */
571  }
572  }
573 
574  /* now do scaling for grayscale pics of bit-depth 4, 2 and 1, but only
575  when we don't have an alpha channel */
576 
577  if (!alpha && pnm_type == PGM_TYPE && !force) {
578  if (maxval == 255) {
579  mayscale = TRUE;
580  for (y = 0 ; y < rows && mayscale ; y++)
581  for (x = 0 ; x < cols && mayscale ; x++) {
582  if ((PNM_GET1 (xels[y][x]) & 0xf) * 0x11 != PNM_GET1 (xels[y][x]))
583  mayscale = FALSE;
584  }
585  if (mayscale) {
586  for (y = 0 ; y < rows ; y++)
587  for (x = 0 ; x < cols ; x++) {
588  PNM_ASSIGN1 (xels[y][x], PNM_GET1 (xels[y][x])&0xf);
589  }
590 
591  if (transparent > 0) {
592  PNM_ASSIGN1 (transcolor, PNM_GET1 (transcolor)&0xf);
593  }
594 
595  maxval = 15;
596  if (verbose)
597  pm_message ("scaling to 4-bit (grayscale superfluous data)");
598  if (sbitval > 0) sbitval >>= 1;
599  }
600  }
601 
602  if (maxval == 15) {
603  mayscale = TRUE;
604  for (y = 0 ; y < rows && mayscale ; y++)
605  for (x = 0 ; x < cols && mayscale ; x++) {
606  if ((PNM_GET1 (xels[y][x])&3) * 5 != PNM_GET1 (xels[y][x]))
607  mayscale = FALSE;
608  }
609  if (mayscale) {
610  for (y = 0 ; y < rows ; y++)
611  for (x = 0 ; x < cols ; x++) {
612  PNM_ASSIGN1 (xels[y][x], PNM_GET1 (xels[y][x]) & 3);
613  }
614  if (transparent > 0) {
615  PNM_ASSIGN1 (transcolor, PNM_GET1 (transcolor) & 3);
616  }
617  maxval = 3;
618  if (verbose)
619  pm_message ("scaling to 2-bit (grayscale superfluous data)");
620  if (sbitval > 0) sbitval >>= 1;
621  }
622  }
623 
624  if (maxval == 3) {
625  mayscale = TRUE;
626  for (y = 0 ; y < rows && mayscale ; y++)
627  for (x = 0 ; x < cols && mayscale ; x++) {
628  if ((PNM_GET1 (xels[y][x])&1) * 3 != PNM_GET1 (xels[y][x]))
629  mayscale = FALSE;
630  }
631  if (mayscale) {
632  for (y = 0 ; y < rows ; y++)
633  for (x = 0 ; x < cols ; x++) {
634  PNM_ASSIGN1 (xels[y][x], PNM_GET1 (xels[y][x])&1);
635  }
636  if (transparent > 0) {
637  PNM_ASSIGN1 (transcolor, PNM_GET1 (transcolor) & 1);
638  }
639  maxval = 1;
640  if (verbose)
641  pm_message ("scaling to 1-bit (grayscale superfluous data)");
642  sbitval = 0;
643  }
644  }
645  }
646 
647  /*
648  We can write a palette file if maxval <= 255 and one of the following is
649  true:
650  - for ppm files if we have <= 256 colors
651  - for alpha if we have <= 256 color/transparency pairs
652  - for pgm files (with or without alpha) if the number of bits needed for
653  the gray-transparency pairs is smaller then the number of bits needed
654  for maxval
655  When maxval > 255, we never write a paletted image.
656  */
657 
658  if ((!force) && (pnm_type != PBM_TYPE) && (maxval <= 255)) {
659  if (verbose) {
660  pm_message ("maxval is %d", maxval);
661  pm_message ("computing colormap...");
662  }
663  /* for the palette check, we have to copy the grayscale values to the RGB
664  channels if we want to apply ppm-functions to grayscale images */
665  if (pnm_type == PGM_TYPE) {
666  for (y = 0 ; y < rows ; y++)
667  for (x = 0 ; x < cols ; x++) {
668  value = PNM_GET1 (xels[y][x]);
669  PPM_ASSIGN (xels[y][x], value, value, value);
670  }
671  }
672  chv = ppm_computecolorhist (xels, cols, rows, MAXCOLORS, &colors);
673  if (verbose) {
674  pm_message ("%d colors found", colors);
675  }
676  if ((chv == (colorhist_vector) NULL) || /* GRR: v--- was `=' here */
677  (pnm_type == PGM_TYPE && pm_maxvaltobits(colors) >
678  (pm_maxvaltobits(maxval) / 2)) ||
679  (pnm_type == PPM_TYPE && maxval > 255)) {
680  chv = NULL;
681  if (verbose) {
682  pm_message ("too many colors for writing a colormapped image");
683  }
684  }
685 
686  if (chv != (colorhist_vector) NULL) {
687 
688  if (alpha) {
689  /* now check if there are different alpha values for the same color
690  and if all pairs still fit into 256 (MAXCOLORS) entries; malloc
691  one extra for possible background color */
693  for (i = 0 ; i < colors + 1 ; i++) {
694  if ((alphas_of_color[i] = (gray *)malloc (MAXCOLORS * sizeof (int)))
695  == NULL)
696  {
697  png_destroy_write_struct (&png_ptr, &info_ptr);
698  pm_close (ifp);
699  pm_error ("out of memory allocating alpha/palette entries");
700  }
701  alphas_of_color_cnt[i] = 0;
702  }
703  num_alphas_of_color = colors + 1;
704  for (y = 0 ; y < rows ; y++) {
705  for (x = 0 ; x < cols ; x++) {
706  color = ppm_lookupcolor (cht, &xels[y][x]);
707  for (i = 0 ; i < alphas_of_color_cnt[color] ; i++) {
708  if (alpha_mask[y][x] == alphas_of_color[color][i])
709  break;
710  }
711  if (i == alphas_of_color_cnt[color]) {
712  alphas_of_color[color][i] = alpha_mask[y][x];
713  alphas_of_color_cnt[color]++;
714  }
715  }
716  }
717  alphas_first_index[0] = 0;
718  for (i = 0 ; i < colors ; i++)
719  alphas_first_index[i+1] = alphas_first_index[i] +
720  alphas_of_color_cnt[i];
721  if (verbose)
722  pm_message ("number of color/transparency pairs is %d",
723  alphas_first_index[colors]);
724  if (alphas_first_index[colors] > MAXCOLORS) {
725  ppm_freecolorhist (chv);
726  chv = NULL;
727  if (verbose)
728  pm_message (
729  "too many color/transparency pairs, writing a non-mapped file");
730  }
731  } /* if alpha */
732 
733  /* add possible background color to palette */
734  if (background > -1) {
737  if (background == -1) {
738  if ((!alpha && colors < MAXCOLORS) ||
739  (alpha && alphas_first_index[colors] < MAXCOLORS))
740  {
741  background = colors;
743  colors);
744  if (alpha) {
745  alphas_of_color[background][0] = 255; /* opaque */
746  alphas_of_color_cnt[background] = 1; /* unique */
747  alphas_first_index[colors] = alphas_first_index[background] + 1;
748  }
749  if (verbose)
750  pm_message ("added background color to palette");
751  } else {
753  if (verbose)
754  pm_message ("no room in palette for background color; using closest match instead");
755  }
756  }
757  ppm_freecolorhash (cht); /* built again about 110 lines below */
758  }
759 
760  }
761  } else {
762  chv = NULL;
763  }
764 
765  if (chv) {
766  if (alpha)
767  palette_size = alphas_first_index[colors];
768  else
769  palette_size = colors;
770 
771 #ifdef GRR_GRAY_PALETTE_FIX
772  if (maxval < 255) {
773  if (verbose)
774  pm_message ("rescaling palette values to 8-bit");
775  for (i = 0 ; i < colors ; i++) {
776  p = chv[i].color;
777  PPM_DEPTH (chv[i].color, p, maxval, 255);
778  }
779  /* ...also image pixels so they still match the palette [inefficient!] */
780  for (y = 0 ; y < rows ; y++)
781  for (x = 0 ; x < cols ; x++) {
782  p = xels[y][x];
783  PPM_DEPTH (xels[y][x], p, maxval, 255);
784  }
785  maxval = 255; /* necessary for transparent case, at least */
786  }
787 #endif
788 
789  if (palette_size <= 2)
790  depth = 1;
791  else if (palette_size <= 4)
792  depth = 2;
793  else if (palette_size <= 16)
794  depth = 4;
795  else
796  depth = 8;
797  fulldepth = depth;
798  } else {
799  /* non-mapped color or grayscale */
800 
801  if (maxval == 65535)
802  depth = 16;
803  else if (maxval == 255)
804  depth = 8;
805  else if (maxval == 15)
806  depth = 4;
807  else if (maxval == 3)
808  depth = 2;
809  else if (maxval == 1)
810  depth = 1;
811  else {
812  png_destroy_write_struct (&png_ptr, &info_ptr);
813  pm_close (ifp);
814  pm_error (" (can't happen) undefined maxval");
815  }
816 
817  if (alpha) {
818  if (pnm_type == PPM_TYPE)
819  fulldepth = 4 * depth;
820  else
821  fulldepth = 2 * depth;
822  } else {
823  if (pnm_type == PPM_TYPE)
824  fulldepth = 3 * depth;
825  else
826  fulldepth = depth;
827  }
828  }
829 
830  if (verbose)
831  pm_message ("writing a%s %d-bit %s%s file%s",
832  fulldepth == 8 ? "n" : "", fulldepth,
833  chv ? "palette": (pnm_type == PPM_TYPE ? "RGB" : "gray"),
834  alpha ? (chv ? "+transparency" : "+alpha") : "",
835  interlace? " (interlaced)" : "");
836 
837  /* now write the file */
838 
839  if (setjmp (pnmtopng_jmpbuf_struct.jmpbuf)) {
840  png_destroy_write_struct (&png_ptr, &info_ptr);
841  pm_close (ifp);
842  pm_error ("setjmp returns error condition (2)");
843  }
844 
845 #ifdef OLDPNG
846  png_write_init (png_ptr);
847  png_info_init (info_ptr);
848 #endif
850  info_ptr->width = cols;
851  info_ptr->height = rows;
852  info_ptr->bit_depth = depth;
853 
854  if (chv != NULL)
855  info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
856  else if (pnm_type == PPM_TYPE)
857  info_ptr->color_type = PNG_COLOR_TYPE_RGB;
858  else
859  info_ptr->color_type = PNG_COLOR_TYPE_GRAY;
860 
861  if (alpha && info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
862  info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
863 
864  info_ptr->interlace_type = interlace;
865 
866  /* gAMA chunk */
867  if (gamma != -1.0) {
868  info_ptr->valid |= PNG_INFO_gAMA;
869  info_ptr->gamma = gamma;
870  }
871 
872  /* cHRM chunk */
873  if (chroma_wx != -1.0) {
874  info_ptr->valid |= PNG_INFO_cHRM;
875  info_ptr->x_white = chroma_wx;
876  info_ptr->y_white = chroma_wy;
877  info_ptr->x_red = chroma_rx;
878  info_ptr->y_red = chroma_ry;
879  info_ptr->x_green = chroma_gx;
880  info_ptr->y_green = chroma_gy;
881  info_ptr->x_blue = chroma_bx;
882  info_ptr->y_blue = chroma_by;
883  }
884 
885  /* pHYS chunk */
886  if (phys_unit != -1.0) {
887  info_ptr->valid |= PNG_INFO_pHYs;
888  info_ptr->x_pixels_per_unit = phys_x;
889  info_ptr->y_pixels_per_unit = phys_y;
890  info_ptr->phys_unit_type = phys_unit;
891  }
892 
893  /* PLTE chunk */
894  if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
896  /* before creating palette figure out the transparent color */
897  if (transparent > 0) {
898  transparent = ppm_lookupcolor (cht, &transcolor);
899  if (transparent == -1) {
900  transparent = closestcolor (transcolor, chv, colors, maxval);
901  transcolor = chv[transparent].color;
902  }
903  /* now put transparent color in entry 0 by swapping */
904  chv[transparent].color = chv[0].color;
905  chv[0].color = transcolor;
906  /* check if background color was by bad luck part of swap */
907  if (background == transparent)
908  background = 0;
909  else if (background == 0)
911  /* rebuild hashtable */
914  transparent = 0;
915  trans[0] = 0; /* fully transparent */
916  info_ptr->valid |= PNG_INFO_tRNS;
917  info_ptr->trans = trans;
918  info_ptr->num_trans = 1;
919  }
920 
921  /* creating PNG palette (tRNS *not* yet valid) */
922  if (alpha) {
923  int bot_idx = 0;
924  int top_idx = alphas_first_index[colors] - 1;
925 
926  /* remap palette indices so opaque entries are last (omittable) */
927  for (i = 0; i < colors; ++i) {
928  for (j = alphas_first_index[i]; j < alphas_first_index[i+1]; ++j) {
929  if (alphas_of_color[i][j-alphas_first_index[i]] == 255)
930  mapping[j] = top_idx--;
931  else
932  mapping[j] = bot_idx++;
933  }
934  }
935  /* indices should have just crossed paths */
936  if (bot_idx != top_idx + 1) {
937  png_destroy_write_struct (&png_ptr, &info_ptr);
938  pm_close (ifp);
939  pm_error ("internal inconsistency: remapped bot_idx = %d, top_idx = %d",
940  bot_idx, top_idx);
941  }
942  for (i = 0 ; i < colors ; i++) {
943  for (j = alphas_first_index[i] ; j < alphas_first_index[i+1] ; j++) {
944  palette[mapping[j]].red = PPM_GETR (chv[i].color);
945  palette[mapping[j]].green = PPM_GETG (chv[i].color);
946  palette[mapping[j]].blue = PPM_GETB (chv[i].color);
947  trans[mapping[j]] = alphas_of_color[i][j-alphas_first_index[i]];
948  }
949  }
950  info_ptr->valid |= PNG_INFO_tRNS;
951  info_ptr->trans = trans;
952  info_ptr->num_trans = bot_idx; /* omit opaque values */
953  pm_message ("writing %d non-opaque transparency values", bot_idx);
954  } else {
955  for (i = 0 ; i < MAXCOLORS ; i++) {
956  palette[i].red = PPM_GETR (chv[i].color);
957  palette[i].green = PPM_GETG (chv[i].color);
958  palette[i].blue = PPM_GETB (chv[i].color);
959  }
960  }
961  info_ptr->valid |= PNG_INFO_PLTE;
962  info_ptr->palette = palette;
963  info_ptr->num_palette = palette_size;
964 
965  /* creating hIST chunk */
966  if (hist) {
967  for (i = 0 ; i < MAXCOLORS ; i++)
968  histogram[i] = chv[i].value;
969  info_ptr->valid |= PNG_INFO_hIST;
970  info_ptr->hist = histogram;
971  if (verbose)
972  pm_message ("histogram created");
973  }
974  ppm_freecolorhist (chv);
975 
976  } else /* color_type != PNG_COLOR_TYPE_PALETTE */
977  if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) {
978  if (transparent > 0) {
979  info_ptr->valid |= PNG_INFO_tRNS;
980  info_ptr->trans_values.gray = PNM_GET1 (transcolor);
981  }
982  } else
983  if (info_ptr->color_type == PNG_COLOR_TYPE_RGB) {
984  if (transparent > 0) {
985  info_ptr->valid |= PNG_INFO_tRNS;
986  info_ptr->trans_values.red = PPM_GETR (transcolor);
987  info_ptr->trans_values.green = PPM_GETG (transcolor);
988  info_ptr->trans_values.blue = PPM_GETB (transcolor);
989  }
990  } else {
991  if (transparent > 0) {
992  png_destroy_write_struct (&png_ptr, &info_ptr);
993  pm_close (ifp);
994  pm_error (" (can't happen) transparency AND alpha");
995  }
996  }
997 
998  /* bKGD chunk */
999  if (background > -1) {
1000  info_ptr->valid |= PNG_INFO_bKGD;
1001  if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
1002  if (alpha)
1003  info_ptr->background.index = mapping[alphas_first_index[background]];
1004  else
1005  info_ptr->background.index = background;
1006  } else
1007  if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
1008  info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
1009  info_ptr->background.red = PPM_GETR (backcolor);
1010  info_ptr->background.green = PPM_GETG (backcolor);
1011  info_ptr->background.blue = PPM_GETB (backcolor);
1012  } else
1013  if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
1014  info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
1015  info_ptr->background.gray = PNM_GET1 (backcolor);
1016  }
1017  }
1018 
1019  /* sBIT chunk */
1020  if ((sbitval != 0) || (alpha && (alpha_sbitval != 0))) {
1021  info_ptr->valid |= PNG_INFO_sBIT;
1022 
1023  if (sbitval == 0)
1024  sbitval = pm_maxvaltobits (maxval);
1025  if (alpha_sbitval == 0)
1026  alpha_sbitval = pm_maxvaltobits (maxval);
1027 
1028  if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) {
1029  info_ptr->sig_bit.red = sbitval;
1030  info_ptr->sig_bit.green = sbitval;
1031  info_ptr->sig_bit.blue = sbitval;
1032  } else {
1033  info_ptr->sig_bit.gray = sbitval;
1034  }
1035 
1036  if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) {
1037  info_ptr->sig_bit.alpha = alpha_sbitval;
1038  }
1039  }
1040 
1041  /* tEXT and zTXT chunks */
1042  if ((text) || (ztxt)) {
1043  read_text (info_ptr, tfp);
1044  }
1045 
1046  /* tIME chunk */
1047  if (mtime) {
1048  info_ptr->valid |= PNG_INFO_tIME;
1049  sscanf (date_string, "%d-%d-%d", &time_struct.tm_year,
1050  &time_struct.tm_mon,
1051  &time_struct.tm_mday);
1052  if (time_struct.tm_year > 1900)
1053  time_struct.tm_year -= 1900;
1054  time_struct.tm_mon--; /* tm has monthes 0..11 */
1055  sscanf (time_string, "%d:%d:%d", &time_struct.tm_hour,
1056  &time_struct.tm_min,
1057  &time_struct.tm_sec);
1058  png_convert_from_struct_tm (&info_ptr->mod_time, &time_struct);
1059  }
1060 
1061  /* explicit filter-type (or none) required */
1062  if ((filter >= 0) && (filter <= 4))
1063  {
1065  }
1066 
1067  /* zlib compression-level (or none) required */
1068  if ((compression >= 0) && (compression <= 9))
1069  {
1071  }
1072 
1073  /* write the png-info struct */
1074  png_write_info (png_ptr, info_ptr);
1075 
1076  if ((text) || (ztxt))
1077  /* prevent from being written twice with png_write_end */
1078  info_ptr->num_text = 0;
1079 
1080  if (mtime)
1081  /* prevent from being written twice with png_write_end */
1082  info_ptr->valid &= ~~PNG_INFO_tIME;
1083 
1084  /* let libpng take care of, e.g., bit-depth conversions */
1086 
1087  /* max: 3 color channels, one alpha channel, 16-bit */
1088  if ((line = (png_byte *) malloc (cols*8)) == NULL)
1089  {
1090  png_destroy_write_struct (&png_ptr, &info_ptr);
1091  pm_close (ifp);
1092  pm_error ("out of memory allocating PNG row buffer");
1093  }
1094 
1095  for (pass = 0 ; pass < png_set_interlace_handling (png_ptr) ; pass++) {
1096  for (y = 0 ; y < rows ; y++) {
1097  pp = line;
1098  for (x = 0 ; x < cols ; x++) {
1099  p = xels[y][x];
1100  if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
1101  info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
1102  if (depth == 16)
1103  *pp++ = PNM_GET1 (p) >> 8;
1104  *pp++ = PNM_GET1 (p)&0xff;
1105  } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) {
1106  color = ppm_lookupcolor (cht, &p);
1107  if (alpha) {
1108  for (i = alphas_first_index[color] ;
1109  i < alphas_first_index[color+1] ; i++)
1110  if (alpha_mask[y][x] ==
1111  alphas_of_color[color][i - alphas_first_index[color]])
1112  {
1113  color = mapping[i];
1114  break;
1115  }
1116  }
1117  *pp++ = color;
1118  } else if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
1119  info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
1120  if (depth == 16)
1121  *pp++ = PPM_GETR (p) >> 8;
1122  *pp++ = PPM_GETR (p)&0xff;
1123  if (depth == 16)
1124  *pp++ = PPM_GETG (p) >> 8;
1125  *pp++ = PPM_GETG (p)&0xff;
1126  if (depth == 16)
1127  *pp++ = PPM_GETB (p) >> 8;
1128  *pp++ = PPM_GETB (p)&0xff;
1129  } else {
1130  png_destroy_write_struct (&png_ptr, &info_ptr);
1131  pm_close (ifp);
1132  pm_error (" (can't happen) undefined color_type");
1133  }
1134  if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) {
1135  if (depth == 16)
1136  *pp++ = alpha_mask[y][x] >> 8;
1137  *pp++ = alpha_mask[y][x]&0xff;
1138  }
1139  }
1141  }
1142  }
1143  png_write_end (png_ptr, info_ptr);
1145  /* flush first because free(png_ptr) can segfault due to jmpbuf problems
1146  in png_write_destroy */
1147  fflush (stdout);
1148  free (png_ptr);
1149  free (info_ptr);
1150  for (i = 0 ; i < num_alphas_of_color ; i++)
1151  free(alphas_of_color[i]);
1152 }
1153 
1154 #ifdef __STDC__
1155 int main (int argc, char *argv[])
1156 #else
1158 int argc;
1159 char *argv[];
1160 #endif
1161 {
1162  FILE *ifp, *tfp, *afp;
1163  int argn;
1164 
1165  char *usage = "[-verbose] [-downscale] [-interlace] [-alpha file] ...\n\
1166  ... [-transparent color] [-background color] [-gamma value] ...\n\
1167  ... [-hist] [-chroma wx wy rx ry gx gy bx by] [-phys x y unit] ...\n\
1168  ... [-text file] [-ztxt file] [-time [yy]yy-mm-dd hh:mm:ss] ...\n\
1169  ... [-filter 0..4] [-compression 0..9] [-force] [pnmfile]";
1170 
1171  pnm_init (&argc, argv);
1172  argn = 1;
1173 
1174  while (argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0') {
1175  if (pm_keymatch (argv[argn], "-verbose", 2)) {
1176  verbose = TRUE;
1177  } else
1178  if (pm_keymatch (argv[argn], "-downscale", 2)) {
1179  downscale = TRUE;
1180  } else
1181  if (pm_keymatch (argv[argn], "-interlace", 2)) {
1182  interlace = TRUE;
1183  } else
1184  if (pm_keymatch (argv[argn], "-alpha", 2)) {
1185  if (transparent > 0)
1186  pm_error ("-alpha and -transparent are mutually exclusive");
1187  alpha = TRUE;
1188  if (++argn < argc)
1189  alpha_file = argv[argn];
1190  else
1191  pm_usage (usage);
1192  } else
1193  if (pm_keymatch (argv[argn], "-transparent", 3)) {
1194  if (alpha)
1195  pm_error ("-alpha and -transparent are mutually exclusive");
1196  transparent = 1;
1197  if (++argn < argc)
1198  transstring = argv[argn];
1199  else
1200  pm_usage (usage);
1201  } else
1202  if (pm_keymatch (argv[argn], "-background", 2)) {
1203  background = 1;
1204  if (++argn < argc)
1205  backstring = argv[argn];
1206  else
1207  pm_usage (usage);
1208  } else
1209  if (pm_keymatch (argv[argn], "-gamma", 2)) {
1210  if (++argn < argc)
1211  sscanf (argv[argn], "%f", &gamma);
1212  else
1213  pm_usage (usage);
1214  } else
1215  if (pm_keymatch (argv[argn], "-hist", 2)) {
1216  hist = TRUE;
1217  } else
1218  if (pm_keymatch (argv[argn], "-chroma", 3)) {
1219  if (++argn < argc)
1220  sscanf (argv[argn], "%f", &chroma_wx);
1221  else
1222  pm_usage (usage);
1223  if (++argn < argc)
1224  sscanf (argv[argn], "%f", &chroma_wy);
1225  else
1226  pm_usage (usage);
1227  if (++argn < argc)
1228  sscanf (argv[argn], "%f", &chroma_rx);
1229  else
1230  pm_usage (usage);
1231  if (++argn < argc)
1232  sscanf (argv[argn], "%f", &chroma_ry);
1233  else
1234  pm_usage (usage);
1235  if (++argn < argc)
1236  sscanf (argv[argn], "%f", &chroma_gx);
1237  else
1238  pm_usage (usage);
1239  if (++argn < argc)
1240  sscanf (argv[argn], "%f", &chroma_gy);
1241  else
1242  pm_usage (usage);
1243  if (++argn < argc)
1244  sscanf (argv[argn], "%f", &chroma_bx);
1245  else
1246  pm_usage (usage);
1247  if (++argn < argc)
1248  sscanf (argv[argn], "%f", &chroma_by);
1249  else
1250  pm_usage (usage);
1251  } else
1252  if (pm_keymatch (argv[argn], "-phys", 3)) {
1253  if (++argn < argc)
1254  sscanf (argv[argn], "%d", &phys_x);
1255  else
1256  pm_usage (usage);
1257  if (++argn < argc)
1258  sscanf (argv[argn], "%d", &phys_y);
1259  else
1260  pm_usage (usage);
1261  if (++argn < argc)
1262  sscanf (argv[argn], "%d", &phys_unit);
1263  else
1264  pm_usage (usage);
1265  } else
1266  if (pm_keymatch (argv[argn], "-text", 3)) {
1267  text = TRUE;
1268  if (++argn < argc)
1269  text_file = argv[argn];
1270  else
1271  pm_usage (usage);
1272  } else
1273  if (pm_keymatch (argv[argn], "-ztxt", 2)) {
1274  ztxt = TRUE;
1275  if (++argn < argc)
1276  text_file = argv[argn];
1277  else
1278  pm_usage (usage);
1279  } else
1280  if (pm_keymatch (argv[argn], "-time", 3)) {
1281  mtime = TRUE;
1282  if (++argn < argc) {
1283  date_string = argv[argn];
1284  if (++argn < argc)
1285  time_string = argv[argn];
1286  else
1287  pm_usage (usage);
1288  } else {
1289  pm_usage (usage);
1290  }
1291  } else
1292  if (pm_keymatch (argv[argn], "-filter", 3)) {
1293  if (++argn < argc)
1294  {
1295  sscanf (argv[argn], "%d", &filter);
1296  if ((filter < 0) || (filter > 4))
1297  {
1298  pm_message
1299  ("filter must be 0 (none), 1 (sub), 2 (up), 3 (avg) or 4 (paeth)");
1300  pm_usage (usage);
1301  }
1302  }
1303  else
1304  pm_usage (usage);
1305  } else
1306  if (pm_keymatch (argv[argn], "-compression", 3)) {
1307  if (++argn < argc)
1308  {
1309  sscanf (argv[argn], "%d", &compression);
1310  if ((compression < 0) || (compression > 9))
1311  {
1312  pm_message ("zlib compression must be between 0 (none) and 9 (max)");
1313  pm_usage (usage);
1314  }
1315  }
1316  else
1317  pm_usage (usage);
1318  } else
1319  if (pm_keymatch (argv[argn], "-force", 3)) {
1320  force = TRUE;
1321  } else {
1322  fprintf(stderr,"pnmtopng version %s.\n", VERSION);
1323  fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
1325  fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
1327  fprintf(stderr,
1328  " Compiled with %d-bit netpbm support (PPM_OVERALLMAXVAL = %d).\n",
1330  fprintf(stderr, "\n");
1331  pm_usage (usage);
1332  }
1333  argn++;
1334  }
1335 
1336  if (argn != argc) {
1337  ifp = pm_openr (argv[argn]);
1338  ++argn;
1339  } else {
1340  ifp = stdin;
1341  }
1342  if (argn != argc)
1343  pm_usage (usage);
1344 
1345  if (alpha)
1346  afp = pm_openr (alpha_file);
1347  else
1348  afp = NULL;
1349 
1350  if ((text) || (ztxt))
1351  tfp = pm_openr (text_file);
1352  else
1353  tfp = NULL;
1354 
1355  convertpnm (ifp, afp, tfp);
1356 
1357  if (alpha)
1358  pm_close (afp);
1359  if ((text) || (ztxt))
1360  pm_close (tfp);
1361 
1362  pm_close (ifp);
1363  pm_close (stdout);
1364 
1365  exit (0);
1366 }
cp
Definition: action.c:1035
#define depth(a)
Definition: aptex-macros.h:199
static gray maxval
Definition: asciitopgm.c:38
#define b
Definition: jpegint.h:372
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
#define free(a)
Definition: decNumber.cpp:310
#define fflush
Definition: xxstdio.h:24
int sscanf()
char * strcpy()
#define dmin(a, b)
Definition: f2c.h:171
mpz_t pp
Definition: gen-psqr.c:108
static char usage[]
Definition: giftopnm.c:59
#define c(n)
Definition: gpos-common.c:150
#define d(n)
Definition: gpos-common.c:151
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
#define ZLIB_VERSION
Definition: zlib.h:40
void exit()
#define EOF
Definition: afmparse.c:59
kerning y
Definition: ttdriver.c:212
void png_init_io(png_structrp png_ptr, png_FILE_p fp)
Definition: png.c:703
png_infop png_create_info_struct(png_const_structrp png_ptr)
Definition: png.c:354
#define PNG_INFO_cHRM
Definition: png.h:734
void() png_set_filter(png_structrp png_ptr, int method, int filters)
Definition: pngwrite.c:1000
void() png_write_row(png_structrp png_ptr, png_const_bytep row)
Definition: pngwrite.c:698
#define PNG_INFO_gAMA
Definition: png.h:732
#define PNG_COLOR_TYPE_RGB
Definition: png.h:670
void() png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
Definition: pngwrite.c:979
int() png_set_interlace_handling(png_structrp png_ptr)
Definition: pngtrans.c:99
#define PNG_INFO_pHYs
Definition: png.h:739
void() png_write_end(png_structrp png_ptr, png_inforp info_ptr)
Definition: pngwrite.c:358
png_structp() png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn)
Definition: pngwrite.c:499
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition: png.h:671
#define PNG_COLOR_TYPE_GRAY_ALPHA
Definition: png.h:672
void() png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
Definition: pngwrite.c:192
#define PNG_COLOR_MASK_COLOR
Definition: png.h:664
void() png_set_compression_level(png_structrp png_ptr, int level)
Definition: pngwrite.c:1158
#define PNG_INFO_tIME
Definition: png.h:741
void() png_set_packing(png_structrp png_ptr)
Definition: pngtrans.c:50
#define PNG_COLOR_MASK_ALPHA
Definition: png.h:665
#define PNG_INFO_sBIT
Definition: png.h:733
#define PNG_INFO_tRNS
Definition: png.h:736
void() png_convert_from_struct_tm(png_timep ptime, const struct tm *ttime)
#define PNG_COLOR_TYPE_GRAY
Definition: png.h:668
#define PNG_INFO_bKGD
Definition: png.h:737
#define PNG_INFO_hIST
Definition: png.h:738
#define PNG_INFO_PLTE
Definition: png.h:735
#define PNG_COLOR_TYPE_PALETTE
Definition: png.h:669
#define PNG_LIBPNG_VER_STRING
Definition: png.h:281
png_voidp() png_get_error_ptr(png_const_structrp png_ptr)
Definition: pngerror.c:856
unsigned short png_uint_16
Definition: pngconf.h:497
unsigned char png_byte
Definition: pngconf.h:481
const char * png_const_charp
Definition: pngconf.h:590
static void png_write_destroy(png_structrp png_ptr)
Definition: pngwrite.c:939
#define zlib_version
Definition: zlib.h:214
#define getc
Definition: line.c:39
#define fprintf
Definition: mendex.h:64
#define malloc
Definition: alloca.c:91
#define png_ptr(N)
Definition: image.h:99
FILE * text_file
Definition: tie.c:122
static struct tm tm
Definition: localtime.c:216
FILE * afp
Definition: main-euc.c:12
int imin(int x, int y)
char png_libpng_ver[]
Definition: mplibstuff.c:112
float x
Definition: cordic.py:15
char msg[512]
Definition: nsfix.c:80
union value value
Definition: obx.h:44
void pm_usage(char *usage)
Definition: libpbm1.c:343
int pm_maxvaltobits(int maxval)
Definition: libpbm1.c:160
FILE * pm_openr(char *name)
Definition: libpbm1.c:600
int pm_bitstomaxval(int bits)
Definition: libpbm1.c:201
#define PBM_TYPE
Definition: pbm.h:21
static int rows
Definition: pbmclean.c:15
static int format
Definition: pbmclean.c:15
static bit backcolor
Definition: pbmmask.c:20
static int cols
Definition: pbmmask.c:21
gray ** pgm_readpgm(FILE *file, int *colsP, int *rowsP, gray *maxvalP)
Definition: libpgm1.c:155
#define PGM_TYPE
Definition: pgm.h:45
unsigned int gray
Definition: pgm.h:10
#define PGM_OVERALLMAXVAL
Definition: pgm.h:34
#define pm_error
Definition: png22pnm.c:118
#define pm_keymatch(stra, strb, _x)
Definition: png22pnm.c:121
#define pnm_init(_a, _b)
Definition: png22pnm.c:114
#define pm_close(file)
Definition: png22pnm.c:120
#define pm_message
Definition: png22pnm.c:116
static png_uint_16 maxmaxval
Definition: pngtopnm.c:67
xel ** pnm_readpnm(FILE *file, int *colsP, int *rowsP, xelval *maxvalP, int *formatP)
Definition: libpnm1.c:114
#define PNM_ASSIGN1(x, v)
Definition: pnm.h:13
#define PNM_GET1(x)
Definition: pnm.h:12
#define PNM_FORMAT_TYPE(f)
Definition: pnm.h:15
pixval xelval
Definition: pnm.h:9
static int compression
Definition: pnmtopng.c:114
static void pnmtopng_error_handler(png_structp png_ptr, png_const_charp msg)
Definition: pnmtopng.c:220
static int verbose
Definition: pnmtopng.c:84
static float chroma_gx
Definition: pnmtopng.c:99
static int downscale
Definition: pnmtopng.c:86
#define VERSION
Definition: pnmtopng.c:20
static int interlace
Definition: pnmtopng.c:85
static void convertpnm(FILE *ifp, FILE *afp, FILE *tfp)
Definition: pnmtopng.c:253
static float chroma_by
Definition: pnmtopng.c:102
static char * alpha_file
Definition: pnmtopng.c:90
static int mtime
Definition: pnmtopng.c:109
static int closestcolor(pixel color, colorhist_vector chv, int colors, xelval maxval)
Definition: pnmtopng.c:121
static void read_text(png_info *info_ptr, FILE *tfp)
Definition: pnmtopng.c:152
static float gamma
Definition: pnmtopng.c:93
static int force
Definition: pnmtopng.c:115
static int phys_unit
Definition: pnmtopng.c:105
#define MAXCOMMENTS
Definition: pnmtopng.c:72
#define MAXCOLORS
Definition: pnmtopng.c:71
static int transparent
Definition: pnmtopng.c:87
static char * date_string
Definition: pnmtopng.c:110
static float chroma_wx
Definition: pnmtopng.c:95
static float chroma_rx
Definition: pnmtopng.c:97
static float chroma_bx
Definition: pnmtopng.c:101
static struct tm time_struct
Definition: pnmtopng.c:112
static int phys_x
Definition: pnmtopng.c:103
static int alpha
Definition: pnmtopng.c:89
static float chroma_ry
Definition: pnmtopng.c:98
static int phys_y
Definition: pnmtopng.c:104
static int ztxt
Definition: pnmtopng.c:107
static int hist
Definition: pnmtopng.c:94
static char * text_file
Definition: pnmtopng.c:108
static char * backstring
Definition: pnmtopng.c:92
static char * transstring
Definition: pnmtopng.c:88
static int background
Definition: pnmtopng.c:91
static float chroma_wy
Definition: pnmtopng.c:96
static jmpbuf_wrapper pnmtopng_jmpbuf_struct
Definition: pnmtopng.c:116
struct _jmpbuf_wrapper jmpbuf_wrapper
static int filter
Definition: pnmtopng.c:113
static float chroma_gy
Definition: pnmtopng.c:100
static char * time_string
Definition: pnmtopng.c:111
int main(int argc, argv)
Definition: pnmtopng.c:1157
void ppm_addtocolorhist(colorhist_vector chv, int *colorsP, int maxcolors, pixel *colorP, int value, int position)
Definition: libppm3.c:45
int ppm_lookupcolor(colorhash_table cht, pixel *colorP)
Definition: libppm3.c:226
void ppm_freecolorhist(colorhist_vector chv)
Definition: libppm3.c:242
colorhist_vector ppm_computecolorhist(pixel **pixels, int cols, int rows, int maxcolors, int *colorsP)
Definition: libppm3.c:28
colorhash_table ppm_colorhisttocolorhash(colorhist_vector chv, int colors)
Definition: libppm3.c:193
void ppm_freecolorhash(colorhash_table cht)
Definition: libppm3.c:249
pixel ppm_parsecolor(char *colorname, pixval maxval)
Definition: libppm4.c:139
#define PPM_GETR(p)
Definition: ppm.h:36
#define PPM_ASSIGN(p, red, grn, blu)
Definition: ppm.h:46
#define PPM_OVERALLMAXVAL
Definition: ppm.h:30
#define PPM_GETG(p)
Definition: ppm.h:37
#define PPM_EQUAL(p, q)
Definition: ppm.h:47
#define PPM_DEPTH(newp, p, oldmaxval, newmaxval)
Definition: ppm.h:95
#define PPM_GETB(p)
Definition: ppm.h:38
#define PPM_TYPE
Definition: ppm.h:59
int g
Definition: ppmqvga.c:68
int r
Definition: ppmqvga.c:68
static colorhash_table cht
Definition: ppmtoacad.c:34
int colors
Definition: ppmtogif.c:51
char line[1024]
Definition: process_score.c:29
#define isgray(x)
Definition: lgc.h:89
jmp_buf jmpbuf
Definition: pngtopnm.c:38
Definition: pdfdev.c:706
pixel color
Definition: ppmcmap.h:9
Definition: bdf.c:133
Definition: texview.c:48
Definition: ppm.h:33
png_byte blue
Definition: png.h:482
png_byte red
Definition: png.h:480
png_byte green
Definition: png.h:481
int width
Definition: pngimage.h:56
int height
Definition: pngimage.h:57
#define FILE
Definition: t1stdio.h:34
int j
Definition: t4ht.c:1589
*job_name strlen((char *) job_name) - 4)
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
FILE * ifp
Definition: t1asm.c:88
int mapping
Definition: ttf2pfb.c:116
Definition: obx.h:51
#define argv
Definition: xmain.c:270
#define argc
Definition: xmain.c:269
static zic_t trans[50]
Definition: zic.c:412
#define argn