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