1*a67afe4dSAndroid Build Coastguard Worker /*
2*a67afe4dSAndroid Build Coastguard Worker * png2pnm.c --- conversion from PNG-file to PGM/PPM-file
3*a67afe4dSAndroid Build Coastguard Worker * copyright (C) 1999-2019 by Willem van Schaik <willem at schaik dot com>
4*a67afe4dSAndroid Build Coastguard Worker *
5*a67afe4dSAndroid Build Coastguard Worker * This software is released under the MIT license. For conditions of
6*a67afe4dSAndroid Build Coastguard Worker * distribution and use, see the LICENSE file part of this package.
7*a67afe4dSAndroid Build Coastguard Worker */
8*a67afe4dSAndroid Build Coastguard Worker
9*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
10*a67afe4dSAndroid Build Coastguard Worker #include <stdlib.h>
11*a67afe4dSAndroid Build Coastguard Worker #include <fcntl.h>
12*a67afe4dSAndroid Build Coastguard Worker
13*a67afe4dSAndroid Build Coastguard Worker #ifndef BOOL
14*a67afe4dSAndroid Build Coastguard Worker #define BOOL unsigned char
15*a67afe4dSAndroid Build Coastguard Worker #endif
16*a67afe4dSAndroid Build Coastguard Worker #ifndef TRUE
17*a67afe4dSAndroid Build Coastguard Worker #define TRUE ((BOOL) 1)
18*a67afe4dSAndroid Build Coastguard Worker #endif
19*a67afe4dSAndroid Build Coastguard Worker #ifndef FALSE
20*a67afe4dSAndroid Build Coastguard Worker #define FALSE ((BOOL) 0)
21*a67afe4dSAndroid Build Coastguard Worker #endif
22*a67afe4dSAndroid Build Coastguard Worker
23*a67afe4dSAndroid Build Coastguard Worker #include "png.h"
24*a67afe4dSAndroid Build Coastguard Worker
25*a67afe4dSAndroid Build Coastguard Worker /* function prototypes */
26*a67afe4dSAndroid Build Coastguard Worker
27*a67afe4dSAndroid Build Coastguard Worker int main (int argc, char *argv[]);
28*a67afe4dSAndroid Build Coastguard Worker void usage ();
29*a67afe4dSAndroid Build Coastguard Worker BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file,
30*a67afe4dSAndroid Build Coastguard Worker BOOL raw, BOOL alpha);
31*a67afe4dSAndroid Build Coastguard Worker BOOL do_png2pnm (png_struct *png_ptr, png_info *info_ptr,
32*a67afe4dSAndroid Build Coastguard Worker FILE *pnm_file, FILE *alpha_file,
33*a67afe4dSAndroid Build Coastguard Worker BOOL raw, BOOL alpha);
34*a67afe4dSAndroid Build Coastguard Worker
35*a67afe4dSAndroid Build Coastguard Worker /*
36*a67afe4dSAndroid Build Coastguard Worker * main
37*a67afe4dSAndroid Build Coastguard Worker */
38*a67afe4dSAndroid Build Coastguard Worker
main(int argc,char * argv[])39*a67afe4dSAndroid Build Coastguard Worker int main (int argc, char *argv[])
40*a67afe4dSAndroid Build Coastguard Worker {
41*a67afe4dSAndroid Build Coastguard Worker FILE *fp_rd = stdin;
42*a67afe4dSAndroid Build Coastguard Worker FILE *fp_wr = stdout;
43*a67afe4dSAndroid Build Coastguard Worker FILE *fp_al = NULL;
44*a67afe4dSAndroid Build Coastguard Worker const char *fname_wr = NULL;
45*a67afe4dSAndroid Build Coastguard Worker const char *fname_al = NULL;
46*a67afe4dSAndroid Build Coastguard Worker BOOL raw = TRUE;
47*a67afe4dSAndroid Build Coastguard Worker BOOL alpha = FALSE;
48*a67afe4dSAndroid Build Coastguard Worker int argi;
49*a67afe4dSAndroid Build Coastguard Worker int ret;
50*a67afe4dSAndroid Build Coastguard Worker
51*a67afe4dSAndroid Build Coastguard Worker for (argi = 1; argi < argc; argi++)
52*a67afe4dSAndroid Build Coastguard Worker {
53*a67afe4dSAndroid Build Coastguard Worker if (argv[argi][0] == '-')
54*a67afe4dSAndroid Build Coastguard Worker {
55*a67afe4dSAndroid Build Coastguard Worker switch (argv[argi][1])
56*a67afe4dSAndroid Build Coastguard Worker {
57*a67afe4dSAndroid Build Coastguard Worker case 'n':
58*a67afe4dSAndroid Build Coastguard Worker raw = FALSE;
59*a67afe4dSAndroid Build Coastguard Worker break;
60*a67afe4dSAndroid Build Coastguard Worker case 'r':
61*a67afe4dSAndroid Build Coastguard Worker raw = TRUE;
62*a67afe4dSAndroid Build Coastguard Worker break;
63*a67afe4dSAndroid Build Coastguard Worker case 'a':
64*a67afe4dSAndroid Build Coastguard Worker alpha = TRUE;
65*a67afe4dSAndroid Build Coastguard Worker argi++;
66*a67afe4dSAndroid Build Coastguard Worker if ((fp_al = fopen (argv[argi], "wb")) == NULL)
67*a67afe4dSAndroid Build Coastguard Worker {
68*a67afe4dSAndroid Build Coastguard Worker fname_al = argv[argi];
69*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNM2PNG\n");
70*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Error: cannot create alpha-channel file %s\n",
71*a67afe4dSAndroid Build Coastguard Worker argv[argi]);
72*a67afe4dSAndroid Build Coastguard Worker exit (1);
73*a67afe4dSAndroid Build Coastguard Worker }
74*a67afe4dSAndroid Build Coastguard Worker break;
75*a67afe4dSAndroid Build Coastguard Worker case 'h':
76*a67afe4dSAndroid Build Coastguard Worker case '?':
77*a67afe4dSAndroid Build Coastguard Worker usage ();
78*a67afe4dSAndroid Build Coastguard Worker exit (0);
79*a67afe4dSAndroid Build Coastguard Worker break;
80*a67afe4dSAndroid Build Coastguard Worker default:
81*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
82*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Error: unknown option %s\n", argv[argi]);
83*a67afe4dSAndroid Build Coastguard Worker usage ();
84*a67afe4dSAndroid Build Coastguard Worker exit (1);
85*a67afe4dSAndroid Build Coastguard Worker break;
86*a67afe4dSAndroid Build Coastguard Worker } /* end switch */
87*a67afe4dSAndroid Build Coastguard Worker }
88*a67afe4dSAndroid Build Coastguard Worker else if (fp_rd == stdin)
89*a67afe4dSAndroid Build Coastguard Worker {
90*a67afe4dSAndroid Build Coastguard Worker if ((fp_rd = fopen (argv[argi], "rb")) == NULL)
91*a67afe4dSAndroid Build Coastguard Worker {
92*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
93*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Error: file %s does not exist\n", argv[argi]);
94*a67afe4dSAndroid Build Coastguard Worker exit (1);
95*a67afe4dSAndroid Build Coastguard Worker }
96*a67afe4dSAndroid Build Coastguard Worker }
97*a67afe4dSAndroid Build Coastguard Worker else if (fp_wr == stdout)
98*a67afe4dSAndroid Build Coastguard Worker {
99*a67afe4dSAndroid Build Coastguard Worker fname_wr = argv[argi];
100*a67afe4dSAndroid Build Coastguard Worker if ((fp_wr = fopen (argv[argi], "wb")) == NULL)
101*a67afe4dSAndroid Build Coastguard Worker {
102*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
103*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Error: cannot create file %s\n", argv[argi]);
104*a67afe4dSAndroid Build Coastguard Worker exit (1);
105*a67afe4dSAndroid Build Coastguard Worker }
106*a67afe4dSAndroid Build Coastguard Worker }
107*a67afe4dSAndroid Build Coastguard Worker else
108*a67afe4dSAndroid Build Coastguard Worker {
109*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
110*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Error: too many parameters\n");
111*a67afe4dSAndroid Build Coastguard Worker usage ();
112*a67afe4dSAndroid Build Coastguard Worker exit (1);
113*a67afe4dSAndroid Build Coastguard Worker }
114*a67afe4dSAndroid Build Coastguard Worker } /* end for */
115*a67afe4dSAndroid Build Coastguard Worker
116*a67afe4dSAndroid Build Coastguard Worker #if defined(O_BINARY) && (O_BINARY != 0)
117*a67afe4dSAndroid Build Coastguard Worker /* set stdin/stdout if required to binary */
118*a67afe4dSAndroid Build Coastguard Worker if (fp_rd == stdin)
119*a67afe4dSAndroid Build Coastguard Worker setmode (fileno (stdin), O_BINARY);
120*a67afe4dSAndroid Build Coastguard Worker if ((raw) && (fp_wr == stdout))
121*a67afe4dSAndroid Build Coastguard Worker setmode (fileno (stdout), O_BINARY);
122*a67afe4dSAndroid Build Coastguard Worker #endif
123*a67afe4dSAndroid Build Coastguard Worker
124*a67afe4dSAndroid Build Coastguard Worker /* call the conversion program itself */
125*a67afe4dSAndroid Build Coastguard Worker ret = png2pnm (fp_rd, fp_wr, fp_al, raw, alpha);
126*a67afe4dSAndroid Build Coastguard Worker
127*a67afe4dSAndroid Build Coastguard Worker /* close input file */
128*a67afe4dSAndroid Build Coastguard Worker fclose (fp_rd);
129*a67afe4dSAndroid Build Coastguard Worker /* close output file */
130*a67afe4dSAndroid Build Coastguard Worker fclose (fp_wr);
131*a67afe4dSAndroid Build Coastguard Worker /* close alpha file */
132*a67afe4dSAndroid Build Coastguard Worker if (alpha)
133*a67afe4dSAndroid Build Coastguard Worker fclose (fp_al);
134*a67afe4dSAndroid Build Coastguard Worker
135*a67afe4dSAndroid Build Coastguard Worker if (!ret)
136*a67afe4dSAndroid Build Coastguard Worker {
137*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
138*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Error: unsuccessful conversion of PNG-image\n");
139*a67afe4dSAndroid Build Coastguard Worker if (fname_wr)
140*a67afe4dSAndroid Build Coastguard Worker remove (fname_wr); /* no broken output file shall remain behind */
141*a67afe4dSAndroid Build Coastguard Worker if (fname_al)
142*a67afe4dSAndroid Build Coastguard Worker remove (fname_al); /* ditto */
143*a67afe4dSAndroid Build Coastguard Worker exit (1);
144*a67afe4dSAndroid Build Coastguard Worker }
145*a67afe4dSAndroid Build Coastguard Worker
146*a67afe4dSAndroid Build Coastguard Worker return 0;
147*a67afe4dSAndroid Build Coastguard Worker }
148*a67afe4dSAndroid Build Coastguard Worker
149*a67afe4dSAndroid Build Coastguard Worker /*
150*a67afe4dSAndroid Build Coastguard Worker * usage
151*a67afe4dSAndroid Build Coastguard Worker */
152*a67afe4dSAndroid Build Coastguard Worker
usage()153*a67afe4dSAndroid Build Coastguard Worker void usage ()
154*a67afe4dSAndroid Build Coastguard Worker {
155*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
156*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, " by Willem van Schaik, 1999\n");
157*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Usage: png2pnm [options] <file>.png [<file>.pnm]\n");
158*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, " or: ... | png2pnm [options]\n");
159*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Options:\n");
160*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr,
161*a67afe4dSAndroid Build Coastguard Worker " -r[aw] write pnm-file in binary format (P4/P5/P6) (default)\n");
162*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, " -n[oraw] write pnm-file in ascii format (P1/P2/P3)\n");
163*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr,
164*a67afe4dSAndroid Build Coastguard Worker " -a[lpha] <file>.pgm write PNG alpha channel as pgm-file\n");
165*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, " -h | -? print this help-information\n");
166*a67afe4dSAndroid Build Coastguard Worker }
167*a67afe4dSAndroid Build Coastguard Worker
168*a67afe4dSAndroid Build Coastguard Worker /*
169*a67afe4dSAndroid Build Coastguard Worker * png2pnm
170*a67afe4dSAndroid Build Coastguard Worker */
171*a67afe4dSAndroid Build Coastguard Worker
png2pnm(FILE * png_file,FILE * pnm_file,FILE * alpha_file,BOOL raw,BOOL alpha)172*a67afe4dSAndroid Build Coastguard Worker BOOL png2pnm (FILE *png_file, FILE *pnm_file, FILE *alpha_file,
173*a67afe4dSAndroid Build Coastguard Worker BOOL raw, BOOL alpha)
174*a67afe4dSAndroid Build Coastguard Worker {
175*a67afe4dSAndroid Build Coastguard Worker png_struct *png_ptr;
176*a67afe4dSAndroid Build Coastguard Worker png_info *info_ptr;
177*a67afe4dSAndroid Build Coastguard Worker BOOL ret;
178*a67afe4dSAndroid Build Coastguard Worker
179*a67afe4dSAndroid Build Coastguard Worker /* initialize the libpng context for reading from png_file */
180*a67afe4dSAndroid Build Coastguard Worker
181*a67afe4dSAndroid Build Coastguard Worker png_ptr = png_create_read_struct (png_get_libpng_ver(NULL),
182*a67afe4dSAndroid Build Coastguard Worker NULL, NULL, NULL);
183*a67afe4dSAndroid Build Coastguard Worker if (!png_ptr)
184*a67afe4dSAndroid Build Coastguard Worker return FALSE; /* out of memory */
185*a67afe4dSAndroid Build Coastguard Worker
186*a67afe4dSAndroid Build Coastguard Worker info_ptr = png_create_info_struct (png_ptr);
187*a67afe4dSAndroid Build Coastguard Worker if (!info_ptr)
188*a67afe4dSAndroid Build Coastguard Worker {
189*a67afe4dSAndroid Build Coastguard Worker png_destroy_read_struct (&png_ptr, NULL, NULL);
190*a67afe4dSAndroid Build Coastguard Worker return FALSE; /* out of memory */
191*a67afe4dSAndroid Build Coastguard Worker }
192*a67afe4dSAndroid Build Coastguard Worker
193*a67afe4dSAndroid Build Coastguard Worker if (setjmp (png_jmpbuf (png_ptr)))
194*a67afe4dSAndroid Build Coastguard Worker {
195*a67afe4dSAndroid Build Coastguard Worker png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
196*a67afe4dSAndroid Build Coastguard Worker return FALSE; /* generic libpng error */
197*a67afe4dSAndroid Build Coastguard Worker }
198*a67afe4dSAndroid Build Coastguard Worker
199*a67afe4dSAndroid Build Coastguard Worker png_init_io (png_ptr, png_file);
200*a67afe4dSAndroid Build Coastguard Worker
201*a67afe4dSAndroid Build Coastguard Worker /* do the actual conversion */
202*a67afe4dSAndroid Build Coastguard Worker ret = do_png2pnm (png_ptr, info_ptr, pnm_file, alpha_file, raw, alpha);
203*a67afe4dSAndroid Build Coastguard Worker
204*a67afe4dSAndroid Build Coastguard Worker /* clean up the libpng structures and their internally-managed data */
205*a67afe4dSAndroid Build Coastguard Worker png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
206*a67afe4dSAndroid Build Coastguard Worker
207*a67afe4dSAndroid Build Coastguard Worker return ret;
208*a67afe4dSAndroid Build Coastguard Worker }
209*a67afe4dSAndroid Build Coastguard Worker
210*a67afe4dSAndroid Build Coastguard Worker /*
211*a67afe4dSAndroid Build Coastguard Worker * do_png2pnm - does the conversion in a fully-initialized libpng context
212*a67afe4dSAndroid Build Coastguard Worker */
213*a67afe4dSAndroid Build Coastguard Worker
do_png2pnm(png_struct * png_ptr,png_info * info_ptr,FILE * pnm_file,FILE * alpha_file,BOOL raw,BOOL alpha)214*a67afe4dSAndroid Build Coastguard Worker BOOL do_png2pnm (png_struct *png_ptr, png_info *info_ptr,
215*a67afe4dSAndroid Build Coastguard Worker FILE *pnm_file, FILE *alpha_file,
216*a67afe4dSAndroid Build Coastguard Worker BOOL raw, BOOL alpha)
217*a67afe4dSAndroid Build Coastguard Worker {
218*a67afe4dSAndroid Build Coastguard Worker png_byte **row_pointers;
219*a67afe4dSAndroid Build Coastguard Worker png_byte *pix_ptr;
220*a67afe4dSAndroid Build Coastguard Worker png_uint_32 width;
221*a67afe4dSAndroid Build Coastguard Worker png_uint_32 height;
222*a67afe4dSAndroid Build Coastguard Worker int bit_depth;
223*a67afe4dSAndroid Build Coastguard Worker int channels;
224*a67afe4dSAndroid Build Coastguard Worker int color_type;
225*a67afe4dSAndroid Build Coastguard Worker int alpha_present;
226*a67afe4dSAndroid Build Coastguard Worker png_uint_32 row, col, i;
227*a67afe4dSAndroid Build Coastguard Worker long dep_16;
228*a67afe4dSAndroid Build Coastguard Worker
229*a67afe4dSAndroid Build Coastguard Worker /* set up the image transformations that are necessary for the PNM format */
230*a67afe4dSAndroid Build Coastguard Worker
231*a67afe4dSAndroid Build Coastguard Worker /* set up (if applicable) the expansion of paletted images to full-color rgb,
232*a67afe4dSAndroid Build Coastguard Worker * and the expansion of transparency maps to full alpha-channel */
233*a67afe4dSAndroid Build Coastguard Worker png_set_expand (png_ptr);
234*a67afe4dSAndroid Build Coastguard Worker
235*a67afe4dSAndroid Build Coastguard Worker /* set up (if applicable) the expansion of grayscale images to bit-depth 8 */
236*a67afe4dSAndroid Build Coastguard Worker png_set_expand_gray_1_2_4_to_8 (png_ptr);
237*a67afe4dSAndroid Build Coastguard Worker
238*a67afe4dSAndroid Build Coastguard Worker #ifdef NJET
239*a67afe4dSAndroid Build Coastguard Worker /* downgrade 16-bit images to 8-bit */
240*a67afe4dSAndroid Build Coastguard Worker if (bit_depth == 16)
241*a67afe4dSAndroid Build Coastguard Worker png_set_strip_16 (png_ptr);
242*a67afe4dSAndroid Build Coastguard Worker /* transform grayscale images into full-color */
243*a67afe4dSAndroid Build Coastguard Worker if (color_type == PNG_COLOR_TYPE_GRAY ||
244*a67afe4dSAndroid Build Coastguard Worker color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
245*a67afe4dSAndroid Build Coastguard Worker png_set_gray_to_rgb (png_ptr);
246*a67afe4dSAndroid Build Coastguard Worker /* if the PNG image has a gAMA chunk then gamma-correct the output image */
247*a67afe4dSAndroid Build Coastguard Worker {
248*a67afe4dSAndroid Build Coastguard Worker double file_gamma;
249*a67afe4dSAndroid Build Coastguard Worker if (png_get_gAMA (png_ptr, info_ptr, &file_gamma))
250*a67afe4dSAndroid Build Coastguard Worker png_set_gamma (png_ptr, (double) 2.2, file_gamma);
251*a67afe4dSAndroid Build Coastguard Worker }
252*a67afe4dSAndroid Build Coastguard Worker #endif
253*a67afe4dSAndroid Build Coastguard Worker
254*a67afe4dSAndroid Build Coastguard Worker /* read the image file, with all of the above image transforms applied */
255*a67afe4dSAndroid Build Coastguard Worker png_read_png (png_ptr, info_ptr, 0, NULL);
256*a67afe4dSAndroid Build Coastguard Worker
257*a67afe4dSAndroid Build Coastguard Worker /* get the image size, bit-depth and color-type */
258*a67afe4dSAndroid Build Coastguard Worker png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
259*a67afe4dSAndroid Build Coastguard Worker NULL, NULL, NULL);
260*a67afe4dSAndroid Build Coastguard Worker
261*a67afe4dSAndroid Build Coastguard Worker /* calculate the number of channels and store alpha-presence */
262*a67afe4dSAndroid Build Coastguard Worker if (color_type == PNG_COLOR_TYPE_GRAY)
263*a67afe4dSAndroid Build Coastguard Worker channels = 1;
264*a67afe4dSAndroid Build Coastguard Worker else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
265*a67afe4dSAndroid Build Coastguard Worker channels = 2;
266*a67afe4dSAndroid Build Coastguard Worker else if (color_type == PNG_COLOR_TYPE_RGB)
267*a67afe4dSAndroid Build Coastguard Worker channels = 3;
268*a67afe4dSAndroid Build Coastguard Worker else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
269*a67afe4dSAndroid Build Coastguard Worker channels = 4;
270*a67afe4dSAndroid Build Coastguard Worker else
271*a67afe4dSAndroid Build Coastguard Worker channels = 0; /* should never happen */
272*a67afe4dSAndroid Build Coastguard Worker alpha_present = (channels - 1) % 2;
273*a67afe4dSAndroid Build Coastguard Worker
274*a67afe4dSAndroid Build Coastguard Worker /* check if alpha is expected to be present in file */
275*a67afe4dSAndroid Build Coastguard Worker if (alpha && !alpha_present)
276*a67afe4dSAndroid Build Coastguard Worker {
277*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "PNG2PNM\n");
278*a67afe4dSAndroid Build Coastguard Worker fprintf (stderr, "Warning: no alpha channel in PNG file\n");
279*a67afe4dSAndroid Build Coastguard Worker return FALSE;
280*a67afe4dSAndroid Build Coastguard Worker }
281*a67afe4dSAndroid Build Coastguard Worker
282*a67afe4dSAndroid Build Coastguard Worker /* get address of internally-allocated image data */
283*a67afe4dSAndroid Build Coastguard Worker row_pointers = png_get_rows (png_ptr, info_ptr);
284*a67afe4dSAndroid Build Coastguard Worker
285*a67afe4dSAndroid Build Coastguard Worker /* write header of PNM file */
286*a67afe4dSAndroid Build Coastguard Worker
287*a67afe4dSAndroid Build Coastguard Worker if ((color_type == PNG_COLOR_TYPE_GRAY) ||
288*a67afe4dSAndroid Build Coastguard Worker (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
289*a67afe4dSAndroid Build Coastguard Worker {
290*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%s\n", (raw) ? "P5" : "P2");
291*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
292*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
293*a67afe4dSAndroid Build Coastguard Worker }
294*a67afe4dSAndroid Build Coastguard Worker else if ((color_type == PNG_COLOR_TYPE_RGB) ||
295*a67afe4dSAndroid Build Coastguard Worker (color_type == PNG_COLOR_TYPE_RGB_ALPHA))
296*a67afe4dSAndroid Build Coastguard Worker {
297*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%s\n", (raw) ? "P6" : "P3");
298*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%d %d\n", (int) width, (int) height);
299*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
300*a67afe4dSAndroid Build Coastguard Worker }
301*a67afe4dSAndroid Build Coastguard Worker
302*a67afe4dSAndroid Build Coastguard Worker /* write header of PGM file with alpha channel */
303*a67afe4dSAndroid Build Coastguard Worker
304*a67afe4dSAndroid Build Coastguard Worker if ((alpha) &&
305*a67afe4dSAndroid Build Coastguard Worker ((color_type == PNG_COLOR_TYPE_GRAY_ALPHA) ||
306*a67afe4dSAndroid Build Coastguard Worker (color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
307*a67afe4dSAndroid Build Coastguard Worker {
308*a67afe4dSAndroid Build Coastguard Worker fprintf (alpha_file, "%s\n", (raw) ? "P5" : "P2");
309*a67afe4dSAndroid Build Coastguard Worker fprintf (alpha_file, "%d %d\n", (int) width, (int) height);
310*a67afe4dSAndroid Build Coastguard Worker fprintf (alpha_file, "%ld\n", ((1L << (int) bit_depth) - 1L));
311*a67afe4dSAndroid Build Coastguard Worker }
312*a67afe4dSAndroid Build Coastguard Worker
313*a67afe4dSAndroid Build Coastguard Worker /* write data to PNM file */
314*a67afe4dSAndroid Build Coastguard Worker
315*a67afe4dSAndroid Build Coastguard Worker for (row = 0; row < height; row++)
316*a67afe4dSAndroid Build Coastguard Worker {
317*a67afe4dSAndroid Build Coastguard Worker pix_ptr = row_pointers[row];
318*a67afe4dSAndroid Build Coastguard Worker for (col = 0; col < width; col++)
319*a67afe4dSAndroid Build Coastguard Worker {
320*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < (png_uint_32) (channels - alpha_present); i++)
321*a67afe4dSAndroid Build Coastguard Worker {
322*a67afe4dSAndroid Build Coastguard Worker if (raw)
323*a67afe4dSAndroid Build Coastguard Worker {
324*a67afe4dSAndroid Build Coastguard Worker fputc ((int) *pix_ptr++, pnm_file);
325*a67afe4dSAndroid Build Coastguard Worker if (bit_depth == 16)
326*a67afe4dSAndroid Build Coastguard Worker fputc ((int) *pix_ptr++, pnm_file);
327*a67afe4dSAndroid Build Coastguard Worker }
328*a67afe4dSAndroid Build Coastguard Worker else
329*a67afe4dSAndroid Build Coastguard Worker {
330*a67afe4dSAndroid Build Coastguard Worker if (bit_depth == 16)
331*a67afe4dSAndroid Build Coastguard Worker {
332*a67afe4dSAndroid Build Coastguard Worker dep_16 = ((long) *pix_ptr++) << 8;
333*a67afe4dSAndroid Build Coastguard Worker dep_16 += ((long) *pix_ptr++);
334*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%ld ", dep_16);
335*a67afe4dSAndroid Build Coastguard Worker }
336*a67afe4dSAndroid Build Coastguard Worker else
337*a67afe4dSAndroid Build Coastguard Worker {
338*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "%ld ", (long) *pix_ptr++);
339*a67afe4dSAndroid Build Coastguard Worker }
340*a67afe4dSAndroid Build Coastguard Worker }
341*a67afe4dSAndroid Build Coastguard Worker }
342*a67afe4dSAndroid Build Coastguard Worker if (alpha_present)
343*a67afe4dSAndroid Build Coastguard Worker {
344*a67afe4dSAndroid Build Coastguard Worker if (!alpha)
345*a67afe4dSAndroid Build Coastguard Worker {
346*a67afe4dSAndroid Build Coastguard Worker /* skip the alpha-channel */
347*a67afe4dSAndroid Build Coastguard Worker pix_ptr++;
348*a67afe4dSAndroid Build Coastguard Worker if (bit_depth == 16)
349*a67afe4dSAndroid Build Coastguard Worker pix_ptr++;
350*a67afe4dSAndroid Build Coastguard Worker }
351*a67afe4dSAndroid Build Coastguard Worker else
352*a67afe4dSAndroid Build Coastguard Worker {
353*a67afe4dSAndroid Build Coastguard Worker /* output the alpha-channel as pgm file */
354*a67afe4dSAndroid Build Coastguard Worker if (raw)
355*a67afe4dSAndroid Build Coastguard Worker {
356*a67afe4dSAndroid Build Coastguard Worker fputc ((int) *pix_ptr++, alpha_file);
357*a67afe4dSAndroid Build Coastguard Worker if (bit_depth == 16)
358*a67afe4dSAndroid Build Coastguard Worker fputc ((int) *pix_ptr++, alpha_file);
359*a67afe4dSAndroid Build Coastguard Worker }
360*a67afe4dSAndroid Build Coastguard Worker else
361*a67afe4dSAndroid Build Coastguard Worker {
362*a67afe4dSAndroid Build Coastguard Worker if (bit_depth == 16)
363*a67afe4dSAndroid Build Coastguard Worker {
364*a67afe4dSAndroid Build Coastguard Worker dep_16 = ((long) *pix_ptr++) << 8;
365*a67afe4dSAndroid Build Coastguard Worker dep_16 += ((long) *pix_ptr++);
366*a67afe4dSAndroid Build Coastguard Worker fprintf (alpha_file, "%ld ", dep_16);
367*a67afe4dSAndroid Build Coastguard Worker }
368*a67afe4dSAndroid Build Coastguard Worker else
369*a67afe4dSAndroid Build Coastguard Worker {
370*a67afe4dSAndroid Build Coastguard Worker fprintf (alpha_file, "%ld ", (long) *pix_ptr++);
371*a67afe4dSAndroid Build Coastguard Worker }
372*a67afe4dSAndroid Build Coastguard Worker }
373*a67afe4dSAndroid Build Coastguard Worker }
374*a67afe4dSAndroid Build Coastguard Worker } /* end if alpha_present */
375*a67afe4dSAndroid Build Coastguard Worker
376*a67afe4dSAndroid Build Coastguard Worker if (!raw)
377*a67afe4dSAndroid Build Coastguard Worker if (col % 4 == 3)
378*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "\n");
379*a67afe4dSAndroid Build Coastguard Worker } /* end for col */
380*a67afe4dSAndroid Build Coastguard Worker
381*a67afe4dSAndroid Build Coastguard Worker if (!raw)
382*a67afe4dSAndroid Build Coastguard Worker if (col % 4 != 0)
383*a67afe4dSAndroid Build Coastguard Worker fprintf (pnm_file, "\n");
384*a67afe4dSAndroid Build Coastguard Worker } /* end for row */
385*a67afe4dSAndroid Build Coastguard Worker
386*a67afe4dSAndroid Build Coastguard Worker return TRUE;
387*a67afe4dSAndroid Build Coastguard Worker } /* end of source */
388