1
2/* pngwrite.c - general routines to write a PNG file
3 *
4 * Last changed in libpng 1.6.19 [November 12, 2015]
5 * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8 *
9 * This code is released under the libpng license.
10 * For conditions of distribution and use, see the disclaimer
11 * and license in png.h
12 */
13
14#include "pngpriv.h"
15#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
16#  include <errno.h>
17#endif /* SIMPLIFIED_WRITE_STDIO */
18
19#ifdef PNG_WRITE_SUPPORTED
20
21#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
22/* Write out all the unknown chunks for the current given location */
23static void
24write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
25   unsigned int where)
26{
27   if (info_ptr->unknown_chunks_num != 0)
28   {
29      png_const_unknown_chunkp up;
30
31      png_debug(5, "writing extra chunks");
32
33      for (up = info_ptr->unknown_chunks;
34           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
35           ++up)
36         if ((up->location & where) != 0)
37      {
38         /* If per-chunk unknown chunk handling is enabled use it, otherwise
39          * just write the chunks the application has set.
40          */
41#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
42         int keep = png_handle_as_unknown(png_ptr, up->name);
43
44         /* NOTE: this code is radically different from the read side in the
45          * matter of handling an ancillary unknown chunk.  In the read side
46          * the default behavior is to discard it, in the code below the default
47          * behavior is to write it.  Critical chunks are, however, only
48          * written if explicitly listed or if the default is set to write all
49          * unknown chunks.
50          *
51          * The default handling is also slightly weird - it is not possible to
52          * stop the writing of all unsafe-to-copy chunks!
53          *
54          * TODO: REVIEW: this would seem to be a bug.
55          */
56         if (keep != PNG_HANDLE_CHUNK_NEVER &&
57             ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
58              keep == PNG_HANDLE_CHUNK_ALWAYS ||
59              (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
60               png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
61#endif
62         {
63            /* TODO: review, what is wrong with a zero length unknown chunk? */
64            if (up->size == 0)
65               png_warning(png_ptr, "Writing zero-length unknown chunk");
66
67            png_write_chunk(png_ptr, up->name, up->data, up->size);
68         }
69      }
70   }
71}
72#endif /* WRITE_UNKNOWN_CHUNKS */
73
74/* Writes all the PNG information.  This is the suggested way to use the
75 * library.  If you have a new chunk to add, make a function to write it,
76 * and put it in the correct location here.  If you want the chunk written
77 * after the image data, put it in png_write_end().  I strongly encourage
78 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
79 * the chunk, as that will keep the code from breaking if you want to just
80 * write a plain PNG file.  If you have long comments, I suggest writing
81 * them in png_write_end(), and compressing them.
82 */
83void PNGAPI
84png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
85{
86   png_debug(1, "in png_write_info_before_PLTE");
87
88   if (png_ptr == NULL || info_ptr == NULL)
89      return;
90
91   if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
92   {
93      /* Write PNG signature */
94      png_write_sig(png_ptr);
95
96#ifdef PNG_MNG_FEATURES_SUPPORTED
97      if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
98          png_ptr->mng_features_permitted != 0)
99      {
100         png_warning(png_ptr,
101             "MNG features are not allowed in a PNG datastream");
102         png_ptr->mng_features_permitted = 0;
103      }
104#endif
105
106      /* Write IHDR information. */
107      png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
108          info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
109          info_ptr->filter_type,
110#ifdef PNG_WRITE_INTERLACING_SUPPORTED
111          info_ptr->interlace_type
112#else
113          0
114#endif
115         );
116
117      /* The rest of these check to see if the valid field has the appropriate
118       * flag set, and if it does, writes the chunk.
119       *
120       * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
121       * the chunks will be written if the WRITE routine is there and
122       * information * is available in the COLORSPACE. (See
123       * png_colorspace_sync_info in png.c for where the valid flags get set.)
124       *
125       * Under certain circumstances the colorspace can be invalidated without
126       * syncing the info_struct 'valid' flags; this happens if libpng detects
127       * an error and calls png_error while the color space is being set, yet
128       * the application continues writing the PNG.  So check the 'invalid'
129       * flag here too.
130       */
131#ifdef PNG_GAMMA_SUPPORTED
132#  ifdef PNG_WRITE_gAMA_SUPPORTED
133      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
134          (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
135          (info_ptr->valid & PNG_INFO_gAMA) != 0)
136         png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
137#  endif
138#endif
139
140#ifdef PNG_COLORSPACE_SUPPORTED
141      /* Write only one of sRGB or an ICC profile.  If a profile was supplied
142       * and it matches one of the known sRGB ones issue a warning.
143       */
144#  ifdef PNG_WRITE_iCCP_SUPPORTED
145         if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
146             (info_ptr->valid & PNG_INFO_iCCP) != 0)
147         {
148#    ifdef PNG_WRITE_sRGB_SUPPORTED
149               if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
150                  png_app_warning(png_ptr,
151                     "profile matches sRGB but writing iCCP instead");
152#     endif
153
154            png_write_iCCP(png_ptr, info_ptr->iccp_name,
155               info_ptr->iccp_profile);
156         }
157#     ifdef PNG_WRITE_sRGB_SUPPORTED
158         else
159#     endif
160#  endif
161
162#  ifdef PNG_WRITE_sRGB_SUPPORTED
163         if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
164             (info_ptr->valid & PNG_INFO_sRGB) != 0)
165            png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
166#  endif /* WRITE_sRGB */
167#endif /* COLORSPACE */
168
169#ifdef PNG_WRITE_sBIT_SUPPORTED
170         if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
171            png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
172#endif
173
174#ifdef PNG_COLORSPACE_SUPPORTED
175#  ifdef PNG_WRITE_cHRM_SUPPORTED
176         if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
177             (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
178             (info_ptr->valid & PNG_INFO_cHRM) != 0)
179            png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
180#  endif
181#endif
182
183#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
184         write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
185#endif
186
187      png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
188   }
189}
190
191void PNGAPI
192png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
193{
194#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
195   int i;
196#endif
197
198   png_debug(1, "in png_write_info");
199
200   if (png_ptr == NULL || info_ptr == NULL)
201      return;
202
203   png_write_info_before_PLTE(png_ptr, info_ptr);
204
205   if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
206      png_write_PLTE(png_ptr, info_ptr->palette,
207          (png_uint_32)info_ptr->num_palette);
208
209   else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
210      png_error(png_ptr, "Valid palette required for paletted images");
211
212#ifdef PNG_WRITE_tRNS_SUPPORTED
213   if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
214   {
215#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
216      /* Invert the alpha channel (in tRNS) */
217      if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
218          info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
219      {
220         int j, jend;
221
222         jend = info_ptr->num_trans;
223         if (jend > PNG_MAX_PALETTE_LENGTH)
224            jend = PNG_MAX_PALETTE_LENGTH;
225
226         for (j = 0; j<jend; ++j)
227            info_ptr->trans_alpha[j] =
228               (png_byte)(255 - info_ptr->trans_alpha[j]);
229      }
230#endif
231      png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
232          info_ptr->num_trans, info_ptr->color_type);
233   }
234#endif
235#ifdef PNG_WRITE_bKGD_SUPPORTED
236   if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
237      png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
238#endif
239
240#ifdef PNG_WRITE_hIST_SUPPORTED
241   if ((info_ptr->valid & PNG_INFO_hIST) != 0)
242      png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
243#endif
244
245#ifdef PNG_WRITE_oFFs_SUPPORTED
246   if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
247      png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
248          info_ptr->offset_unit_type);
249#endif
250
251#ifdef PNG_WRITE_pCAL_SUPPORTED
252   if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
253      png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
254          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
255          info_ptr->pcal_units, info_ptr->pcal_params);
256#endif
257
258#ifdef PNG_WRITE_sCAL_SUPPORTED
259   if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
260      png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
261          info_ptr->scal_s_width, info_ptr->scal_s_height);
262#endif /* sCAL */
263
264#ifdef PNG_WRITE_pHYs_SUPPORTED
265   if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
266      png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
267          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
268#endif /* pHYs */
269
270#ifdef PNG_WRITE_tIME_SUPPORTED
271   if ((info_ptr->valid & PNG_INFO_tIME) != 0)
272   {
273      png_write_tIME(png_ptr, &(info_ptr->mod_time));
274      png_ptr->mode |= PNG_WROTE_tIME;
275   }
276#endif /* tIME */
277
278#ifdef PNG_WRITE_sPLT_SUPPORTED
279   if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
280      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
281         png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
282#endif /* sPLT */
283
284#ifdef PNG_WRITE_TEXT_SUPPORTED
285   /* Check to see if we need to write text chunks */
286   for (i = 0; i < info_ptr->num_text; i++)
287   {
288      png_debug2(2, "Writing header text chunk %d, type %d", i,
289          info_ptr->text[i].compression);
290      /* An internationalized chunk? */
291      if (info_ptr->text[i].compression > 0)
292      {
293#ifdef PNG_WRITE_iTXt_SUPPORTED
294         /* Write international chunk */
295         png_write_iTXt(png_ptr,
296             info_ptr->text[i].compression,
297             info_ptr->text[i].key,
298             info_ptr->text[i].lang,
299             info_ptr->text[i].lang_key,
300             info_ptr->text[i].text);
301         /* Mark this chunk as written */
302         if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
303            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
304         else
305            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
306#else
307         png_warning(png_ptr, "Unable to write international text");
308#endif
309      }
310
311      /* If we want a compressed text chunk */
312      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
313      {
314#ifdef PNG_WRITE_zTXt_SUPPORTED
315         /* Write compressed chunk */
316         png_write_zTXt(png_ptr, info_ptr->text[i].key,
317             info_ptr->text[i].text, info_ptr->text[i].compression);
318         /* Mark this chunk as written */
319         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
320#else
321         png_warning(png_ptr, "Unable to write compressed text");
322#endif
323      }
324
325      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
326      {
327#ifdef PNG_WRITE_tEXt_SUPPORTED
328         /* Write uncompressed chunk */
329         png_write_tEXt(png_ptr, info_ptr->text[i].key,
330             info_ptr->text[i].text,
331             0);
332         /* Mark this chunk as written */
333         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
334#else
335         /* Can't get here */
336         png_warning(png_ptr, "Unable to write uncompressed text");
337#endif
338      }
339   }
340#endif /* tEXt */
341
342#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
343   write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
344#endif
345}
346
347/* Writes the end of the PNG file.  If you don't want to write comments or
348 * time information, you can pass NULL for info.  If you already wrote these
349 * in png_write_info(), do not write them again here.  If you have long
350 * comments, I suggest writing them here, and compressing them.
351 */
352void PNGAPI
353png_write_end(png_structrp png_ptr, png_inforp info_ptr)
354{
355   png_debug(1, "in png_write_end");
356
357   if (png_ptr == NULL)
358      return;
359
360   if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
361      png_error(png_ptr, "No IDATs written into file");
362
363#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
364   if (png_ptr->num_palette_max > png_ptr->num_palette)
365      png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
366#endif
367
368   /* See if user wants us to write information chunks */
369   if (info_ptr != NULL)
370   {
371#ifdef PNG_WRITE_TEXT_SUPPORTED
372      int i; /* local index variable */
373#endif
374#ifdef PNG_WRITE_tIME_SUPPORTED
375      /* Check to see if user has supplied a time chunk */
376      if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
377          (png_ptr->mode & PNG_WROTE_tIME) == 0)
378         png_write_tIME(png_ptr, &(info_ptr->mod_time));
379
380#endif
381#ifdef PNG_WRITE_TEXT_SUPPORTED
382      /* Loop through comment chunks */
383      for (i = 0; i < info_ptr->num_text; i++)
384      {
385         png_debug2(2, "Writing trailer text chunk %d, type %d", i,
386            info_ptr->text[i].compression);
387         /* An internationalized chunk? */
388         if (info_ptr->text[i].compression > 0)
389         {
390#ifdef PNG_WRITE_iTXt_SUPPORTED
391            /* Write international chunk */
392            png_write_iTXt(png_ptr,
393                info_ptr->text[i].compression,
394                info_ptr->text[i].key,
395                info_ptr->text[i].lang,
396                info_ptr->text[i].lang_key,
397                info_ptr->text[i].text);
398            /* Mark this chunk as written */
399            if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
400               info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
401            else
402               info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
403#else
404            png_warning(png_ptr, "Unable to write international text");
405#endif
406         }
407
408         else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
409         {
410#ifdef PNG_WRITE_zTXt_SUPPORTED
411            /* Write compressed chunk */
412            png_write_zTXt(png_ptr, info_ptr->text[i].key,
413                info_ptr->text[i].text, info_ptr->text[i].compression);
414            /* Mark this chunk as written */
415            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
416#else
417            png_warning(png_ptr, "Unable to write compressed text");
418#endif
419         }
420
421         else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
422         {
423#ifdef PNG_WRITE_tEXt_SUPPORTED
424            /* Write uncompressed chunk */
425            png_write_tEXt(png_ptr, info_ptr->text[i].key,
426                info_ptr->text[i].text, 0);
427            /* Mark this chunk as written */
428            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
429#else
430            png_warning(png_ptr, "Unable to write uncompressed text");
431#endif
432         }
433      }
434#endif
435#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
436      write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
437#endif
438   }
439
440   png_ptr->mode |= PNG_AFTER_IDAT;
441
442   /* Write end of PNG file */
443   png_write_IEND(png_ptr);
444
445   /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
446    * and restored again in libpng-1.2.30, may cause some applications that
447    * do not set png_ptr->output_flush_fn to crash.  If your application
448    * experiences a problem, please try building libpng with
449    * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
450    * png-mng-implement at lists.sf.net .
451    */
452#ifdef PNG_WRITE_FLUSH_SUPPORTED
453#  ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
454   png_flush(png_ptr);
455#  endif
456#endif
457}
458
459#ifdef PNG_CONVERT_tIME_SUPPORTED
460void PNGAPI
461png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
462{
463   png_debug(1, "in png_convert_from_struct_tm");
464
465   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
466   ptime->month = (png_byte)(ttime->tm_mon + 1);
467   ptime->day = (png_byte)ttime->tm_mday;
468   ptime->hour = (png_byte)ttime->tm_hour;
469   ptime->minute = (png_byte)ttime->tm_min;
470   ptime->second = (png_byte)ttime->tm_sec;
471}
472
473void PNGAPI
474png_convert_from_time_t(png_timep ptime, time_t ttime)
475{
476   struct tm *tbuf;
477
478   png_debug(1, "in png_convert_from_time_t");
479
480   tbuf = gmtime(&ttime);
481   png_convert_from_struct_tm(ptime, tbuf);
482}
483#endif
484
485/* Initialize png_ptr structure, and allocate any memory needed */
486PNG_FUNCTION(png_structp,PNGAPI
487png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
488    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
489{
490#ifndef PNG_USER_MEM_SUPPORTED
491   png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
492       error_fn, warn_fn, NULL, NULL, NULL);
493#else
494   return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
495       warn_fn, NULL, NULL, NULL);
496}
497
498/* Alternate initialize png_ptr structure, and allocate any memory needed */
499PNG_FUNCTION(png_structp,PNGAPI
500png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
501    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
502    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
503{
504   png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
505       error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
506#endif /* USER_MEM */
507   if (png_ptr != NULL)
508   {
509      /* Set the zlib control values to defaults; they can be overridden by the
510       * application after the struct has been created.
511       */
512      png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
513
514      /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
515       * pngwutil.c defaults it according to whether or not filters will be
516       * used, and ignores this setting.
517       */
518      png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
519      png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
520      png_ptr->zlib_mem_level = 8;
521      png_ptr->zlib_window_bits = 15;
522      png_ptr->zlib_method = 8;
523
524#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
525      png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
526      png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
527      png_ptr->zlib_text_mem_level = 8;
528      png_ptr->zlib_text_window_bits = 15;
529      png_ptr->zlib_text_method = 8;
530#endif /* WRITE_COMPRESSED_TEXT */
531
532      /* This is a highly dubious configuration option; by default it is off,
533       * but it may be appropriate for private builds that are testing
534       * extensions not conformant to the current specification, or of
535       * applications that must not fail to write at all costs!
536       */
537#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
538      /* In stable builds only warn if an application error can be completely
539       * handled.
540       */
541      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
542#endif
543
544      /* App warnings are warnings in release (or release candidate) builds but
545       * are errors during development.
546       */
547#if PNG_RELEASE_BUILD
548      png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
549#endif
550
551      /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
552       * do it itself) avoiding setting the default function if it is not
553       * required.
554       */
555      png_set_write_fn(png_ptr, NULL, NULL, NULL);
556   }
557
558   return png_ptr;
559}
560
561
562/* Write a few rows of image data.  If the image is interlaced,
563 * either you will have to write the 7 sub images, or, if you
564 * have called png_set_interlace_handling(), you will have to
565 * "write" the image seven times.
566 */
567void PNGAPI
568png_write_rows(png_structrp png_ptr, png_bytepp row,
569    png_uint_32 num_rows)
570{
571   png_uint_32 i; /* row counter */
572   png_bytepp rp; /* row pointer */
573
574   png_debug(1, "in png_write_rows");
575
576   if (png_ptr == NULL)
577      return;
578
579   /* Loop through the rows */
580   for (i = 0, rp = row; i < num_rows; i++, rp++)
581   {
582      png_write_row(png_ptr, *rp);
583   }
584}
585
586/* Write the image.  You only need to call this function once, even
587 * if you are writing an interlaced image.
588 */
589void PNGAPI
590png_write_image(png_structrp png_ptr, png_bytepp image)
591{
592   png_uint_32 i; /* row index */
593   int pass, num_pass; /* pass variables */
594   png_bytepp rp; /* points to current row */
595
596   if (png_ptr == NULL)
597      return;
598
599   png_debug(1, "in png_write_image");
600
601#ifdef PNG_WRITE_INTERLACING_SUPPORTED
602   /* Initialize interlace handling.  If image is not interlaced,
603    * this will set pass to 1
604    */
605   num_pass = png_set_interlace_handling(png_ptr);
606#else
607   num_pass = 1;
608#endif
609   /* Loop through passes */
610   for (pass = 0; pass < num_pass; pass++)
611   {
612      /* Loop through image */
613      for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
614      {
615         png_write_row(png_ptr, *rp);
616      }
617   }
618}
619
620#ifdef PNG_MNG_FEATURES_SUPPORTED
621/* Performs intrapixel differencing  */
622static void
623png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
624{
625   png_debug(1, "in png_do_write_intrapixel");
626
627   if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
628   {
629      int bytes_per_pixel;
630      png_uint_32 row_width = row_info->width;
631      if (row_info->bit_depth == 8)
632      {
633         png_bytep rp;
634         png_uint_32 i;
635
636         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
637            bytes_per_pixel = 3;
638
639         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
640            bytes_per_pixel = 4;
641
642         else
643            return;
644
645         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
646         {
647            *(rp)     = (png_byte)(*rp       - *(rp + 1));
648            *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
649         }
650      }
651
652#ifdef PNG_WRITE_16BIT_SUPPORTED
653      else if (row_info->bit_depth == 16)
654      {
655         png_bytep rp;
656         png_uint_32 i;
657
658         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
659            bytes_per_pixel = 6;
660
661         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
662            bytes_per_pixel = 8;
663
664         else
665            return;
666
667         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
668         {
669            png_uint_32 s0   = (*(rp    ) << 8) | *(rp + 1);
670            png_uint_32 s1   = (*(rp + 2) << 8) | *(rp + 3);
671            png_uint_32 s2   = (*(rp + 4) << 8) | *(rp + 5);
672            png_uint_32 red  = (png_uint_32)((s0 - s1) & 0xffffL);
673            png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
674            *(rp    ) = (png_byte)(red >> 8);
675            *(rp + 1) = (png_byte)red;
676            *(rp + 4) = (png_byte)(blue >> 8);
677            *(rp + 5) = (png_byte)blue;
678         }
679      }
680#endif /* WRITE_16BIT */
681   }
682}
683#endif /* MNG_FEATURES */
684
685/* Called by user to write a row of image data */
686void PNGAPI
687png_write_row(png_structrp png_ptr, png_const_bytep row)
688{
689   /* 1.5.6: moved from png_struct to be a local structure: */
690   png_row_info row_info;
691
692   if (png_ptr == NULL)
693      return;
694
695   png_debug2(1, "in png_write_row (row %u, pass %d)",
696      png_ptr->row_number, png_ptr->pass);
697
698   /* Initialize transformations and other stuff if first time */
699   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
700   {
701      /* Make sure we wrote the header info */
702      if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
703         png_error(png_ptr,
704             "png_write_info was never called before png_write_row");
705
706      /* Check for transforms that have been set but were defined out */
707#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
708      if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
709         png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
710#endif
711
712#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
713      if ((png_ptr->transformations & PNG_FILLER) != 0)
714         png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
715#endif
716#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
717    defined(PNG_READ_PACKSWAP_SUPPORTED)
718      if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
719         png_warning(png_ptr,
720             "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
721#endif
722
723#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
724      if ((png_ptr->transformations & PNG_PACK) != 0)
725         png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
726#endif
727
728#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
729      if ((png_ptr->transformations & PNG_SHIFT) != 0)
730         png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
731#endif
732
733#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
734      if ((png_ptr->transformations & PNG_BGR) != 0)
735         png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
736#endif
737
738#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
739      if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
740         png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
741#endif
742
743      png_write_start_row(png_ptr);
744   }
745
746#ifdef PNG_WRITE_INTERLACING_SUPPORTED
747   /* If interlaced and not interested in row, return */
748   if (png_ptr->interlaced != 0 &&
749       (png_ptr->transformations & PNG_INTERLACE) != 0)
750   {
751      switch (png_ptr->pass)
752      {
753         case 0:
754            if ((png_ptr->row_number & 0x07) != 0)
755            {
756               png_write_finish_row(png_ptr);
757               return;
758            }
759            break;
760
761         case 1:
762            if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
763            {
764               png_write_finish_row(png_ptr);
765               return;
766            }
767            break;
768
769         case 2:
770            if ((png_ptr->row_number & 0x07) != 4)
771            {
772               png_write_finish_row(png_ptr);
773               return;
774            }
775            break;
776
777         case 3:
778            if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
779            {
780               png_write_finish_row(png_ptr);
781               return;
782            }
783            break;
784
785         case 4:
786            if ((png_ptr->row_number & 0x03) != 2)
787            {
788               png_write_finish_row(png_ptr);
789               return;
790            }
791            break;
792
793         case 5:
794            if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
795            {
796               png_write_finish_row(png_ptr);
797               return;
798            }
799            break;
800
801         case 6:
802            if ((png_ptr->row_number & 0x01) == 0)
803            {
804               png_write_finish_row(png_ptr);
805               return;
806            }
807            break;
808
809         default: /* error: ignore it */
810            break;
811      }
812   }
813#endif
814
815   /* Set up row info for transformations */
816   row_info.color_type = png_ptr->color_type;
817   row_info.width = png_ptr->usr_width;
818   row_info.channels = png_ptr->usr_channels;
819   row_info.bit_depth = png_ptr->usr_bit_depth;
820   row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
821   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
822
823   png_debug1(3, "row_info->color_type = %d", row_info.color_type);
824   png_debug1(3, "row_info->width = %u", row_info.width);
825   png_debug1(3, "row_info->channels = %d", row_info.channels);
826   png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
827   png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
828   png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
829
830   /* Copy user's row into buffer, leaving room for filter byte. */
831   memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
832
833#ifdef PNG_WRITE_INTERLACING_SUPPORTED
834   /* Handle interlacing */
835   if (png_ptr->interlaced && png_ptr->pass < 6 &&
836       (png_ptr->transformations & PNG_INTERLACE) != 0)
837   {
838      png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
839      /* This should always get caught above, but still ... */
840      if (row_info.width == 0)
841      {
842         png_write_finish_row(png_ptr);
843         return;
844      }
845   }
846#endif
847
848#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
849   /* Handle other transformations */
850   if (png_ptr->transformations != 0)
851      png_do_write_transformations(png_ptr, &row_info);
852#endif
853
854   /* At this point the row_info pixel depth must match the 'transformed' depth,
855    * which is also the output depth.
856    */
857   if (row_info.pixel_depth != png_ptr->pixel_depth ||
858       row_info.pixel_depth != png_ptr->transformed_pixel_depth)
859      png_error(png_ptr, "internal write transform logic error");
860
861#ifdef PNG_MNG_FEATURES_SUPPORTED
862   /* Write filter_method 64 (intrapixel differencing) only if
863    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
864    * 2. Libpng did not write a PNG signature (this filter_method is only
865    *    used in PNG datastreams that are embedded in MNG datastreams) and
866    * 3. The application called png_permit_mng_features with a mask that
867    *    included PNG_FLAG_MNG_FILTER_64 and
868    * 4. The filter_method is 64 and
869    * 5. The color_type is RGB or RGBA
870    */
871   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
872       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
873   {
874      /* Intrapixel differencing */
875      png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
876   }
877#endif
878
879/* Added at libpng-1.5.10 */
880#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
881   /* Check for out-of-range palette index */
882   if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
883       png_ptr->num_palette_max >= 0)
884      png_do_check_palette_indexes(png_ptr, &row_info);
885#endif
886
887   /* Find a filter if necessary, filter the row and write it out. */
888   png_write_find_filter(png_ptr, &row_info);
889
890   if (png_ptr->write_row_fn != NULL)
891      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
892}
893
894#ifdef PNG_WRITE_FLUSH_SUPPORTED
895/* Set the automatic flush interval or 0 to turn flushing off */
896void PNGAPI
897png_set_flush(png_structrp png_ptr, int nrows)
898{
899   png_debug(1, "in png_set_flush");
900
901   if (png_ptr == NULL)
902      return;
903
904   png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
905}
906
907/* Flush the current output buffers now */
908void PNGAPI
909png_write_flush(png_structrp png_ptr)
910{
911   png_debug(1, "in png_write_flush");
912
913   if (png_ptr == NULL)
914      return;
915
916   /* We have already written out all of the data */
917   if (png_ptr->row_number >= png_ptr->num_rows)
918      return;
919
920   png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
921   png_ptr->flush_rows = 0;
922   png_flush(png_ptr);
923}
924#endif /* WRITE_FLUSH */
925
926/* Free any memory used in png_ptr struct without freeing the struct itself. */
927static void
928png_write_destroy(png_structrp png_ptr)
929{
930   png_debug(1, "in png_write_destroy");
931
932   /* Free any memory zlib uses */
933   if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
934      deflateEnd(&png_ptr->zstream);
935
936   /* Free our memory.  png_free checks NULL for us. */
937   png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
938   png_free(png_ptr, png_ptr->row_buf);
939   png_ptr->row_buf = NULL;
940#ifdef PNG_WRITE_FILTER_SUPPORTED
941   png_free(png_ptr, png_ptr->prev_row);
942   png_free(png_ptr, png_ptr->try_row);
943   png_free(png_ptr, png_ptr->tst_row);
944   png_ptr->prev_row = NULL;
945   png_ptr->try_row = NULL;
946   png_ptr->tst_row = NULL;
947#endif
948
949#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
950   png_free(png_ptr, png_ptr->chunk_list);
951   png_ptr->chunk_list = NULL;
952#endif
953
954   /* The error handling and memory handling information is left intact at this
955    * point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
956    * for how this happens.
957    */
958}
959
960/* Free all memory used by the write.
961 * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
962 * *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
963 * the passed in info_structs but it would quietly fail to free any of the data
964 * inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
965 * has no png_ptr.)
966 */
967void PNGAPI
968png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
969{
970   png_debug(1, "in png_destroy_write_struct");
971
972   if (png_ptr_ptr != NULL)
973   {
974      png_structrp png_ptr = *png_ptr_ptr;
975
976      if (png_ptr != NULL) /* added in libpng 1.6.0 */
977      {
978         png_destroy_info_struct(png_ptr, info_ptr_ptr);
979
980         *png_ptr_ptr = NULL;
981         png_write_destroy(png_ptr);
982         png_destroy_png_struct(png_ptr);
983      }
984   }
985}
986
987/* Allow the application to select one or more row filters to use. */
988void PNGAPI
989png_set_filter(png_structrp png_ptr, int method, int filters)
990{
991   png_debug(1, "in png_set_filter");
992
993   if (png_ptr == NULL)
994      return;
995
996#ifdef PNG_MNG_FEATURES_SUPPORTED
997   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
998       (method == PNG_INTRAPIXEL_DIFFERENCING))
999      method = PNG_FILTER_TYPE_BASE;
1000
1001#endif
1002   if (method == PNG_FILTER_TYPE_BASE)
1003   {
1004      switch (filters & (PNG_ALL_FILTERS | 0x07))
1005      {
1006#ifdef PNG_WRITE_FILTER_SUPPORTED
1007         case 5:
1008         case 6:
1009         case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
1010            /* FALL THROUGH */
1011#endif /* WRITE_FILTER */
1012         case PNG_FILTER_VALUE_NONE:
1013            png_ptr->do_filter = PNG_FILTER_NONE; break;
1014
1015#ifdef PNG_WRITE_FILTER_SUPPORTED
1016         case PNG_FILTER_VALUE_SUB:
1017            png_ptr->do_filter = PNG_FILTER_SUB; break;
1018
1019         case PNG_FILTER_VALUE_UP:
1020            png_ptr->do_filter = PNG_FILTER_UP; break;
1021
1022         case PNG_FILTER_VALUE_AVG:
1023            png_ptr->do_filter = PNG_FILTER_AVG; break;
1024
1025         case PNG_FILTER_VALUE_PAETH:
1026            png_ptr->do_filter = PNG_FILTER_PAETH; break;
1027
1028         default:
1029            png_ptr->do_filter = (png_byte)filters; break;
1030#else
1031         default:
1032            png_app_error(png_ptr, "Unknown row filter for method 0");
1033#endif /* WRITE_FILTER */
1034      }
1035
1036#ifdef PNG_WRITE_FILTER_SUPPORTED
1037      /* If we have allocated the row_buf, this means we have already started
1038       * with the image and we should have allocated all of the filter buffers
1039       * that have been selected.  If prev_row isn't already allocated, then
1040       * it is too late to start using the filters that need it, since we
1041       * will be missing the data in the previous row.  If an application
1042       * wants to start and stop using particular filters during compression,
1043       * it should start out with all of the filters, and then remove them
1044       * or add them back after the start of compression.
1045       *
1046       * NOTE: this is a nasty constraint on the code, because it means that the
1047       * prev_row buffer must be maintained even if there are currently no
1048       * 'prev_row' requiring filters active.
1049       */
1050      if (png_ptr->row_buf != NULL)
1051      {
1052         int num_filters;
1053         png_alloc_size_t buf_size;
1054
1055         /* Repeat the checks in png_write_start_row; 1 pixel high or wide
1056          * images cannot benefit from certain filters.  If this isn't done here
1057          * the check below will fire on 1 pixel high images.
1058          */
1059         if (png_ptr->height == 1)
1060            filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1061
1062         if (png_ptr->width == 1)
1063            filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1064
1065         if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0
1066            && png_ptr->prev_row == NULL)
1067         {
1068            /* This is the error case, however it is benign - the previous row
1069             * is not available so the filter can't be used.  Just warn here.
1070             */
1071            png_app_warning(png_ptr,
1072               "png_set_filter: UP/AVG/PAETH cannot be added after start");
1073            filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1074         }
1075
1076         num_filters = 0;
1077
1078         if (filters & PNG_FILTER_SUB)
1079            num_filters++;
1080
1081         if (filters & PNG_FILTER_UP)
1082            num_filters++;
1083
1084         if (filters & PNG_FILTER_AVG)
1085            num_filters++;
1086
1087         if (filters & PNG_FILTER_PAETH)
1088            num_filters++;
1089
1090         /* Allocate needed row buffers if they have not already been
1091          * allocated.
1092          */
1093         buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth,
1094             png_ptr->width) + 1;
1095
1096         if (png_ptr->try_row == NULL)
1097            png_ptr->try_row = png_voidcast(png_bytep,
1098               png_malloc(png_ptr, buf_size));
1099
1100         if (num_filters > 1)
1101         {
1102            if (png_ptr->tst_row == NULL)
1103               png_ptr->tst_row = png_voidcast(png_bytep,
1104                  png_malloc(png_ptr, buf_size));
1105         }
1106      }
1107      png_ptr->do_filter = (png_byte)filters;
1108#endif
1109   }
1110   else
1111      png_error(png_ptr, "Unknown custom filter method");
1112}
1113
1114#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
1115/* Provide floating and fixed point APIs */
1116#ifdef PNG_FLOATING_POINT_SUPPORTED
1117void PNGAPI
1118png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
1119    int num_weights, png_const_doublep filter_weights,
1120    png_const_doublep filter_costs)
1121{
1122   PNG_UNUSED(png_ptr)
1123   PNG_UNUSED(heuristic_method)
1124   PNG_UNUSED(num_weights)
1125   PNG_UNUSED(filter_weights)
1126   PNG_UNUSED(filter_costs)
1127}
1128#endif /* FLOATING_POINT */
1129
1130#ifdef PNG_FIXED_POINT_SUPPORTED
1131void PNGAPI
1132png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
1133    int num_weights, png_const_fixed_point_p filter_weights,
1134    png_const_fixed_point_p filter_costs)
1135{
1136   PNG_UNUSED(png_ptr)
1137   PNG_UNUSED(heuristic_method)
1138   PNG_UNUSED(num_weights)
1139   PNG_UNUSED(filter_weights)
1140   PNG_UNUSED(filter_costs)
1141}
1142#endif /* FIXED_POINT */
1143#endif /* WRITE_WEIGHTED_FILTER */
1144
1145#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
1146void PNGAPI
1147png_set_compression_level(png_structrp png_ptr, int level)
1148{
1149   png_debug(1, "in png_set_compression_level");
1150
1151   if (png_ptr == NULL)
1152      return;
1153
1154   png_ptr->zlib_level = level;
1155}
1156
1157void PNGAPI
1158png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
1159{
1160   png_debug(1, "in png_set_compression_mem_level");
1161
1162   if (png_ptr == NULL)
1163      return;
1164
1165   png_ptr->zlib_mem_level = mem_level;
1166}
1167
1168void PNGAPI
1169png_set_compression_strategy(png_structrp png_ptr, int strategy)
1170{
1171   png_debug(1, "in png_set_compression_strategy");
1172
1173   if (png_ptr == NULL)
1174      return;
1175
1176   /* The flag setting here prevents the libpng dynamic selection of strategy.
1177    */
1178   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
1179   png_ptr->zlib_strategy = strategy;
1180}
1181
1182/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1183 * smaller value of window_bits if it can do so safely.
1184 */
1185void PNGAPI
1186png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
1187{
1188   if (png_ptr == NULL)
1189      return;
1190
1191   /* Prior to 1.6.0 this would warn but then set the window_bits value. This
1192    * meant that negative window bits values could be selected that would cause
1193    * libpng to write a non-standard PNG file with raw deflate or gzip
1194    * compressed IDAT or ancillary chunks.  Such files can be read and there is
1195    * no warning on read, so this seems like a very bad idea.
1196    */
1197   if (window_bits > 15)
1198   {
1199      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1200      window_bits = 15;
1201   }
1202
1203   else if (window_bits < 8)
1204   {
1205      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
1206      window_bits = 8;
1207   }
1208
1209   png_ptr->zlib_window_bits = window_bits;
1210}
1211
1212void PNGAPI
1213png_set_compression_method(png_structrp png_ptr, int method)
1214{
1215   png_debug(1, "in png_set_compression_method");
1216
1217   if (png_ptr == NULL)
1218      return;
1219
1220   /* This would produce an invalid PNG file if it worked, but it doesn't and
1221    * deflate will fault it, so it is harmless to just warn here.
1222    */
1223   if (method != 8)
1224      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1225
1226   png_ptr->zlib_method = method;
1227}
1228#endif /* WRITE_CUSTOMIZE_COMPRESSION */
1229
1230/* The following were added to libpng-1.5.4 */
1231#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1232void PNGAPI
1233png_set_text_compression_level(png_structrp png_ptr, int level)
1234{
1235   png_debug(1, "in png_set_text_compression_level");
1236
1237   if (png_ptr == NULL)
1238      return;
1239
1240   png_ptr->zlib_text_level = level;
1241}
1242
1243void PNGAPI
1244png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
1245{
1246   png_debug(1, "in png_set_text_compression_mem_level");
1247
1248   if (png_ptr == NULL)
1249      return;
1250
1251   png_ptr->zlib_text_mem_level = mem_level;
1252}
1253
1254void PNGAPI
1255png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
1256{
1257   png_debug(1, "in png_set_text_compression_strategy");
1258
1259   if (png_ptr == NULL)
1260      return;
1261
1262   png_ptr->zlib_text_strategy = strategy;
1263}
1264
1265/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1266 * smaller value of window_bits if it can do so safely.
1267 */
1268void PNGAPI
1269png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
1270{
1271   if (png_ptr == NULL)
1272      return;
1273
1274   if (window_bits > 15)
1275   {
1276      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1277      window_bits = 15;
1278   }
1279
1280   else if (window_bits < 8)
1281   {
1282      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
1283      window_bits = 8;
1284   }
1285
1286   png_ptr->zlib_text_window_bits = window_bits;
1287}
1288
1289void PNGAPI
1290png_set_text_compression_method(png_structrp png_ptr, int method)
1291{
1292   png_debug(1, "in png_set_text_compression_method");
1293
1294   if (png_ptr == NULL)
1295      return;
1296
1297   if (method != 8)
1298      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1299
1300   png_ptr->zlib_text_method = method;
1301}
1302#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
1303/* end of API added to libpng-1.5.4 */
1304
1305void PNGAPI
1306png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
1307{
1308   if (png_ptr == NULL)
1309      return;
1310
1311   png_ptr->write_row_fn = write_row_fn;
1312}
1313
1314#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1315void PNGAPI
1316png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1317    write_user_transform_fn)
1318{
1319   png_debug(1, "in png_set_write_user_transform_fn");
1320
1321   if (png_ptr == NULL)
1322      return;
1323
1324   png_ptr->transformations |= PNG_USER_TRANSFORM;
1325   png_ptr->write_user_transform_fn = write_user_transform_fn;
1326}
1327#endif
1328
1329
1330#ifdef PNG_INFO_IMAGE_SUPPORTED
1331void PNGAPI
1332png_write_png(png_structrp png_ptr, png_inforp info_ptr,
1333    int transforms, voidp params)
1334{
1335   if (png_ptr == NULL || info_ptr == NULL)
1336      return;
1337
1338   if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
1339   {
1340      png_app_error(png_ptr, "no rows for png_write_image to write");
1341      return;
1342   }
1343
1344   /* Write the file header information. */
1345   png_write_info(png_ptr, info_ptr);
1346
1347   /* ------ these transformations don't touch the info structure ------- */
1348
1349   /* Invert monochrome pixels */
1350   if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
1351#ifdef PNG_WRITE_INVERT_SUPPORTED
1352      png_set_invert_mono(png_ptr);
1353#else
1354      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
1355#endif
1356
1357   /* Shift the pixels up to a legal bit depth and fill in
1358    * as appropriate to correctly scale the image.
1359    */
1360   if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
1361#ifdef PNG_WRITE_SHIFT_SUPPORTED
1362      if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
1363         png_set_shift(png_ptr, &info_ptr->sig_bit);
1364#else
1365      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
1366#endif
1367
1368   /* Pack pixels into bytes */
1369   if ((transforms & PNG_TRANSFORM_PACKING) != 0)
1370#ifdef PNG_WRITE_PACK_SUPPORTED
1371      png_set_packing(png_ptr);
1372#else
1373      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
1374#endif
1375
1376   /* Swap location of alpha bytes from ARGB to RGBA */
1377   if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
1378#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
1379      png_set_swap_alpha(png_ptr);
1380#else
1381      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
1382#endif
1383
1384   /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
1385    * RGB, note that the code expects the input color type to be G or RGB; no
1386    * alpha channel.
1387    */
1388   if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
1389       PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
1390   {
1391#ifdef PNG_WRITE_FILLER_SUPPORTED
1392      if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
1393      {
1394         if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1395            png_app_error(png_ptr,
1396                "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
1397
1398         /* Continue if ignored - this is the pre-1.6.10 behavior */
1399         png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1400      }
1401
1402      else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1403         png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1404#else
1405      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
1406#endif
1407   }
1408
1409   /* Flip BGR pixels to RGB */
1410   if ((transforms & PNG_TRANSFORM_BGR) != 0)
1411#ifdef PNG_WRITE_BGR_SUPPORTED
1412      png_set_bgr(png_ptr);
1413#else
1414      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
1415#endif
1416
1417   /* Swap bytes of 16-bit files to most significant byte first */
1418   if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
1419#ifdef PNG_WRITE_SWAP_SUPPORTED
1420      png_set_swap(png_ptr);
1421#else
1422      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
1423#endif
1424
1425   /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
1426   if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
1427#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
1428      png_set_packswap(png_ptr);
1429#else
1430      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
1431#endif
1432
1433   /* Invert the alpha channel from opacity to transparency */
1434   if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
1435#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1436      png_set_invert_alpha(png_ptr);
1437#else
1438      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
1439#endif
1440
1441   /* ----------------------- end of transformations ------------------- */
1442
1443   /* Write the bits */
1444   png_write_image(png_ptr, info_ptr->row_pointers);
1445
1446   /* It is REQUIRED to call this to finish writing the rest of the file */
1447   png_write_end(png_ptr, info_ptr);
1448
1449   PNG_UNUSED(params)
1450}
1451#endif
1452
1453
1454#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1455/* Initialize the write structure - general purpose utility. */
1456static int
1457png_image_write_init(png_imagep image)
1458{
1459   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1460       png_safe_error, png_safe_warning);
1461
1462   if (png_ptr != NULL)
1463   {
1464      png_infop info_ptr = png_create_info_struct(png_ptr);
1465
1466      if (info_ptr != NULL)
1467      {
1468         png_controlp control = png_voidcast(png_controlp,
1469             png_malloc_warn(png_ptr, (sizeof *control)));
1470
1471         if (control != NULL)
1472         {
1473            memset(control, 0, (sizeof *control));
1474
1475            control->png_ptr = png_ptr;
1476            control->info_ptr = info_ptr;
1477            control->for_write = 1;
1478
1479            image->opaque = control;
1480            return 1;
1481         }
1482
1483         /* Error clean up */
1484         png_destroy_info_struct(png_ptr, &info_ptr);
1485      }
1486
1487      png_destroy_write_struct(&png_ptr, NULL);
1488   }
1489
1490   return png_image_error(image, "png_image_write_: out of memory");
1491}
1492
1493/* Arguments to png_image_write_main: */
1494typedef struct
1495{
1496   /* Arguments: */
1497   png_imagep      image;
1498   png_const_voidp buffer;
1499   png_int_32      row_stride;
1500   png_const_voidp colormap;
1501   int             convert_to_8bit;
1502   /* Local variables: */
1503   png_const_voidp first_row;
1504   ptrdiff_t       row_bytes;
1505   png_voidp       local_row;
1506   /* Byte count for memory writing */
1507   png_bytep        memory;
1508   png_alloc_size_t memory_bytes; /* not used for STDIO */
1509   png_alloc_size_t output_bytes; /* running total */
1510} png_image_write_control;
1511
1512/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1513 * do any necessary byte swapping.  The component order is defined by the
1514 * png_image format value.
1515 */
1516static int
1517png_write_image_16bit(png_voidp argument)
1518{
1519   png_image_write_control *display = png_voidcast(png_image_write_control*,
1520       argument);
1521   png_imagep image = display->image;
1522   png_structrp png_ptr = image->opaque->png_ptr;
1523
1524   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1525       display->first_row);
1526   png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
1527   png_uint_16p row_end;
1528   const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1529   int aindex = 0;
1530   png_uint_32 y = image->height;
1531
1532   if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1533   {
1534#   ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1535      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1536      {
1537         aindex = -1;
1538         ++input_row; /* To point to the first component */
1539         ++output_row;
1540      }
1541         else
1542            aindex = channels;
1543#     else
1544         aindex = channels;
1545#     endif
1546   }
1547
1548   else
1549      png_error(png_ptr, "png_write_image: internal call error");
1550
1551   /* Work out the output row end and count over this, note that the increment
1552    * above to 'row' means that row_end can actually be beyond the end of the
1553    * row; this is correct.
1554    */
1555   row_end = output_row + image->width * (channels+1);
1556
1557   while (y-- > 0)
1558   {
1559      png_const_uint_16p in_ptr = input_row;
1560      png_uint_16p out_ptr = output_row;
1561
1562      while (out_ptr < row_end)
1563      {
1564         const png_uint_16 alpha = in_ptr[aindex];
1565         png_uint_32 reciprocal = 0;
1566         int c;
1567
1568         out_ptr[aindex] = alpha;
1569
1570         /* Calculate a reciprocal.  The correct calculation is simply
1571          * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
1572          * allows correct rounding by adding .5 before the shift.  'reciprocal'
1573          * is only initialized when required.
1574          */
1575         if (alpha > 0 && alpha < 65535)
1576            reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
1577
1578         c = channels;
1579         do /* always at least one channel */
1580         {
1581            png_uint_16 component = *in_ptr++;
1582
1583            /* The following gives 65535 for an alpha of 0, which is fine,
1584             * otherwise if 0/0 is represented as some other value there is more
1585             * likely to be a discontinuity which will probably damage
1586             * compression when moving from a fully transparent area to a
1587             * nearly transparent one.  (The assumption here is that opaque
1588             * areas tend not to be 0 intensity.)
1589             */
1590            if (component >= alpha)
1591               component = 65535;
1592
1593            /* component<alpha, so component/alpha is less than one and
1594             * component*reciprocal is less than 2^31.
1595             */
1596            else if (component > 0 && alpha < 65535)
1597            {
1598               png_uint_32 calc = component * reciprocal;
1599               calc += 16384; /* round to nearest */
1600               component = (png_uint_16)(calc >> 15);
1601            }
1602
1603            *out_ptr++ = component;
1604         }
1605         while (--c > 0);
1606
1607         /* Skip to next component (skip the intervening alpha channel) */
1608         ++in_ptr;
1609         ++out_ptr;
1610      }
1611
1612      png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
1613      input_row += display->row_bytes/(sizeof (png_uint_16));
1614   }
1615
1616   return 1;
1617}
1618
1619/* Given 16-bit input (1 to 4 channels) write 8-bit output.  If an alpha channel
1620 * is present it must be removed from the components, the components are then
1621 * written in sRGB encoding.  No components are added or removed.
1622 *
1623 * Calculate an alpha reciprocal to reverse pre-multiplication.  As above the
1624 * calculation can be done to 15 bits of accuracy; however, the output needs to
1625 * be scaled in the range 0..255*65535, so include that scaling here.
1626 */
1627#   define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
1628
1629static png_byte
1630png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
1631   png_uint_32 reciprocal/*from the above macro*/)
1632{
1633   /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
1634    * is represented as some other value there is more likely to be a
1635    * discontinuity which will probably damage compression when moving from a
1636    * fully transparent area to a nearly transparent one.  (The assumption here
1637    * is that opaque areas tend not to be 0 intensity.)
1638    *
1639    * There is a rounding problem here; if alpha is less than 128 it will end up
1640    * as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
1641    * output change for this too.
1642    */
1643   if (component >= alpha || alpha < 128)
1644      return 255;
1645
1646   /* component<alpha, so component/alpha is less than one and
1647    * component*reciprocal is less than 2^31.
1648    */
1649   else if (component > 0)
1650   {
1651      /* The test is that alpha/257 (rounded) is less than 255, the first value
1652       * that becomes 255 is 65407.
1653       * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
1654       * be exact!)  [Could also test reciprocal != 0]
1655       */
1656      if (alpha < 65407)
1657      {
1658         component *= reciprocal;
1659         component += 64; /* round to nearest */
1660         component >>= 7;
1661      }
1662
1663      else
1664         component *= 255;
1665
1666      /* Convert the component to sRGB. */
1667      return (png_byte)PNG_sRGB_FROM_LINEAR(component);
1668   }
1669
1670   else
1671      return 0;
1672}
1673
1674static int
1675png_write_image_8bit(png_voidp argument)
1676{
1677   png_image_write_control *display = png_voidcast(png_image_write_control*,
1678       argument);
1679   png_imagep image = display->image;
1680   png_structrp png_ptr = image->opaque->png_ptr;
1681
1682   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
1683       display->first_row);
1684   png_bytep output_row = png_voidcast(png_bytep, display->local_row);
1685   png_uint_32 y = image->height;
1686   const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
1687
1688   if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1689   {
1690      png_bytep row_end;
1691      int aindex;
1692
1693#   ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1694      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1695      {
1696         aindex = -1;
1697         ++input_row; /* To point to the first component */
1698         ++output_row;
1699      }
1700
1701      else
1702#   endif
1703      aindex = channels;
1704
1705      /* Use row_end in place of a loop counter: */
1706      row_end = output_row + image->width * (channels+1);
1707
1708      while (y-- > 0)
1709      {
1710         png_const_uint_16p in_ptr = input_row;
1711         png_bytep out_ptr = output_row;
1712
1713         while (out_ptr < row_end)
1714         {
1715            png_uint_16 alpha = in_ptr[aindex];
1716            png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
1717            png_uint_32 reciprocal = 0;
1718            int c;
1719
1720            /* Scale and write the alpha channel. */
1721            out_ptr[aindex] = alphabyte;
1722
1723            if (alphabyte > 0 && alphabyte < 255)
1724               reciprocal = UNP_RECIPROCAL(alpha);
1725
1726            c = channels;
1727            do /* always at least one channel */
1728               *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
1729            while (--c > 0);
1730
1731            /* Skip to next component (skip the intervening alpha channel) */
1732            ++in_ptr;
1733            ++out_ptr;
1734         } /* while out_ptr < row_end */
1735
1736         png_write_row(png_ptr, png_voidcast(png_const_bytep,
1737             display->local_row));
1738         input_row += display->row_bytes/(sizeof (png_uint_16));
1739      } /* while y */
1740   }
1741
1742   else
1743   {
1744      /* No alpha channel, so the row_end really is the end of the row and it
1745       * is sufficient to loop over the components one by one.
1746       */
1747      png_bytep row_end = output_row + image->width * channels;
1748
1749      while (y-- > 0)
1750      {
1751         png_const_uint_16p in_ptr = input_row;
1752         png_bytep out_ptr = output_row;
1753
1754         while (out_ptr < row_end)
1755         {
1756            png_uint_32 component = *in_ptr++;
1757
1758            component *= 255;
1759            *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
1760         }
1761
1762         png_write_row(png_ptr, output_row);
1763         input_row += display->row_bytes/(sizeof (png_uint_16));
1764      }
1765   }
1766
1767   return 1;
1768}
1769
1770static void
1771png_image_set_PLTE(png_image_write_control *display)
1772{
1773   const png_imagep image = display->image;
1774   const void *cmap = display->colormap;
1775   const int entries = image->colormap_entries > 256 ? 256 :
1776       (int)image->colormap_entries;
1777
1778   /* NOTE: the caller must check for cmap != NULL and entries != 0 */
1779   const png_uint_32 format = image->format;
1780   const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
1781
1782#   if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
1783      defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
1784      const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
1785          (format & PNG_FORMAT_FLAG_ALPHA) != 0;
1786#   else
1787#     define afirst 0
1788#   endif
1789
1790#   ifdef PNG_FORMAT_BGR_SUPPORTED
1791      const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
1792#   else
1793#     define bgr 0
1794#   endif
1795
1796   int i, num_trans;
1797   png_color palette[256];
1798   png_byte tRNS[256];
1799
1800   memset(tRNS, 255, (sizeof tRNS));
1801   memset(palette, 0, (sizeof palette));
1802
1803   for (i=num_trans=0; i<entries; ++i)
1804   {
1805      /* This gets automatically converted to sRGB with reversal of the
1806       * pre-multiplication if the color-map has an alpha channel.
1807       */
1808      if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
1809      {
1810         png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
1811
1812         entry += i * channels;
1813
1814         if ((channels & 1) != 0) /* no alpha */
1815         {
1816            if (channels >= 3) /* RGB */
1817            {
1818               palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1819                   entry[(2 ^ bgr)]);
1820               palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1821                   entry[1]);
1822               palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1823                   entry[bgr]);
1824            }
1825
1826            else /* Gray */
1827               palette[i].blue = palette[i].red = palette[i].green =
1828                  (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
1829         }
1830
1831         else /* alpha */
1832         {
1833            png_uint_16 alpha = entry[afirst ? 0 : channels-1];
1834            png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
1835            png_uint_32 reciprocal = 0;
1836
1837            /* Calculate a reciprocal, as in the png_write_image_8bit code above
1838             * this is designed to produce a value scaled to 255*65535 when
1839             * divided by 128 (i.e. asr 7).
1840             */
1841            if (alphabyte > 0 && alphabyte < 255)
1842               reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
1843
1844            tRNS[i] = alphabyte;
1845            if (alphabyte < 255)
1846               num_trans = i+1;
1847
1848            if (channels >= 3) /* RGB */
1849            {
1850               palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
1851                  alpha, reciprocal);
1852               palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
1853                  reciprocal);
1854               palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
1855                  reciprocal);
1856            }
1857
1858            else /* gray */
1859               palette[i].blue = palette[i].red = palette[i].green =
1860                  png_unpremultiply(entry[afirst], alpha, reciprocal);
1861         }
1862      }
1863
1864      else /* Color-map has sRGB values */
1865      {
1866         png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
1867
1868         entry += i * channels;
1869
1870         switch (channels)
1871         {
1872            case 4:
1873               tRNS[i] = entry[afirst ? 0 : 3];
1874               if (tRNS[i] < 255)
1875                  num_trans = i+1;
1876               /* FALL THROUGH */
1877            case 3:
1878               palette[i].blue = entry[afirst + (2 ^ bgr)];
1879               palette[i].green = entry[afirst + 1];
1880               palette[i].red = entry[afirst + bgr];
1881               break;
1882
1883            case 2:
1884               tRNS[i] = entry[1 ^ afirst];
1885               if (tRNS[i] < 255)
1886                  num_trans = i+1;
1887               /* FALL THROUGH */
1888            case 1:
1889               palette[i].blue = palette[i].red = palette[i].green =
1890                  entry[afirst];
1891               break;
1892
1893            default:
1894               break;
1895         }
1896      }
1897   }
1898
1899#   ifdef afirst
1900#     undef afirst
1901#   endif
1902#   ifdef bgr
1903#     undef bgr
1904#   endif
1905
1906   png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
1907      entries);
1908
1909   if (num_trans > 0)
1910      png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
1911         num_trans, NULL);
1912
1913   image->colormap_entries = entries;
1914}
1915
1916static int
1917png_image_write_main(png_voidp argument)
1918{
1919   png_image_write_control *display = png_voidcast(png_image_write_control*,
1920      argument);
1921   png_imagep image = display->image;
1922   png_structrp png_ptr = image->opaque->png_ptr;
1923   png_inforp info_ptr = image->opaque->info_ptr;
1924   png_uint_32 format = image->format;
1925
1926   /* The following four ints are actually booleans */
1927   int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
1928   int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
1929   int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
1930   int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
1931
1932#   ifdef PNG_BENIGN_ERRORS_SUPPORTED
1933      /* Make sure we error out on any bad situation */
1934      png_set_benign_errors(png_ptr, 0/*error*/);
1935#   endif
1936
1937   /* Default the 'row_stride' parameter if required, also check the row stride
1938    * and total image size to ensure that they are within the system limits.
1939    */
1940   {
1941      const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
1942
1943      if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
1944      {
1945         png_uint_32 check;
1946         const png_uint_32 png_row_stride = image->width * channels;
1947
1948         if (display->row_stride == 0)
1949            display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
1950
1951         if (display->row_stride < 0)
1952            check = -display->row_stride;
1953
1954         else
1955            check = display->row_stride;
1956
1957         if (check >= png_row_stride)
1958         {
1959            /* Now check for overflow of the image buffer calculation; this
1960             * limits the whole image size to 32 bits for API compatibility with
1961             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
1962             */
1963            if (image->height > 0xFFFFFFFF/png_row_stride)
1964               png_error(image->opaque->png_ptr, "memory image too large");
1965         }
1966
1967         else
1968            png_error(image->opaque->png_ptr, "supplied row stride too small");
1969      }
1970
1971      else
1972         png_error(image->opaque->png_ptr, "image row stride too large");
1973   }
1974
1975   /* Set the required transforms then write the rows in the correct order. */
1976   if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
1977   {
1978      if (display->colormap != NULL && image->colormap_entries > 0)
1979      {
1980         png_uint_32 entries = image->colormap_entries;
1981
1982         png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
1983            entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
1984            PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
1985            PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1986
1987         png_image_set_PLTE(display);
1988      }
1989
1990      else
1991         png_error(image->opaque->png_ptr,
1992            "no color-map for color-mapped image");
1993   }
1994
1995   else
1996      png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
1997         write_16bit ? 16 : 8,
1998         ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
1999         ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
2000         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
2001
2002   /* Counter-intuitively the data transformations must be called *after*
2003    * png_write_info, not before as in the read code, but the 'set' functions
2004    * must still be called before.  Just set the color space information, never
2005    * write an interlaced image.
2006    */
2007
2008   if (write_16bit != 0)
2009   {
2010      /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
2011      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
2012
2013      if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2014         png_set_cHRM_fixed(png_ptr, info_ptr,
2015            /* color      x       y */
2016            /* white */ 31270, 32900,
2017            /* red   */ 64000, 33000,
2018            /* green */ 30000, 60000,
2019            /* blue  */ 15000,  6000
2020         );
2021   }
2022
2023   else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2024      png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
2025
2026   /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
2027    * space must still be gamma encoded.
2028    */
2029   else
2030      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
2031
2032   /* Write the file header. */
2033   png_write_info(png_ptr, info_ptr);
2034
2035   /* Now set up the data transformations (*after* the header is written),
2036    * remove the handled transformations from the 'format' flags for checking.
2037    *
2038    * First check for a little endian system if writing 16-bit files.
2039    */
2040   if (write_16bit != 0)
2041   {
2042      PNG_CONST png_uint_16 le = 0x0001;
2043
2044      if ((*(png_const_bytep) & le) != 0)
2045         png_set_swap(png_ptr);
2046   }
2047
2048#   ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
2049      if ((format & PNG_FORMAT_FLAG_BGR) != 0)
2050      {
2051         if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
2052            png_set_bgr(png_ptr);
2053         format &= ~PNG_FORMAT_FLAG_BGR;
2054      }
2055#   endif
2056
2057#   ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
2058      if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
2059      {
2060         if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
2061            png_set_swap_alpha(png_ptr);
2062         format &= ~PNG_FORMAT_FLAG_AFIRST;
2063      }
2064#   endif
2065
2066   /* If there are 16 or fewer color-map entries we wrote a lower bit depth
2067    * above, but the application data is still byte packed.
2068    */
2069   if (colormap != 0 && image->colormap_entries <= 16)
2070      png_set_packing(png_ptr);
2071
2072   /* That should have handled all (both) the transforms. */
2073   if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
2074         PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
2075      png_error(png_ptr, "png_write_image: unsupported transformation");
2076
2077   {
2078      png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
2079      ptrdiff_t row_bytes = display->row_stride;
2080
2081      if (linear != 0)
2082         row_bytes *= (sizeof (png_uint_16));
2083
2084      if (row_bytes < 0)
2085         row += (image->height-1) * (-row_bytes);
2086
2087      display->first_row = row;
2088      display->row_bytes = row_bytes;
2089   }
2090
2091   /* Apply 'fast' options if the flag is set. */
2092   if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
2093   {
2094      png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
2095      /* NOTE: determined by experiment using pngstest, this reflects some
2096       * balance between the time to write the image once and the time to read
2097       * it about 50 times.  The speed-up in pngstest was about 10-20% of the
2098       * total (user) time on a heavily loaded system.
2099       */
2100#   ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
2101      png_set_compression_level(png_ptr, 3);
2102#   endif
2103   }
2104
2105   /* Check for the cases that currently require a pre-transform on the row
2106    * before it is written.  This only applies when the input is 16-bit and
2107    * either there is an alpha channel or it is converted to 8-bit.
2108    */
2109   if ((linear != 0 && alpha != 0 ) ||
2110       (colormap == 0 && display->convert_to_8bit != 0))
2111   {
2112      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
2113         png_get_rowbytes(png_ptr, info_ptr)));
2114      int result;
2115
2116      display->local_row = row;
2117      if (write_16bit != 0)
2118         result = png_safe_execute(image, png_write_image_16bit, display);
2119      else
2120         result = png_safe_execute(image, png_write_image_8bit, display);
2121      display->local_row = NULL;
2122
2123      png_free(png_ptr, row);
2124
2125      /* Skip the 'write_end' on error: */
2126      if (result == 0)
2127         return 0;
2128   }
2129
2130   /* Otherwise this is the case where the input is in a format currently
2131    * supported by the rest of the libpng write code; call it directly.
2132    */
2133   else
2134   {
2135      png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
2136      ptrdiff_t row_bytes = display->row_bytes;
2137      png_uint_32 y = image->height;
2138
2139      while (y-- > 0)
2140      {
2141         png_write_row(png_ptr, row);
2142         row += row_bytes;
2143      }
2144   }
2145
2146   png_write_end(png_ptr, info_ptr);
2147   return 1;
2148}
2149
2150
2151static void (PNGCBAPI
2152image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
2153   png_size_t size)
2154{
2155   png_image_write_control *display = png_voidcast(png_image_write_control*,
2156      png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
2157   const png_alloc_size_t ob = display->output_bytes;
2158
2159   /* Check for overflow; this should never happen: */
2160   if (size <= ((png_alloc_size_t)-1) - ob)
2161   {
2162      /* I don't think libpng ever does this, but just in case: */
2163      if (size > 0)
2164      {
2165         if (display->memory_bytes >= ob+size) /* writing */
2166            memcpy(display->memory+ob, data, size);
2167
2168         /* Always update the size: */
2169         display->output_bytes = ob+size;
2170      }
2171   }
2172
2173   else
2174      png_error(png_ptr, "png_image_write_to_memory: PNG too big");
2175}
2176
2177static void (PNGCBAPI
2178image_memory_flush)(png_structp png_ptr)
2179{
2180   PNG_UNUSED(png_ptr)
2181}
2182
2183static int
2184png_image_write_memory(png_voidp argument)
2185{
2186   png_image_write_control *display = png_voidcast(png_image_write_control*,
2187      argument);
2188
2189   /* The rest of the memory-specific init and write_main in an error protected
2190    * environment.  This case needs to use callbacks for the write operations
2191    * since libpng has no built in support for writing to memory.
2192    */
2193   png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
2194         image_memory_write, image_memory_flush);
2195
2196   return png_image_write_main(display);
2197}
2198
2199int PNGAPI
2200png_image_write_to_memory(png_imagep image, void *memory,
2201   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
2202   const void *buffer, png_int_32 row_stride, const void *colormap)
2203{
2204   /* Write the image to the given buffer, or count the bytes if it is NULL */
2205   if (image != NULL && image->version == PNG_IMAGE_VERSION)
2206   {
2207      if (memory_bytes != NULL && buffer != NULL)
2208      {
2209         /* This is to give the caller an easier error detection in the NULL
2210          * case and guard against uninitialized variable problems:
2211          */
2212         if (memory == NULL)
2213            *memory_bytes = 0;
2214
2215         if (png_image_write_init(image) != 0)
2216         {
2217            png_image_write_control display;
2218            int result;
2219
2220            memset(&display, 0, (sizeof display));
2221            display.image = image;
2222            display.buffer = buffer;
2223            display.row_stride = row_stride;
2224            display.colormap = colormap;
2225            display.convert_to_8bit = convert_to_8bit;
2226            display.memory = png_voidcast(png_bytep, memory);
2227            display.memory_bytes = *memory_bytes;
2228            display.output_bytes = 0;
2229
2230            result = png_safe_execute(image, png_image_write_memory, &display);
2231            png_image_free(image);
2232
2233            /* write_memory returns true even if we ran out of buffer. */
2234            if (result)
2235            {
2236               /* On out-of-buffer this function returns '0' but still updates
2237                * memory_bytes:
2238                */
2239               if (memory != NULL && display.output_bytes > *memory_bytes)
2240                  result = 0;
2241
2242               *memory_bytes = display.output_bytes;
2243            }
2244
2245            return result;
2246         }
2247
2248         else
2249            return 0;
2250      }
2251
2252      else
2253         return png_image_error(image,
2254            "png_image_write_to_memory: invalid argument");
2255   }
2256
2257   else if (image != NULL)
2258      return png_image_error(image,
2259         "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
2260
2261   else
2262      return 0;
2263}
2264
2265#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
2266int PNGAPI
2267png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
2268   const void *buffer, png_int_32 row_stride, const void *colormap)
2269{
2270   /* Write the image to the given (FILE*). */
2271   if (image != NULL && image->version == PNG_IMAGE_VERSION)
2272   {
2273      if (file != NULL && buffer != NULL)
2274      {
2275         if (png_image_write_init(image) != 0)
2276         {
2277            png_image_write_control display;
2278            int result;
2279
2280            /* This is slightly evil, but png_init_io doesn't do anything other
2281             * than this and we haven't changed the standard IO functions so
2282             * this saves a 'safe' function.
2283             */
2284            image->opaque->png_ptr->io_ptr = file;
2285
2286            memset(&display, 0, (sizeof display));
2287            display.image = image;
2288            display.buffer = buffer;
2289            display.row_stride = row_stride;
2290            display.colormap = colormap;
2291            display.convert_to_8bit = convert_to_8bit;
2292
2293            result = png_safe_execute(image, png_image_write_main, &display);
2294            png_image_free(image);
2295            return result;
2296         }
2297
2298         else
2299            return 0;
2300      }
2301
2302      else
2303         return png_image_error(image,
2304            "png_image_write_to_stdio: invalid argument");
2305   }
2306
2307   else if (image != NULL)
2308      return png_image_error(image,
2309         "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
2310
2311   else
2312      return 0;
2313}
2314
2315int PNGAPI
2316png_image_write_to_file(png_imagep image, const char *file_name,
2317   int convert_to_8bit, const void *buffer, png_int_32 row_stride,
2318   const void *colormap)
2319{
2320   /* Write the image to the named file. */
2321   if (image != NULL && image->version == PNG_IMAGE_VERSION)
2322   {
2323      if (file_name != NULL && buffer != NULL)
2324      {
2325         FILE *fp = fopen(file_name, "wb");
2326
2327         if (fp != NULL)
2328         {
2329            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2330               row_stride, colormap) != 0)
2331            {
2332               int error; /* from fflush/fclose */
2333
2334               /* Make sure the file is flushed correctly. */
2335               if (fflush(fp) == 0 && ferror(fp) == 0)
2336               {
2337                  if (fclose(fp) == 0)
2338                     return 1;
2339
2340                  error = errno; /* from fclose */
2341               }
2342
2343               else
2344               {
2345                  error = errno; /* from fflush or ferror */
2346                  (void)fclose(fp);
2347               }
2348
2349               (void)remove(file_name);
2350               /* The image has already been cleaned up; this is just used to
2351                * set the error (because the original write succeeded).
2352                */
2353               return png_image_error(image, strerror(error));
2354            }
2355
2356            else
2357            {
2358               /* Clean up: just the opened file. */
2359               (void)fclose(fp);
2360               (void)remove(file_name);
2361               return 0;
2362            }
2363         }
2364
2365         else
2366            return png_image_error(image, strerror(errno));
2367      }
2368
2369      else
2370         return png_image_error(image,
2371            "png_image_write_to_file: invalid argument");
2372   }
2373
2374   else if (image != NULL)
2375      return png_image_error(image,
2376         "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
2377
2378   else
2379      return 0;
2380}
2381#endif /* SIMPLIFIED_WRITE_STDIO */
2382#endif /* SIMPLIFIED_WRITE */
2383#endif /* WRITE */
2384