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