xref: /aosp_15_r20/external/libpng/contrib/pngminus/png2pnm.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
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