]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/libpng/lib/dist/pngwutil.c
update: sync
[l4.git] / l4 / pkg / libpng / lib / dist / pngwutil.c
1
2 /* pngwutil.c - utilities to write a PNG file
3  *
4  * Last changed in libpng 1.5.14 [January 24, 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
14 #include "pngpriv.h"
15
16 #ifdef PNG_WRITE_SUPPORTED
17
18 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
19 /* Place a 32-bit number into a buffer in PNG byte order.  We work
20  * with unsigned numbers for convenience, although one supported
21  * ancillary chunk uses signed (two's complement) numbers.
22  */
23 void PNGAPI
24 png_save_uint_32(png_bytep buf, png_uint_32 i)
25 {
26    buf[0] = (png_byte)((i >> 24) & 0xff);
27    buf[1] = (png_byte)((i >> 16) & 0xff);
28    buf[2] = (png_byte)((i >> 8) & 0xff);
29    buf[3] = (png_byte)(i & 0xff);
30 }
31
32 #ifdef PNG_SAVE_INT_32_SUPPORTED
33 /* The png_save_int_32 function assumes integers are stored in two's
34  * complement format.  If this isn't the case, then this routine needs to
35  * be modified to write data in two's complement format.  Note that,
36  * the following works correctly even if png_int_32 has more than 32 bits
37  * (compare the more complex code required on read for sign extention.)
38  */
39 void PNGAPI
40 png_save_int_32(png_bytep buf, png_int_32 i)
41 {
42    buf[0] = (png_byte)((i >> 24) & 0xff);
43    buf[1] = (png_byte)((i >> 16) & 0xff);
44    buf[2] = (png_byte)((i >> 8) & 0xff);
45    buf[3] = (png_byte)(i & 0xff);
46 }
47 #endif
48
49 /* Place a 16-bit number into a buffer in PNG byte order.
50  * The parameter is declared unsigned int, not png_uint_16,
51  * just to avoid potential problems on pre-ANSI C compilers.
52  */
53 void PNGAPI
54 png_save_uint_16(png_bytep buf, unsigned int i)
55 {
56    buf[0] = (png_byte)((i >> 8) & 0xff);
57    buf[1] = (png_byte)(i & 0xff);
58 }
59 #endif
60
61 /* Simple function to write the signature.  If we have already written
62  * the magic bytes of the signature, or more likely, the PNG stream is
63  * being embedded into another stream and doesn't need its own signature,
64  * we should call png_set_sig_bytes() to tell libpng how many of the
65  * bytes have already been written.
66  */
67 void PNGAPI
68 png_write_sig(png_structp png_ptr)
69 {
70    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
71
72 #ifdef PNG_IO_STATE_SUPPORTED
73    /* Inform the I/O callback that the signature is being written */
74    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
75 #endif
76
77    /* Write the rest of the 8 byte signature */
78    png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
79       (png_size_t)(8 - png_ptr->sig_bytes));
80
81    if (png_ptr->sig_bytes < 3)
82       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
83 }
84
85 /* Write the start of a PNG chunk.  The type is the chunk type.
86  * The total_length is the sum of the lengths of all the data you will be
87  * passing in png_write_chunk_data().
88  */
89 static void
90 png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
91     png_uint_32 length)
92 {
93    png_byte buf[8];
94
95 #if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
96    PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
97    png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
98 #endif
99
100    if (png_ptr == NULL)
101       return;
102
103 #ifdef PNG_IO_STATE_SUPPORTED
104    /* Inform the I/O callback that the chunk header is being written.
105     * PNG_IO_CHUNK_HDR requires a single I/O call.
106     */
107    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
108 #endif
109
110    /* Write the length and the chunk name */
111    png_save_uint_32(buf, length);
112    png_save_uint_32(buf + 4, chunk_name);
113    png_write_data(png_ptr, buf, 8);
114
115    /* Put the chunk name into png_ptr->chunk_name */
116    png_ptr->chunk_name = chunk_name;
117
118    /* Reset the crc and run it over the chunk name */
119    png_reset_crc(png_ptr);
120
121    png_calculate_crc(png_ptr, buf + 4, 4);
122
123 #ifdef PNG_IO_STATE_SUPPORTED
124    /* Inform the I/O callback that chunk data will (possibly) be written.
125     * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
126     */
127    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
128 #endif
129 }
130
131 void PNGAPI
132 png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
133     png_uint_32 length)
134 {
135    png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
136 }
137
138 /* Write the data of a PNG chunk started with png_write_chunk_header().
139  * Note that multiple calls to this function are allowed, and that the
140  * sum of the lengths from these calls *must* add up to the total_length
141  * given to png_write_chunk_header().
142  */
143 void PNGAPI
144 png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
145     png_size_t length)
146 {
147    /* Write the data, and run the CRC over it */
148    if (png_ptr == NULL)
149       return;
150
151    if (data != NULL && length > 0)
152    {
153       png_write_data(png_ptr, data, length);
154
155       /* Update the CRC after writing the data,
156        * in case that the user I/O routine alters it.
157        */
158       png_calculate_crc(png_ptr, data, length);
159    }
160 }
161
162 /* Finish a chunk started with png_write_chunk_header(). */
163 void PNGAPI
164 png_write_chunk_end(png_structp png_ptr)
165 {
166    png_byte buf[4];
167
168    if (png_ptr == NULL) return;
169
170 #ifdef PNG_IO_STATE_SUPPORTED
171    /* Inform the I/O callback that the chunk CRC is being written.
172     * PNG_IO_CHUNK_CRC requires a single I/O function call.
173     */
174    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
175 #endif
176
177    /* Write the crc in a single operation */
178    png_save_uint_32(buf, png_ptr->crc);
179
180    png_write_data(png_ptr, buf, (png_size_t)4);
181 }
182
183 /* Write a PNG chunk all at once.  The type is an array of ASCII characters
184  * representing the chunk name.  The array must be at least 4 bytes in
185  * length, and does not need to be null terminated.  To be safe, pass the
186  * pre-defined chunk names here, and if you need a new one, define it
187  * where the others are defined.  The length is the length of the data.
188  * All the data must be present.  If that is not possible, use the
189  * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
190  * functions instead.
191  */
192 static void
193 png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
194    png_const_bytep data, png_size_t length)
195 {
196    if (png_ptr == NULL)
197       return;
198
199    /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
200    if (length > PNG_UINT_32_MAX)
201       png_error(png_ptr, "length exceeds PNG maxima");
202
203    png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
204    png_write_chunk_data(png_ptr, data, length);
205    png_write_chunk_end(png_ptr);
206 }
207
208 /* This is the API that calls the internal function above. */
209 void PNGAPI
210 png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string,
211    png_const_bytep data, png_size_t length)
212 {
213    png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
214       length);
215 }
216
217 /* Initialize the compressor for the appropriate type of compression. */
218 static void
219 png_zlib_claim(png_structp png_ptr, png_uint_32 state)
220 {
221    if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE))
222    {
223       /* If already initialized for 'state' do not re-init. */
224       if (png_ptr->zlib_state != state)
225       {
226          int ret = Z_OK;
227          png_const_charp who = "-";
228
229          /* If actually initialized for another state do a deflateEnd. */
230          if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
231          {
232             ret = deflateEnd(&png_ptr->zstream);
233             who = "end";
234             png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
235          }
236
237          /* zlib itself detects an incomplete state on deflateEnd */
238          if (ret == Z_OK) switch (state)
239          {
240 #           ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
241                case PNG_ZLIB_FOR_TEXT:
242                   ret = deflateInit2(&png_ptr->zstream,
243                      png_ptr->zlib_text_level, png_ptr->zlib_text_method,
244                      png_ptr->zlib_text_window_bits,
245                      png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);
246                   who = "text";
247                   break;
248 #           endif
249
250             case PNG_ZLIB_FOR_IDAT:
251                ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
252                    png_ptr->zlib_method, png_ptr->zlib_window_bits,
253                    png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
254                who = "IDAT";
255                break;
256
257             default:
258                png_error(png_ptr, "invalid zlib state");
259          }
260
261          if (ret == Z_OK)
262             png_ptr->zlib_state = state;
263
264          else /* an error in deflateEnd or deflateInit2 */
265          {
266             size_t pos = 0;
267             char msg[64];
268
269             pos = png_safecat(msg, sizeof msg, pos,
270                "zlib failed to initialize compressor (");
271             pos = png_safecat(msg, sizeof msg, pos, who);
272
273             switch (ret)
274             {
275                case Z_VERSION_ERROR:
276                   pos = png_safecat(msg, sizeof msg, pos, ") version error");
277                   break;
278
279                case Z_STREAM_ERROR:
280                   pos = png_safecat(msg, sizeof msg, pos, ") stream error");
281                   break;
282
283                case Z_MEM_ERROR:
284                   pos = png_safecat(msg, sizeof msg, pos, ") memory error");
285                   break;
286
287                default:
288                   pos = png_safecat(msg, sizeof msg, pos, ") unknown error");
289                   break;
290             }
291
292             png_error(png_ptr, msg);
293          }
294       }
295
296       /* Here on success, claim the zstream: */
297       png_ptr->zlib_state |= PNG_ZLIB_IN_USE;
298    }
299
300    else
301       png_error(png_ptr, "zstream already in use (internal error)");
302 }
303
304 /* The opposite: release the stream.  It is also reset, this API will warn on
305  * error but will not fail.
306  */
307 static void
308 png_zlib_release(png_structp png_ptr)
309 {
310    if (png_ptr->zlib_state & PNG_ZLIB_IN_USE)
311    {
312       int ret = deflateReset(&png_ptr->zstream);
313
314       png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE;
315
316       if (ret != Z_OK)
317       {
318          png_const_charp err;
319          PNG_WARNING_PARAMETERS(p)
320
321          switch (ret)
322          {
323             case Z_VERSION_ERROR:
324                err = "version";
325                break;
326
327             case Z_STREAM_ERROR:
328                err = "stream";
329                break;
330
331             case Z_MEM_ERROR:
332                err = "memory";
333                break;
334
335             default:
336                err = "unknown";
337                break;
338          }
339
340          png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret);
341          png_warning_parameter(p, 2, err);
342
343          if (png_ptr->zstream.msg)
344             err = png_ptr->zstream.msg;
345          else
346             err = "[no zlib message]";
347
348          png_warning_parameter(p, 3, err);
349
350          png_formatted_warning(png_ptr, p,
351             "zlib failed to reset compressor: @1(@2): @3");
352       }
353    }
354
355    else
356       png_warning(png_ptr, "zstream not in use (internal error)");
357 }
358
359 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
360 /* This pair of functions encapsulates the operation of (a) compressing a
361  * text string, and (b) issuing it later as a series of chunk data writes.
362  * The compression_state structure is shared context for these functions
363  * set up by the caller in order to make the whole mess thread-safe.
364  */
365
366 typedef struct
367 {
368    png_const_bytep input;   /* The uncompressed input data */
369    png_size_t input_len;    /* Its length */
370    int num_output_ptr;      /* Number of output pointers used */
371    int max_output_ptr;      /* Size of output_ptr */
372    png_bytep *output_ptr;   /* Array of pointers to output */
373 } compression_state;
374
375 /* Compress given text into storage in the png_ptr structure */
376 static int /* PRIVATE */
377 png_text_compress(png_structp png_ptr,
378     png_const_charp text, png_size_t text_len, int compression,
379     compression_state *comp)
380 {
381    int ret;
382
383    comp->num_output_ptr = 0;
384    comp->max_output_ptr = 0;
385    comp->output_ptr = NULL;
386    comp->input = NULL;
387    comp->input_len = text_len;
388
389    /* We may just want to pass the text right through */
390    if (compression == PNG_TEXT_COMPRESSION_NONE)
391    {
392       comp->input = (png_const_bytep)text;
393       return((int)text_len);
394    }
395
396    if (compression >= PNG_TEXT_COMPRESSION_LAST)
397    {
398       PNG_WARNING_PARAMETERS(p)
399
400       png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
401          compression);
402       png_formatted_warning(png_ptr, p, "Unknown compression type @1");
403    }
404
405    /* We can't write the chunk until we find out how much data we have,
406     * which means we need to run the compressor first and save the
407     * output.  This shouldn't be a problem, as the vast majority of
408     * comments should be reasonable, but we will set up an array of
409     * malloc'd pointers to be sure.
410     *
411     * If we knew the application was well behaved, we could simplify this
412     * greatly by assuming we can always malloc an output buffer large
413     * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
414     * and malloc this directly.  The only time this would be a bad idea is
415     * if we can't malloc more than 64K and we have 64K of random input
416     * data, or if the input string is incredibly large (although this
417     * wouldn't cause a failure, just a slowdown due to swapping).
418     */
419    png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT);
420
421    /* Set up the compression buffers */
422    /* TODO: the following cast hides a potential overflow problem. */
423    png_ptr->zstream.avail_in = (uInt)text_len;
424
425    /* NOTE: assume zlib doesn't overwrite the input */
426    png_ptr->zstream.next_in = (Bytef *)text;
427    png_ptr->zstream.avail_out = png_ptr->zbuf_size;
428    png_ptr->zstream.next_out = png_ptr->zbuf;
429
430    /* This is the same compression loop as in png_write_row() */
431    do
432    {
433       /* Compress the data */
434       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
435
436       if (ret != Z_OK)
437       {
438          /* Error */
439          if (png_ptr->zstream.msg != NULL)
440             png_error(png_ptr, png_ptr->zstream.msg);
441
442          else
443             png_error(png_ptr, "zlib error");
444       }
445
446       /* Check to see if we need more room */
447       if (!(png_ptr->zstream.avail_out))
448       {
449          /* Make sure the output array has room */
450          if (comp->num_output_ptr >= comp->max_output_ptr)
451          {
452             int old_max;
453
454             old_max = comp->max_output_ptr;
455             comp->max_output_ptr = comp->num_output_ptr + 4;
456             if (comp->output_ptr != NULL)
457             {
458                png_bytepp old_ptr;
459
460                old_ptr = comp->output_ptr;
461
462                comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
463                    (comp->max_output_ptr * png_sizeof(png_bytep)));
464
465                png_memcpy(comp->output_ptr, old_ptr, old_max
466                    * png_sizeof(png_bytep));
467
468                png_free(png_ptr, old_ptr);
469             }
470             else
471                comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
472                    (comp->max_output_ptr * png_sizeof(png_bytep)));
473          }
474
475          /* Save the data */
476          comp->output_ptr[comp->num_output_ptr] =
477              (png_bytep)png_malloc(png_ptr, png_ptr->zbuf_size);
478
479          png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
480              png_ptr->zbuf_size);
481
482          comp->num_output_ptr++;
483
484          /* and reset the buffer */
485          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
486          png_ptr->zstream.next_out = png_ptr->zbuf;
487       }
488    /* Continue until we don't have any more to compress */
489    } while (png_ptr->zstream.avail_in);
490
491    /* Finish the compression */
492    do
493    {
494       /* Tell zlib we are finished */
495       ret = deflate(&png_ptr->zstream, Z_FINISH);
496
497       if (ret == Z_OK)
498       {
499          /* Check to see if we need more room */
500          if (!(png_ptr->zstream.avail_out))
501          {
502             /* Check to make sure our output array has room */
503             if (comp->num_output_ptr >= comp->max_output_ptr)
504             {
505                int old_max;
506
507                old_max = comp->max_output_ptr;
508                comp->max_output_ptr = comp->num_output_ptr + 4;
509                if (comp->output_ptr != NULL)
510                {
511                   png_bytepp old_ptr;
512
513                   old_ptr = comp->output_ptr;
514
515                   /* This could be optimized to realloc() */
516                   comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
517                       (png_alloc_size_t)(comp->max_output_ptr *
518                       png_sizeof(png_charp)));
519
520                   png_memcpy(comp->output_ptr, old_ptr,
521                       old_max * png_sizeof(png_charp));
522
523                   png_free(png_ptr, old_ptr);
524                }
525
526                else
527                   comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
528                       (png_alloc_size_t)(comp->max_output_ptr *
529                       png_sizeof(png_charp)));
530             }
531
532             /* Save the data */
533             comp->output_ptr[comp->num_output_ptr] =
534                 (png_bytep)png_malloc(png_ptr,
535                 (png_alloc_size_t)png_ptr->zbuf_size);
536
537             png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
538                 png_ptr->zbuf_size);
539
540             comp->num_output_ptr++;
541
542             /* and reset the buffer pointers */
543             png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
544             png_ptr->zstream.next_out = png_ptr->zbuf;
545          }
546       }
547       else if (ret != Z_STREAM_END)
548       {
549          /* We got an error */
550          if (png_ptr->zstream.msg != NULL)
551             png_error(png_ptr, png_ptr->zstream.msg);
552
553          else
554             png_error(png_ptr, "zlib error");
555       }
556    } while (ret != Z_STREAM_END);
557
558    /* Text length is number of buffers plus last buffer */
559    text_len = png_ptr->zbuf_size * comp->num_output_ptr;
560
561    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
562       text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
563
564    return((int)text_len);
565 }
566
567 /* Ship the compressed text out via chunk writes */
568 static void /* PRIVATE */
569 png_write_compressed_data_out(png_structp png_ptr, compression_state *comp,
570    png_size_t data_len)
571 {
572    int i;
573
574    /* Handle the no-compression case */
575    if (comp->input)
576    {
577       png_write_chunk_data(png_ptr, comp->input, data_len);
578
579       return;
580    }
581
582 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
583    /* The zbuf_size test is because the code below doesn't work if zbuf_size is
584     * '1'; simply skip it to avoid memory overwrite.
585     */
586    if (data_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
587    {
588       unsigned int z_cmf;  /* zlib compression method and flags */
589
590       /* Optimize the CMF field in the zlib stream.  This hack of the zlib
591        * stream is compliant to the stream specification.
592        */
593
594       if (comp->num_output_ptr)
595         z_cmf = comp->output_ptr[0][0];
596       else
597         z_cmf = png_ptr->zbuf[0];
598
599       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
600       {
601          unsigned int z_cinfo;
602          unsigned int half_z_window_size;
603          png_size_t uncompressed_text_size = comp->input_len;
604
605          z_cinfo = z_cmf >> 4;
606          half_z_window_size = 1 << (z_cinfo + 7);
607
608          while (uncompressed_text_size <= half_z_window_size &&
609              half_z_window_size >= 256)
610          {
611             z_cinfo--;
612             half_z_window_size >>= 1;
613          }
614
615          z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
616
617          if (comp->num_output_ptr)
618          {
619
620            if (comp->output_ptr[0][0] != z_cmf)
621            {
622               int tmp;
623
624               comp->output_ptr[0][0] = (png_byte)z_cmf;
625               tmp = comp->output_ptr[0][1] & 0xe0;
626               tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
627               comp->output_ptr[0][1] = (png_byte)tmp;
628            }
629          }
630          else
631          {
632             int tmp;
633
634             png_ptr->zbuf[0] = (png_byte)z_cmf;
635             tmp = png_ptr->zbuf[1] & 0xe0;
636             tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
637             png_ptr->zbuf[1] = (png_byte)tmp;
638          }
639       }
640
641       else
642          png_error(png_ptr,
643              "Invalid zlib compression method or flags in non-IDAT chunk");
644    }
645 #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
646
647    /* Write saved output buffers, if any */
648    for (i = 0; i < comp->num_output_ptr; i++)
649    {
650       png_write_chunk_data(png_ptr, comp->output_ptr[i],
651           (png_size_t)png_ptr->zbuf_size);
652
653       png_free(png_ptr, comp->output_ptr[i]);
654    }
655
656    if (comp->max_output_ptr != 0)
657       png_free(png_ptr, comp->output_ptr);
658
659    /* Write anything left in zbuf */
660    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
661       png_write_chunk_data(png_ptr, png_ptr->zbuf,
662           (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
663
664    /* Reset zlib for another zTXt/iTXt or image data */
665    png_zlib_release(png_ptr);
666 }
667 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
668
669 /* Write the IHDR chunk, and update the png_struct with the necessary
670  * information.  Note that the rest of this code depends upon this
671  * information being correct.
672  */
673 void /* PRIVATE */
674 png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
675     int bit_depth, int color_type, int compression_type, int filter_type,
676     int interlace_type)
677 {
678    png_byte buf[13]; /* Buffer to store the IHDR info */
679
680    png_debug(1, "in png_write_IHDR");
681
682    /* Check that we have valid input data from the application info */
683    switch (color_type)
684    {
685       case PNG_COLOR_TYPE_GRAY:
686          switch (bit_depth)
687          {
688             case 1:
689             case 2:
690             case 4:
691             case 8:
692 #ifdef PNG_WRITE_16BIT_SUPPORTED
693             case 16:
694 #endif
695                png_ptr->channels = 1; break;
696
697             default:
698                png_error(png_ptr,
699                    "Invalid bit depth for grayscale image");
700          }
701          break;
702
703       case PNG_COLOR_TYPE_RGB:
704 #ifdef PNG_WRITE_16BIT_SUPPORTED
705          if (bit_depth != 8 && bit_depth != 16)
706 #else
707          if (bit_depth != 8)
708 #endif
709             png_error(png_ptr, "Invalid bit depth for RGB image");
710
711          png_ptr->channels = 3;
712          break;
713
714       case PNG_COLOR_TYPE_PALETTE:
715          switch (bit_depth)
716          {
717             case 1:
718             case 2:
719             case 4:
720             case 8:
721                png_ptr->channels = 1;
722                break;
723
724             default:
725                png_error(png_ptr, "Invalid bit depth for paletted image");
726          }
727          break;
728
729       case PNG_COLOR_TYPE_GRAY_ALPHA:
730          if (bit_depth != 8 && bit_depth != 16)
731             png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
732
733          png_ptr->channels = 2;
734          break;
735
736       case PNG_COLOR_TYPE_RGB_ALPHA:
737 #ifdef PNG_WRITE_16BIT_SUPPORTED
738          if (bit_depth != 8 && bit_depth != 16)
739 #else
740          if (bit_depth != 8)
741 #endif
742             png_error(png_ptr, "Invalid bit depth for RGBA image");
743
744          png_ptr->channels = 4;
745          break;
746
747       default:
748          png_error(png_ptr, "Invalid image color type specified");
749    }
750
751    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
752    {
753       png_warning(png_ptr, "Invalid compression type specified");
754       compression_type = PNG_COMPRESSION_TYPE_BASE;
755    }
756
757    /* Write filter_method 64 (intrapixel differencing) only if
758     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
759     * 2. Libpng did not write a PNG signature (this filter_method is only
760     *    used in PNG datastreams that are embedded in MNG datastreams) and
761     * 3. The application called png_permit_mng_features with a mask that
762     *    included PNG_FLAG_MNG_FILTER_64 and
763     * 4. The filter_method is 64 and
764     * 5. The color_type is RGB or RGBA
765     */
766    if (
767 #ifdef PNG_MNG_FEATURES_SUPPORTED
768        !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
769        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
770        (color_type == PNG_COLOR_TYPE_RGB ||
771         color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
772        (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
773 #endif
774        filter_type != PNG_FILTER_TYPE_BASE)
775    {
776       png_warning(png_ptr, "Invalid filter type specified");
777       filter_type = PNG_FILTER_TYPE_BASE;
778    }
779
780 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
781    if (interlace_type != PNG_INTERLACE_NONE &&
782        interlace_type != PNG_INTERLACE_ADAM7)
783    {
784       png_warning(png_ptr, "Invalid interlace type specified");
785       interlace_type = PNG_INTERLACE_ADAM7;
786    }
787 #else
788    interlace_type=PNG_INTERLACE_NONE;
789 #endif
790
791    /* Save the relevent information */
792    png_ptr->bit_depth = (png_byte)bit_depth;
793    png_ptr->color_type = (png_byte)color_type;
794    png_ptr->interlaced = (png_byte)interlace_type;
795 #ifdef PNG_MNG_FEATURES_SUPPORTED
796    png_ptr->filter_type = (png_byte)filter_type;
797 #endif
798    png_ptr->compression_type = (png_byte)compression_type;
799    png_ptr->width = width;
800    png_ptr->height = height;
801
802    png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
803    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
804    /* Set the usr info, so any transformations can modify it */
805    png_ptr->usr_width = png_ptr->width;
806    png_ptr->usr_bit_depth = png_ptr->bit_depth;
807    png_ptr->usr_channels = png_ptr->channels;
808
809    /* Pack the header information into the buffer */
810    png_save_uint_32(buf, width);
811    png_save_uint_32(buf + 4, height);
812    buf[8] = (png_byte)bit_depth;
813    buf[9] = (png_byte)color_type;
814    buf[10] = (png_byte)compression_type;
815    buf[11] = (png_byte)filter_type;
816    buf[12] = (png_byte)interlace_type;
817
818    /* Write the chunk */
819    png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
820
821    /* Initialize zlib with PNG info */
822    png_ptr->zstream.zalloc = png_zalloc;
823    png_ptr->zstream.zfree = png_zfree;
824    png_ptr->zstream.opaque = (voidpf)png_ptr;
825
826    if (!(png_ptr->do_filter))
827    {
828       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
829           png_ptr->bit_depth < 8)
830          png_ptr->do_filter = PNG_FILTER_NONE;
831
832       else
833          png_ptr->do_filter = PNG_ALL_FILTERS;
834    }
835
836    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
837    {
838       if (png_ptr->do_filter != PNG_FILTER_NONE)
839          png_ptr->zlib_strategy = Z_FILTERED;
840
841       else
842          png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
843    }
844
845    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
846       png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
847
848    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
849       png_ptr->zlib_mem_level = 8;
850
851    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
852       png_ptr->zlib_window_bits = 15;
853
854    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
855       png_ptr->zlib_method = 8;
856
857 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
858 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
859    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
860       png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
861
862    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
863       png_ptr->zlib_text_level = png_ptr->zlib_level;
864
865    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
866       png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
867
868    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
869       png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
870
871    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
872       png_ptr->zlib_text_method = png_ptr->zlib_method;
873 #else
874    png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
875    png_ptr->zlib_text_level = png_ptr->zlib_level;
876    png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
877    png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
878    png_ptr->zlib_text_method = png_ptr->zlib_method;
879 #endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
880 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
881
882    /* Record that the compressor has not yet been initialized. */
883    png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
884
885    png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
886 }
887
888 /* Write the palette.  We are careful not to trust png_color to be in the
889  * correct order for PNG, so people can redefine it to any convenient
890  * structure.
891  */
892 void /* PRIVATE */
893 png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
894     png_uint_32 num_pal)
895 {
896    png_uint_32 i;
897    png_const_colorp pal_ptr;
898    png_byte buf[3];
899
900    png_debug(1, "in png_write_PLTE");
901
902    if ((
903 #ifdef PNG_MNG_FEATURES_SUPPORTED
904        !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
905 #endif
906        num_pal == 0) || num_pal > 256)
907    {
908       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
909       {
910          png_error(png_ptr, "Invalid number of colors in palette");
911       }
912
913       else
914       {
915          png_warning(png_ptr, "Invalid number of colors in palette");
916          return;
917       }
918    }
919
920    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
921    {
922       png_warning(png_ptr,
923           "Ignoring request to write a PLTE chunk in grayscale PNG");
924
925       return;
926    }
927
928    png_ptr->num_palette = (png_uint_16)num_pal;
929    png_debug1(3, "num_palette = %d", png_ptr->num_palette);
930
931    png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
932 #ifdef PNG_POINTER_INDEXING_SUPPORTED
933
934    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
935    {
936       buf[0] = pal_ptr->red;
937       buf[1] = pal_ptr->green;
938       buf[2] = pal_ptr->blue;
939       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
940    }
941
942 #else
943    /* This is a little slower but some buggy compilers need to do this
944     * instead
945     */
946    pal_ptr=palette;
947
948    for (i = 0; i < num_pal; i++)
949    {
950       buf[0] = pal_ptr[i].red;
951       buf[1] = pal_ptr[i].green;
952       buf[2] = pal_ptr[i].blue;
953       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
954    }
955
956 #endif
957    png_write_chunk_end(png_ptr);
958    png_ptr->mode |= PNG_HAVE_PLTE;
959 }
960
961 /* Write an IDAT chunk */
962 void /* PRIVATE */
963 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
964 {
965    png_debug(1, "in png_write_IDAT");
966
967 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
968    if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
969        png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
970    {
971       /* Optimize the CMF field in the zlib stream.  This hack of the zlib
972        * stream is compliant to the stream specification.
973        */
974       unsigned int z_cmf = data[0];  /* zlib compression method and flags */
975
976       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
977       {
978          /* Avoid memory underflows and multiplication overflows.
979           *
980           * The conditions below are practically always satisfied;
981           * however, they still must be checked.
982           */
983          if (length >= 2 &&
984              png_ptr->height < 16384 && png_ptr->width < 16384)
985          {
986             /* Compute the maximum possible length of the datastream */
987
988             /* Number of pixels, plus for each row a filter byte
989              * and possibly a padding byte, so increase the maximum
990              * size to account for these.
991              */
992             unsigned int z_cinfo;
993             unsigned int half_z_window_size;
994             png_uint_32 uncompressed_idat_size = png_ptr->height *
995                 ((png_ptr->width *
996                 png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
997
998             /* If it's interlaced, each block of 8 rows is sent as up to
999              * 14 rows, i.e., 6 additional rows, each with a filter byte
1000              * and possibly a padding byte
1001              */
1002             if (png_ptr->interlaced)
1003                uncompressed_idat_size += ((png_ptr->height + 7)/8) *
1004                    (png_ptr->bit_depth < 8 ? 12 : 6);
1005
1006             z_cinfo = z_cmf >> 4;
1007             half_z_window_size = 1 << (z_cinfo + 7);
1008
1009             while (uncompressed_idat_size <= half_z_window_size &&
1010                 half_z_window_size >= 256)
1011             {
1012                z_cinfo--;
1013                half_z_window_size >>= 1;
1014             }
1015
1016             z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
1017
1018             if (data[0] != z_cmf)
1019             {
1020                int tmp;
1021                data[0] = (png_byte)z_cmf;
1022                tmp = data[1] & 0xe0;
1023                tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
1024                data[1] = (png_byte)tmp;
1025             }
1026          }
1027       }
1028
1029       else
1030          png_error(png_ptr,
1031              "Invalid zlib compression method or flags in IDAT");
1032    }
1033 #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
1034
1035    png_write_complete_chunk(png_ptr, png_IDAT, data, length);
1036    png_ptr->mode |= PNG_HAVE_IDAT;
1037
1038    /* Prior to 1.5.4 this code was replicated in every caller (except at the
1039     * end, where it isn't technically necessary).  Since this function has
1040     * flushed the data we can safely reset the zlib output buffer here.
1041     */
1042    png_ptr->zstream.next_out = png_ptr->zbuf;
1043    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1044 }
1045
1046 /* Write an IEND chunk */
1047 void /* PRIVATE */
1048 png_write_IEND(png_structp png_ptr)
1049 {
1050    png_debug(1, "in png_write_IEND");
1051
1052    png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
1053    png_ptr->mode |= PNG_HAVE_IEND;
1054 }
1055
1056 #ifdef PNG_WRITE_gAMA_SUPPORTED
1057 /* Write a gAMA chunk */
1058 void /* PRIVATE */
1059 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
1060 {
1061    png_byte buf[4];
1062
1063    png_debug(1, "in png_write_gAMA");
1064
1065    /* file_gamma is saved in 1/100,000ths */
1066    png_save_uint_32(buf, (png_uint_32)file_gamma);
1067    png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
1068 }
1069 #endif
1070
1071 #ifdef PNG_WRITE_sRGB_SUPPORTED
1072 /* Write a sRGB chunk */
1073 void /* PRIVATE */
1074 png_write_sRGB(png_structp png_ptr, int srgb_intent)
1075 {
1076    png_byte buf[1];
1077
1078    png_debug(1, "in png_write_sRGB");
1079
1080    if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1081       png_warning(png_ptr,
1082           "Invalid sRGB rendering intent specified");
1083
1084    buf[0]=(png_byte)srgb_intent;
1085    png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
1086 }
1087 #endif
1088
1089 #ifdef PNG_WRITE_iCCP_SUPPORTED
1090 /* Write an iCCP chunk */
1091 void /* PRIVATE */
1092 png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
1093     png_const_charp profile, int profile_len)
1094 {
1095    png_size_t name_len;
1096    png_charp new_name;
1097    compression_state comp;
1098    int embedded_profile_len = 0;
1099
1100    png_debug(1, "in png_write_iCCP");
1101
1102    comp.num_output_ptr = 0;
1103    comp.max_output_ptr = 0;
1104    comp.output_ptr = NULL;
1105    comp.input = NULL;
1106    comp.input_len = 0;
1107
1108    if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
1109       return;
1110
1111    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
1112       png_warning(png_ptr, "Unknown compression type in iCCP chunk");
1113
1114    if (profile == NULL)
1115       profile_len = 0;
1116
1117    if (profile_len > 3)
1118       embedded_profile_len =
1119           ((*( (png_const_bytep)profile    ))<<24) |
1120           ((*( (png_const_bytep)profile + 1))<<16) |
1121           ((*( (png_const_bytep)profile + 2))<< 8) |
1122           ((*( (png_const_bytep)profile + 3))    );
1123
1124    if (embedded_profile_len < 0)
1125    {
1126       png_warning(png_ptr,
1127           "Embedded profile length in iCCP chunk is negative");
1128
1129       png_free(png_ptr, new_name);
1130       return;
1131    }
1132
1133    if (profile_len < embedded_profile_len)
1134    {
1135       png_warning(png_ptr,
1136           "Embedded profile length too large in iCCP chunk");
1137
1138       png_free(png_ptr, new_name);
1139       return;
1140    }
1141
1142    if (profile_len > embedded_profile_len)
1143    {
1144       png_warning(png_ptr,
1145           "Truncating profile to actual length in iCCP chunk");
1146
1147       profile_len = embedded_profile_len;
1148    }
1149
1150    if (profile_len)
1151       profile_len = png_text_compress(png_ptr, profile,
1152           (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
1153
1154    /* Make sure we include the NULL after the name and the compression type */
1155    png_write_chunk_header(png_ptr, png_iCCP,
1156        (png_uint_32)(name_len + profile_len + 2));
1157
1158    new_name[name_len + 1] = 0x00;
1159
1160    png_write_chunk_data(png_ptr, (png_bytep)new_name,
1161        (png_size_t)(name_len + 2));
1162
1163    if (profile_len)
1164    {
1165       png_write_compressed_data_out(png_ptr, &comp, profile_len);
1166    }
1167
1168    png_write_chunk_end(png_ptr);
1169    png_free(png_ptr, new_name);
1170 }
1171 #endif
1172
1173 #ifdef PNG_WRITE_sPLT_SUPPORTED
1174 /* Write a sPLT chunk */
1175 void /* PRIVATE */
1176 png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
1177 {
1178    png_size_t name_len;
1179    png_charp new_name;
1180    png_byte entrybuf[10];
1181    png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
1182    png_size_t palette_size = entry_size * spalette->nentries;
1183    png_sPLT_entryp ep;
1184 #ifndef PNG_POINTER_INDEXING_SUPPORTED
1185    int i;
1186 #endif
1187
1188    png_debug(1, "in png_write_sPLT");
1189
1190    if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
1191       return;
1192
1193    /* Make sure we include the NULL after the name */
1194    png_write_chunk_header(png_ptr, png_sPLT,
1195        (png_uint_32)(name_len + 2 + palette_size));
1196
1197    png_write_chunk_data(png_ptr, (png_bytep)new_name,
1198        (png_size_t)(name_len + 1));
1199
1200    png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
1201
1202    /* Loop through each palette entry, writing appropriately */
1203 #ifdef PNG_POINTER_INDEXING_SUPPORTED
1204    for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1205    {
1206       if (spalette->depth == 8)
1207       {
1208          entrybuf[0] = (png_byte)ep->red;
1209          entrybuf[1] = (png_byte)ep->green;
1210          entrybuf[2] = (png_byte)ep->blue;
1211          entrybuf[3] = (png_byte)ep->alpha;
1212          png_save_uint_16(entrybuf + 4, ep->frequency);
1213       }
1214
1215       else
1216       {
1217          png_save_uint_16(entrybuf + 0, ep->red);
1218          png_save_uint_16(entrybuf + 2, ep->green);
1219          png_save_uint_16(entrybuf + 4, ep->blue);
1220          png_save_uint_16(entrybuf + 6, ep->alpha);
1221          png_save_uint_16(entrybuf + 8, ep->frequency);
1222       }
1223
1224       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
1225    }
1226 #else
1227    ep=spalette->entries;
1228    for (i = 0; i>spalette->nentries; i++)
1229    {
1230       if (spalette->depth == 8)
1231       {
1232          entrybuf[0] = (png_byte)ep[i].red;
1233          entrybuf[1] = (png_byte)ep[i].green;
1234          entrybuf[2] = (png_byte)ep[i].blue;
1235          entrybuf[3] = (png_byte)ep[i].alpha;
1236          png_save_uint_16(entrybuf + 4, ep[i].frequency);
1237       }
1238
1239       else
1240       {
1241          png_save_uint_16(entrybuf + 0, ep[i].red);
1242          png_save_uint_16(entrybuf + 2, ep[i].green);
1243          png_save_uint_16(entrybuf + 4, ep[i].blue);
1244          png_save_uint_16(entrybuf + 6, ep[i].alpha);
1245          png_save_uint_16(entrybuf + 8, ep[i].frequency);
1246       }
1247
1248       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
1249    }
1250 #endif
1251
1252    png_write_chunk_end(png_ptr);
1253    png_free(png_ptr, new_name);
1254 }
1255 #endif
1256
1257 #ifdef PNG_WRITE_sBIT_SUPPORTED
1258 /* Write the sBIT chunk */
1259 void /* PRIVATE */
1260 png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
1261 {
1262    png_byte buf[4];
1263    png_size_t size;
1264
1265    png_debug(1, "in png_write_sBIT");
1266
1267    /* Make sure we don't depend upon the order of PNG_COLOR_8 */
1268    if (color_type & PNG_COLOR_MASK_COLOR)
1269    {
1270       png_byte maxbits;
1271
1272       maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
1273           png_ptr->usr_bit_depth);
1274
1275       if (sbit->red == 0 || sbit->red > maxbits ||
1276           sbit->green == 0 || sbit->green > maxbits ||
1277           sbit->blue == 0 || sbit->blue > maxbits)
1278       {
1279          png_warning(png_ptr, "Invalid sBIT depth specified");
1280          return;
1281       }
1282
1283       buf[0] = sbit->red;
1284       buf[1] = sbit->green;
1285       buf[2] = sbit->blue;
1286       size = 3;
1287    }
1288
1289    else
1290    {
1291       if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
1292       {
1293          png_warning(png_ptr, "Invalid sBIT depth specified");
1294          return;
1295       }
1296
1297       buf[0] = sbit->gray;
1298       size = 1;
1299    }
1300
1301    if (color_type & PNG_COLOR_MASK_ALPHA)
1302    {
1303       if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
1304       {
1305          png_warning(png_ptr, "Invalid sBIT depth specified");
1306          return;
1307       }
1308
1309       buf[size++] = sbit->alpha;
1310    }
1311
1312    png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
1313 }
1314 #endif
1315
1316 #ifdef PNG_WRITE_cHRM_SUPPORTED
1317 /* Write the cHRM chunk */
1318 void /* PRIVATE */
1319 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
1320     png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
1321     png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
1322     png_fixed_point blue_y)
1323 {
1324    png_byte buf[32];
1325
1326    png_debug(1, "in png_write_cHRM");
1327
1328    /* Each value is saved in 1/100,000ths */
1329 #ifdef PNG_CHECK_cHRM_SUPPORTED
1330    if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
1331        green_x, green_y, blue_x, blue_y))
1332 #endif
1333    {
1334       png_save_uint_32(buf, (png_uint_32)white_x);
1335       png_save_uint_32(buf + 4, (png_uint_32)white_y);
1336
1337       png_save_uint_32(buf + 8, (png_uint_32)red_x);
1338       png_save_uint_32(buf + 12, (png_uint_32)red_y);
1339
1340       png_save_uint_32(buf + 16, (png_uint_32)green_x);
1341       png_save_uint_32(buf + 20, (png_uint_32)green_y);
1342
1343       png_save_uint_32(buf + 24, (png_uint_32)blue_x);
1344       png_save_uint_32(buf + 28, (png_uint_32)blue_y);
1345
1346       png_write_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
1347    }
1348 }
1349 #endif
1350
1351 #ifdef PNG_WRITE_tRNS_SUPPORTED
1352 /* Write the tRNS chunk */
1353 void /* PRIVATE */
1354 png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
1355     png_const_color_16p tran, int num_trans, int color_type)
1356 {
1357    png_byte buf[6];
1358
1359    png_debug(1, "in png_write_tRNS");
1360
1361    if (color_type == PNG_COLOR_TYPE_PALETTE)
1362    {
1363       if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
1364       {
1365          png_warning(png_ptr, "Invalid number of transparent colors specified");
1366          return;
1367       }
1368
1369       /* Write the chunk out as it is */
1370       png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
1371          (png_size_t)num_trans);
1372    }
1373
1374    else if (color_type == PNG_COLOR_TYPE_GRAY)
1375    {
1376       /* One 16 bit value */
1377       if (tran->gray >= (1 << png_ptr->bit_depth))
1378       {
1379          png_warning(png_ptr,
1380              "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1381
1382          return;
1383       }
1384
1385       png_save_uint_16(buf, tran->gray);
1386       png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
1387    }
1388
1389    else if (color_type == PNG_COLOR_TYPE_RGB)
1390    {
1391       /* Three 16 bit values */
1392       png_save_uint_16(buf, tran->red);
1393       png_save_uint_16(buf + 2, tran->green);
1394       png_save_uint_16(buf + 4, tran->blue);
1395 #ifdef PNG_WRITE_16BIT_SUPPORTED
1396       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1397 #else
1398       if (buf[0] | buf[2] | buf[4])
1399 #endif
1400       {
1401          png_warning(png_ptr,
1402            "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1403          return;
1404       }
1405
1406       png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
1407    }
1408
1409    else
1410    {
1411       png_warning(png_ptr, "Can't write tRNS with an alpha channel");
1412    }
1413 }
1414 #endif
1415
1416 #ifdef PNG_WRITE_bKGD_SUPPORTED
1417 /* Write the background chunk */
1418 void /* PRIVATE */
1419 png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
1420 {
1421    png_byte buf[6];
1422
1423    png_debug(1, "in png_write_bKGD");
1424
1425    if (color_type == PNG_COLOR_TYPE_PALETTE)
1426    {
1427       if (
1428 #ifdef PNG_MNG_FEATURES_SUPPORTED
1429           (png_ptr->num_palette ||
1430           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
1431 #endif
1432          back->index >= png_ptr->num_palette)
1433       {
1434          png_warning(png_ptr, "Invalid background palette index");
1435          return;
1436       }
1437
1438       buf[0] = back->index;
1439       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
1440    }
1441
1442    else if (color_type & PNG_COLOR_MASK_COLOR)
1443    {
1444       png_save_uint_16(buf, back->red);
1445       png_save_uint_16(buf + 2, back->green);
1446       png_save_uint_16(buf + 4, back->blue);
1447 #ifdef PNG_WRITE_16BIT_SUPPORTED
1448       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1449 #else
1450       if (buf[0] | buf[2] | buf[4])
1451 #endif
1452       {
1453          png_warning(png_ptr,
1454              "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
1455
1456          return;
1457       }
1458
1459       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
1460    }
1461
1462    else
1463    {
1464       if (back->gray >= (1 << png_ptr->bit_depth))
1465       {
1466          png_warning(png_ptr,
1467              "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1468
1469          return;
1470       }
1471
1472       png_save_uint_16(buf, back->gray);
1473       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
1474    }
1475 }
1476 #endif
1477
1478 #ifdef PNG_WRITE_hIST_SUPPORTED
1479 /* Write the histogram */
1480 void /* PRIVATE */
1481 png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
1482 {
1483    int i;
1484    png_byte buf[3];
1485
1486    png_debug(1, "in png_write_hIST");
1487
1488    if (num_hist > (int)png_ptr->num_palette)
1489    {
1490       png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1491           png_ptr->num_palette);
1492
1493       png_warning(png_ptr, "Invalid number of histogram entries specified");
1494       return;
1495    }
1496
1497    png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1498
1499    for (i = 0; i < num_hist; i++)
1500    {
1501       png_save_uint_16(buf, hist[i]);
1502       png_write_chunk_data(png_ptr, buf, (png_size_t)2);
1503    }
1504
1505    png_write_chunk_end(png_ptr);
1506 }
1507 #endif
1508
1509 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
1510     defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
1511 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
1512  * and if invalid, correct the keyword rather than discarding the entire
1513  * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
1514  * length, forbids leading or trailing whitespace, multiple internal spaces,
1515  * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
1516  *
1517  * The new_key is allocated to hold the corrected keyword and must be freed
1518  * by the calling routine.  This avoids problems with trying to write to
1519  * static keywords without having to have duplicate copies of the strings.
1520  */
1521 png_size_t /* PRIVATE */
1522 png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
1523 {
1524    png_size_t key_len;
1525    png_const_charp ikp;
1526    png_charp kp, dp;
1527    int kflag;
1528    int kwarn=0;
1529
1530    png_debug(1, "in png_check_keyword");
1531
1532    *new_key = NULL;
1533
1534    if (key == NULL || (key_len = png_strlen(key)) == 0)
1535    {
1536       png_warning(png_ptr, "zero length keyword");
1537       return ((png_size_t)0);
1538    }
1539
1540    png_debug1(2, "Keyword to be checked is '%s'", key);
1541
1542    *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
1543
1544    if (*new_key == NULL)
1545    {
1546       png_warning(png_ptr, "Out of memory while procesing keyword");
1547       return ((png_size_t)0);
1548    }
1549
1550    /* Replace non-printing characters with a blank and print a warning */
1551    for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
1552    {
1553       if ((png_byte)*ikp < 0x20 ||
1554          ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
1555       {
1556          PNG_WARNING_PARAMETERS(p)
1557
1558          png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
1559             (png_byte)*ikp);
1560          png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
1561          *dp = ' ';
1562       }
1563
1564       else
1565       {
1566          *dp = *ikp;
1567       }
1568    }
1569    *dp = '\0';
1570
1571    /* Remove any trailing white space. */
1572    kp = *new_key + key_len - 1;
1573    if (*kp == ' ')
1574    {
1575       png_warning(png_ptr, "trailing spaces removed from keyword");
1576
1577       while (*kp == ' ')
1578       {
1579          *(kp--) = '\0';
1580          key_len--;
1581       }
1582    }
1583
1584    /* Remove any leading white space. */
1585    kp = *new_key;
1586    if (*kp == ' ')
1587    {
1588       png_warning(png_ptr, "leading spaces removed from keyword");
1589
1590       while (*kp == ' ')
1591       {
1592          kp++;
1593          key_len--;
1594       }
1595    }
1596
1597    png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
1598
1599    /* Remove multiple internal spaces. */
1600    for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
1601    {
1602       if (*kp == ' ' && kflag == 0)
1603       {
1604          *(dp++) = *kp;
1605          kflag = 1;
1606       }
1607
1608       else if (*kp == ' ')
1609       {
1610          key_len--;
1611          kwarn = 1;
1612       }
1613
1614       else
1615       {
1616          *(dp++) = *kp;
1617          kflag = 0;
1618       }
1619    }
1620    *dp = '\0';
1621    if (kwarn)
1622       png_warning(png_ptr, "extra interior spaces removed from keyword");
1623
1624    if (key_len == 0)
1625    {
1626       png_free(png_ptr, *new_key);
1627       png_warning(png_ptr, "Zero length keyword");
1628    }
1629
1630    if (key_len > 79)
1631    {
1632       png_warning(png_ptr, "keyword length must be 1 - 79 characters");
1633       (*new_key)[79] = '\0';
1634       key_len = 79;
1635    }
1636
1637    return (key_len);
1638 }
1639 #endif
1640
1641 #ifdef PNG_WRITE_tEXt_SUPPORTED
1642 /* Write a tEXt chunk */
1643 void /* PRIVATE */
1644 png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
1645     png_size_t text_len)
1646 {
1647    png_size_t key_len;
1648    png_charp new_key;
1649
1650    png_debug(1, "in png_write_tEXt");
1651
1652    if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1653       return;
1654
1655    if (text == NULL || *text == '\0')
1656       text_len = 0;
1657
1658    else
1659       text_len = png_strlen(text);
1660
1661    /* Make sure we include the 0 after the key */
1662    png_write_chunk_header(png_ptr, png_tEXt,
1663        (png_uint_32)(key_len + text_len + 1));
1664    /*
1665     * We leave it to the application to meet PNG-1.0 requirements on the
1666     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
1667     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
1668     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1669     */
1670    png_write_chunk_data(png_ptr, (png_bytep)new_key,
1671        (png_size_t)(key_len + 1));
1672
1673    if (text_len)
1674       png_write_chunk_data(png_ptr, (png_const_bytep)text,
1675           (png_size_t)text_len);
1676
1677    png_write_chunk_end(png_ptr);
1678    png_free(png_ptr, new_key);
1679 }
1680 #endif
1681
1682 #ifdef PNG_WRITE_zTXt_SUPPORTED
1683 /* Write a compressed text chunk */
1684 void /* PRIVATE */
1685 png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
1686     png_size_t text_len, int compression)
1687 {
1688    png_size_t key_len;
1689    png_byte buf;
1690    png_charp new_key;
1691    compression_state comp;
1692
1693    png_debug(1, "in png_write_zTXt");
1694
1695    comp.num_output_ptr = 0;
1696    comp.max_output_ptr = 0;
1697    comp.output_ptr = NULL;
1698    comp.input = NULL;
1699    comp.input_len = 0;
1700
1701    if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
1702    {
1703       png_free(png_ptr, new_key);
1704       return;
1705    }
1706
1707    if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
1708    {
1709       png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
1710       png_free(png_ptr, new_key);
1711       return;
1712    }
1713
1714    text_len = png_strlen(text);
1715
1716    /* Compute the compressed data; do it now for the length */
1717    text_len = png_text_compress(png_ptr, text, text_len, compression,
1718        &comp);
1719
1720    /* Write start of chunk */
1721    png_write_chunk_header(png_ptr, png_zTXt,
1722        (png_uint_32)(key_len+text_len + 2));
1723
1724    /* Write key */
1725    png_write_chunk_data(png_ptr, (png_bytep)new_key,
1726        (png_size_t)(key_len + 1));
1727
1728    png_free(png_ptr, new_key);
1729
1730    buf = (png_byte)compression;
1731
1732    /* Write compression */
1733    png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
1734
1735    /* Write the compressed data */
1736    png_write_compressed_data_out(png_ptr, &comp, text_len);
1737
1738    /* Close the chunk */
1739    png_write_chunk_end(png_ptr);
1740 }
1741 #endif
1742
1743 #ifdef PNG_WRITE_iTXt_SUPPORTED
1744 /* Write an iTXt chunk */
1745 void /* PRIVATE */
1746 png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
1747     png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1748 {
1749    png_size_t lang_len, key_len, lang_key_len, text_len;
1750    png_charp new_lang;
1751    png_charp new_key = NULL;
1752    png_byte cbuf[2];
1753    compression_state comp;
1754
1755    png_debug(1, "in png_write_iTXt");
1756
1757    comp.num_output_ptr = 0;
1758    comp.max_output_ptr = 0;
1759    comp.output_ptr = NULL;
1760    comp.input = NULL;
1761
1762    if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
1763       return;
1764
1765    if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
1766    {
1767       png_warning(png_ptr, "Empty language field in iTXt chunk");
1768       new_lang = NULL;
1769       lang_len = 0;
1770    }
1771
1772    if (lang_key == NULL)
1773       lang_key_len = 0;
1774
1775    else
1776       lang_key_len = png_strlen(lang_key);
1777
1778    if (text == NULL)
1779       text_len = 0;
1780
1781    else
1782       text_len = png_strlen(text);
1783
1784    /* Compute the compressed data; do it now for the length */
1785    text_len = png_text_compress(png_ptr, text, text_len, compression - 2,
1786        &comp);
1787
1788
1789    /* Make sure we include the compression flag, the compression byte,
1790     * and the NULs after the key, lang, and lang_key parts
1791     */
1792
1793    png_write_chunk_header(png_ptr, png_iTXt, (png_uint_32)(
1794         5 /* comp byte, comp flag, terminators for key, lang and lang_key */
1795         + key_len
1796         + lang_len
1797         + lang_key_len
1798         + text_len));
1799
1800    /* We leave it to the application to meet PNG-1.0 requirements on the
1801     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
1802     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
1803     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1804     */
1805    png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
1806
1807    /* Set the compression flag */
1808    if (compression == PNG_ITXT_COMPRESSION_NONE ||
1809        compression == PNG_TEXT_COMPRESSION_NONE)
1810       cbuf[0] = 0;
1811
1812    else /* compression == PNG_ITXT_COMPRESSION_zTXt */
1813       cbuf[0] = 1;
1814
1815    /* Set the compression method */
1816    cbuf[1] = 0;
1817
1818    png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
1819
1820    cbuf[0] = 0;
1821    png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
1822        (png_size_t)(lang_len + 1));
1823
1824    png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
1825        (png_size_t)(lang_key_len + 1));
1826
1827    png_write_compressed_data_out(png_ptr, &comp, text_len);
1828
1829    png_write_chunk_end(png_ptr);
1830
1831    png_free(png_ptr, new_key);
1832    png_free(png_ptr, new_lang);
1833 }
1834 #endif
1835
1836 #ifdef PNG_WRITE_oFFs_SUPPORTED
1837 /* Write the oFFs chunk */
1838 void /* PRIVATE */
1839 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1840     int unit_type)
1841 {
1842    png_byte buf[9];
1843
1844    png_debug(1, "in png_write_oFFs");
1845
1846    if (unit_type >= PNG_OFFSET_LAST)
1847       png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
1848
1849    png_save_int_32(buf, x_offset);
1850    png_save_int_32(buf + 4, y_offset);
1851    buf[8] = (png_byte)unit_type;
1852
1853    png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
1854 }
1855 #endif
1856 #ifdef PNG_WRITE_pCAL_SUPPORTED
1857 /* Write the pCAL chunk (described in the PNG extensions document) */
1858 void /* PRIVATE */
1859 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
1860     png_int_32 X1, int type, int nparams, png_const_charp units,
1861     png_charpp params)
1862 {
1863    png_size_t purpose_len, units_len, total_len;
1864    png_size_tp params_len;
1865    png_byte buf[10];
1866    png_charp new_purpose;
1867    int i;
1868
1869    png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1870
1871    if (type >= PNG_EQUATION_LAST)
1872       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1873
1874    purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
1875    png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
1876    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
1877    png_debug1(3, "pCAL units length = %d", (int)units_len);
1878    total_len = purpose_len + units_len + 10;
1879
1880    params_len = (png_size_tp)png_malloc(png_ptr,
1881        (png_alloc_size_t)(nparams * png_sizeof(png_size_t)));
1882
1883    /* Find the length of each parameter, making sure we don't count the
1884     * null terminator for the last parameter.
1885     */
1886    for (i = 0; i < nparams; i++)
1887    {
1888       params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1889       png_debug2(3, "pCAL parameter %d length = %lu", i,
1890           (unsigned long)params_len[i]);
1891       total_len += params_len[i];
1892    }
1893
1894    png_debug1(3, "pCAL total length = %d", (int)total_len);
1895    png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
1896    png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len);
1897    png_save_int_32(buf, X0);
1898    png_save_int_32(buf + 4, X1);
1899    buf[8] = (png_byte)type;
1900    buf[9] = (png_byte)nparams;
1901    png_write_chunk_data(png_ptr, buf, (png_size_t)10);
1902    png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
1903
1904    png_free(png_ptr, new_purpose);
1905
1906    for (i = 0; i < nparams; i++)
1907    {
1908       png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
1909    }
1910
1911    png_free(png_ptr, params_len);
1912    png_write_chunk_end(png_ptr);
1913 }
1914 #endif
1915
1916 #ifdef PNG_WRITE_sCAL_SUPPORTED
1917 /* Write the sCAL chunk */
1918 void /* PRIVATE */
1919 png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
1920     png_const_charp height)
1921 {
1922    png_byte buf[64];
1923    png_size_t wlen, hlen, total_len;
1924
1925    png_debug(1, "in png_write_sCAL_s");
1926
1927    wlen = png_strlen(width);
1928    hlen = png_strlen(height);
1929    total_len = wlen + hlen + 2;
1930
1931    if (total_len > 64)
1932    {
1933       png_warning(png_ptr, "Can't write sCAL (buffer too small)");
1934       return;
1935    }
1936
1937    buf[0] = (png_byte)unit;
1938    png_memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
1939    png_memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
1940
1941    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1942    png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1943 }
1944 #endif
1945
1946 #ifdef PNG_WRITE_pHYs_SUPPORTED
1947 /* Write the pHYs chunk */
1948 void /* PRIVATE */
1949 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1950     png_uint_32 y_pixels_per_unit,
1951     int unit_type)
1952 {
1953    png_byte buf[9];
1954
1955    png_debug(1, "in png_write_pHYs");
1956
1957    if (unit_type >= PNG_RESOLUTION_LAST)
1958       png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
1959
1960    png_save_uint_32(buf, x_pixels_per_unit);
1961    png_save_uint_32(buf + 4, y_pixels_per_unit);
1962    buf[8] = (png_byte)unit_type;
1963
1964    png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
1965 }
1966 #endif
1967
1968 #ifdef PNG_WRITE_tIME_SUPPORTED
1969 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
1970  * or png_convert_from_time_t(), or fill in the structure yourself.
1971  */
1972 void /* PRIVATE */
1973 png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
1974 {
1975    png_byte buf[7];
1976
1977    png_debug(1, "in png_write_tIME");
1978
1979    if (mod_time->month  > 12 || mod_time->month  < 1 ||
1980        mod_time->day    > 31 || mod_time->day    < 1 ||
1981        mod_time->hour   > 23 || mod_time->second > 60)
1982    {
1983       png_warning(png_ptr, "Invalid time specified for tIME chunk");
1984       return;
1985    }
1986
1987    png_save_uint_16(buf, mod_time->year);
1988    buf[2] = mod_time->month;
1989    buf[3] = mod_time->day;
1990    buf[4] = mod_time->hour;
1991    buf[5] = mod_time->minute;
1992    buf[6] = mod_time->second;
1993
1994    png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
1995 }
1996 #endif
1997
1998 /* Initializes the row writing capability of libpng */
1999 void /* PRIVATE */
2000 png_write_start_row(png_structp png_ptr)
2001 {
2002 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2003    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2004
2005    /* Start of interlace block */
2006    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2007
2008    /* Offset to next interlace block */
2009    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2010
2011    /* Start of interlace block in the y direction */
2012    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2013
2014    /* Offset to next interlace block in the y direction */
2015    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2016 #endif
2017
2018    png_alloc_size_t buf_size;
2019    int usr_pixel_depth;
2020
2021    png_debug(1, "in png_write_start_row");
2022
2023    usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
2024    buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
2025
2026    /* 1.5.6: added to allow checking in the row write code. */
2027    png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
2028    png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
2029
2030    /* Set up row buffer */
2031    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
2032
2033    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
2034
2035 #ifdef PNG_WRITE_FILTER_SUPPORTED
2036    /* Set up filtering buffer, if using this filter */
2037    if (png_ptr->do_filter & PNG_FILTER_SUB)
2038    {
2039       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
2040
2041       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
2042    }
2043
2044    /* We only need to keep the previous row if we are using one of these. */
2045    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
2046    {
2047       /* Set up previous row buffer */
2048       png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
2049
2050       if (png_ptr->do_filter & PNG_FILTER_UP)
2051       {
2052          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
2053             png_ptr->rowbytes + 1);
2054
2055          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
2056       }
2057
2058       if (png_ptr->do_filter & PNG_FILTER_AVG)
2059       {
2060          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
2061              png_ptr->rowbytes + 1);
2062
2063          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
2064       }
2065
2066       if (png_ptr->do_filter & PNG_FILTER_PAETH)
2067       {
2068          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
2069              png_ptr->rowbytes + 1);
2070
2071          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
2072       }
2073    }
2074 #endif /* PNG_WRITE_FILTER_SUPPORTED */
2075
2076 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2077    /* If interlaced, we need to set up width and height of pass */
2078    if (png_ptr->interlaced)
2079    {
2080       if (!(png_ptr->transformations & PNG_INTERLACE))
2081       {
2082          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2083              png_pass_ystart[0]) / png_pass_yinc[0];
2084
2085          png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2086              png_pass_start[0]) / png_pass_inc[0];
2087       }
2088
2089       else
2090       {
2091          png_ptr->num_rows = png_ptr->height;
2092          png_ptr->usr_width = png_ptr->width;
2093       }
2094    }
2095
2096    else
2097 #endif
2098    {
2099       png_ptr->num_rows = png_ptr->height;
2100       png_ptr->usr_width = png_ptr->width;
2101    }
2102
2103    png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT);
2104    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2105    png_ptr->zstream.next_out = png_ptr->zbuf;
2106 }
2107
2108 /* Internal use only.  Called when finished processing a row of data. */
2109 void /* PRIVATE */
2110 png_write_finish_row(png_structp png_ptr)
2111 {
2112 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2113    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2114
2115    /* Start of interlace block */
2116    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2117
2118    /* Offset to next interlace block */
2119    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2120
2121    /* Start of interlace block in the y direction */
2122    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2123
2124    /* Offset to next interlace block in the y direction */
2125    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2126 #endif
2127
2128    int ret;
2129
2130    png_debug(1, "in png_write_finish_row");
2131
2132    /* Next row */
2133    png_ptr->row_number++;
2134
2135    /* See if we are done */
2136    if (png_ptr->row_number < png_ptr->num_rows)
2137       return;
2138
2139 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2140    /* If interlaced, go to next pass */
2141    if (png_ptr->interlaced)
2142    {
2143       png_ptr->row_number = 0;
2144       if (png_ptr->transformations & PNG_INTERLACE)
2145       {
2146          png_ptr->pass++;
2147       }
2148
2149       else
2150       {
2151          /* Loop until we find a non-zero width or height pass */
2152          do
2153          {
2154             png_ptr->pass++;
2155
2156             if (png_ptr->pass >= 7)
2157                break;
2158
2159             png_ptr->usr_width = (png_ptr->width +
2160                 png_pass_inc[png_ptr->pass] - 1 -
2161                 png_pass_start[png_ptr->pass]) /
2162                 png_pass_inc[png_ptr->pass];
2163
2164             png_ptr->num_rows = (png_ptr->height +
2165                 png_pass_yinc[png_ptr->pass] - 1 -
2166                 png_pass_ystart[png_ptr->pass]) /
2167                 png_pass_yinc[png_ptr->pass];
2168
2169             if (png_ptr->transformations & PNG_INTERLACE)
2170                break;
2171
2172          } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
2173
2174       }
2175
2176       /* Reset the row above the image for the next pass */
2177       if (png_ptr->pass < 7)
2178       {
2179          if (png_ptr->prev_row != NULL)
2180             png_memset(png_ptr->prev_row, 0,
2181                 (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
2182                 png_ptr->usr_bit_depth, png_ptr->width)) + 1);
2183
2184          return;
2185       }
2186    }
2187 #endif
2188
2189    /* If we get here, we've just written the last row, so we need
2190       to flush the compressor */
2191    do
2192    {
2193       /* Tell the compressor we are done */
2194       ret = deflate(&png_ptr->zstream, Z_FINISH);
2195
2196       /* Check for an error */
2197       if (ret == Z_OK)
2198       {
2199          /* Check to see if we need more room */
2200          if (!(png_ptr->zstream.avail_out))
2201          {
2202             png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
2203             png_ptr->zstream.next_out = png_ptr->zbuf;
2204             png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2205          }
2206       }
2207
2208       else if (ret != Z_STREAM_END)
2209       {
2210          if (png_ptr->zstream.msg != NULL)
2211             png_error(png_ptr, png_ptr->zstream.msg);
2212
2213          else
2214             png_error(png_ptr, "zlib error");
2215       }
2216    } while (ret != Z_STREAM_END);
2217
2218    /* Write any extra space */
2219    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
2220    {
2221       png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
2222           png_ptr->zstream.avail_out);
2223    }
2224
2225    png_zlib_release(png_ptr);
2226    png_ptr->zstream.data_type = Z_BINARY;
2227 }
2228
2229 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2230 /* Pick out the correct pixels for the interlace pass.
2231  * The basic idea here is to go through the row with a source
2232  * pointer and a destination pointer (sp and dp), and copy the
2233  * correct pixels for the pass.  As the row gets compacted,
2234  * sp will always be >= dp, so we should never overwrite anything.
2235  * See the default: case for the easiest code to understand.
2236  */
2237 void /* PRIVATE */
2238 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
2239 {
2240    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2241
2242    /* Start of interlace block */
2243    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2244
2245    /* Offset to next interlace block */
2246    static PNG_CONST png_byte  png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2247
2248    png_debug(1, "in png_do_write_interlace");
2249
2250    /* We don't have to do anything on the last pass (6) */
2251    if (pass < 6)
2252    {
2253       /* Each pixel depth is handled separately */
2254       switch (row_info->pixel_depth)
2255       {
2256          case 1:
2257          {
2258             png_bytep sp;
2259             png_bytep dp;
2260             int shift;
2261             int d;
2262             int value;
2263             png_uint_32 i;
2264             png_uint_32 row_width = row_info->width;
2265
2266             dp = row;
2267             d = 0;
2268             shift = 7;
2269
2270             for (i = png_pass_start[pass]; i < row_width;
2271                i += png_pass_inc[pass])
2272             {
2273                sp = row + (png_size_t)(i >> 3);
2274                value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
2275                d |= (value << shift);
2276
2277                if (shift == 0)
2278                {
2279                   shift = 7;
2280                   *dp++ = (png_byte)d;
2281                   d = 0;
2282                }
2283
2284                else
2285                   shift--;
2286
2287             }
2288             if (shift != 7)
2289                *dp = (png_byte)d;
2290
2291             break;
2292          }
2293
2294          case 2:
2295          {
2296             png_bytep sp;
2297             png_bytep dp;
2298             int shift;
2299             int d;
2300             int value;
2301             png_uint_32 i;
2302             png_uint_32 row_width = row_info->width;
2303
2304             dp = row;
2305             shift = 6;
2306             d = 0;
2307
2308             for (i = png_pass_start[pass]; i < row_width;
2309                i += png_pass_inc[pass])
2310             {
2311                sp = row + (png_size_t)(i >> 2);
2312                value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
2313                d |= (value << shift);
2314
2315                if (shift == 0)
2316                {
2317                   shift = 6;
2318                   *dp++ = (png_byte)d;
2319                   d = 0;
2320                }
2321
2322                else
2323                   shift -= 2;
2324             }
2325             if (shift != 6)
2326                *dp = (png_byte)d;
2327
2328             break;
2329          }
2330
2331          case 4:
2332          {
2333             png_bytep sp;
2334             png_bytep dp;
2335             int shift;
2336             int d;
2337             int value;
2338             png_uint_32 i;
2339             png_uint_32 row_width = row_info->width;
2340
2341             dp = row;
2342             shift = 4;
2343             d = 0;
2344             for (i = png_pass_start[pass]; i < row_width;
2345                 i += png_pass_inc[pass])
2346             {
2347                sp = row + (png_size_t)(i >> 1);
2348                value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
2349                d |= (value << shift);
2350
2351                if (shift == 0)
2352                {
2353                   shift = 4;
2354                   *dp++ = (png_byte)d;
2355                   d = 0;
2356                }
2357
2358                else
2359                   shift -= 4;
2360             }
2361             if (shift != 4)
2362                *dp = (png_byte)d;
2363
2364             break;
2365          }
2366
2367          default:
2368          {
2369             png_bytep sp;
2370             png_bytep dp;
2371             png_uint_32 i;
2372             png_uint_32 row_width = row_info->width;
2373             png_size_t pixel_bytes;
2374
2375             /* Start at the beginning */
2376             dp = row;
2377
2378             /* Find out how many bytes each pixel takes up */
2379             pixel_bytes = (row_info->pixel_depth >> 3);
2380
2381             /* Loop through the row, only looking at the pixels that matter */
2382             for (i = png_pass_start[pass]; i < row_width;
2383                i += png_pass_inc[pass])
2384             {
2385                /* Find out where the original pixel is */
2386                sp = row + (png_size_t)i * pixel_bytes;
2387
2388                /* Move the pixel */
2389                if (dp != sp)
2390                   png_memcpy(dp, sp, pixel_bytes);
2391
2392                /* Next pixel */
2393                dp += pixel_bytes;
2394             }
2395             break;
2396          }
2397       }
2398       /* Set new row width */
2399       row_info->width = (row_info->width +
2400           png_pass_inc[pass] - 1 -
2401           png_pass_start[pass]) /
2402           png_pass_inc[pass];
2403
2404       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
2405           row_info->width);
2406    }
2407 }
2408 #endif
2409
2410 /* This filters the row, chooses which filter to use, if it has not already
2411  * been specified by the application, and then writes the row out with the
2412  * chosen filter.
2413  */
2414 static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
2415    png_size_t row_bytes);
2416
2417 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
2418 #define PNG_HISHIFT 10
2419 #define PNG_LOMASK ((png_uint_32)0xffffL)
2420 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
2421 void /* PRIVATE */
2422 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
2423 {
2424    png_bytep best_row;
2425 #ifdef PNG_WRITE_FILTER_SUPPORTED
2426    png_bytep prev_row, row_buf;
2427    png_uint_32 mins, bpp;
2428    png_byte filter_to_do = png_ptr->do_filter;
2429    png_size_t row_bytes = row_info->rowbytes;
2430 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2431    int num_p_filters = png_ptr->num_prev_filters;
2432 #endif
2433
2434    png_debug(1, "in png_write_find_filter");
2435
2436 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2437   if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
2438   {
2439      /* These will never be selected so we need not test them. */
2440      filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
2441   }
2442 #endif
2443
2444    /* Find out how many bytes offset each pixel is */
2445    bpp = (row_info->pixel_depth + 7) >> 3;
2446
2447    prev_row = png_ptr->prev_row;
2448 #endif
2449    best_row = png_ptr->row_buf;
2450 #ifdef PNG_WRITE_FILTER_SUPPORTED
2451    row_buf = best_row;
2452    mins = PNG_MAXSUM;
2453
2454    /* The prediction method we use is to find which method provides the
2455     * smallest value when summing the absolute values of the distances
2456     * from zero, using anything >= 128 as negative numbers.  This is known
2457     * as the "minimum sum of absolute differences" heuristic.  Other
2458     * heuristics are the "weighted minimum sum of absolute differences"
2459     * (experimental and can in theory improve compression), and the "zlib
2460     * predictive" method (not implemented yet), which does test compressions
2461     * of lines using different filter methods, and then chooses the
2462     * (series of) filter(s) that give minimum compressed data size (VERY
2463     * computationally expensive).
2464     *
2465     * GRR 980525:  consider also
2466     *
2467     *   (1) minimum sum of absolute differences from running average (i.e.,
2468     *       keep running sum of non-absolute differences & count of bytes)
2469     *       [track dispersion, too?  restart average if dispersion too large?]
2470     *
2471     *  (1b) minimum sum of absolute differences from sliding average, probably
2472     *       with window size <= deflate window (usually 32K)
2473     *
2474     *   (2) minimum sum of squared differences from zero or running average
2475     *       (i.e., ~ root-mean-square approach)
2476     */
2477
2478
2479    /* We don't need to test the 'no filter' case if this is the only filter
2480     * that has been chosen, as it doesn't actually do anything to the data.
2481     */
2482    if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
2483    {
2484       png_bytep rp;
2485       png_uint_32 sum = 0;
2486       png_size_t i;
2487       int v;
2488
2489       for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
2490       {
2491          v = *rp;
2492          sum += (v < 128) ? v : 256 - v;
2493       }
2494
2495 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2496       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2497       {
2498          png_uint_32 sumhi, sumlo;
2499          int j;
2500          sumlo = sum & PNG_LOMASK;
2501          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
2502
2503          /* Reduce the sum if we match any of the previous rows */
2504          for (j = 0; j < num_p_filters; j++)
2505          {
2506             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2507             {
2508                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2509                    PNG_WEIGHT_SHIFT;
2510
2511                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2512                    PNG_WEIGHT_SHIFT;
2513             }
2514          }
2515
2516          /* Factor in the cost of this filter (this is here for completeness,
2517           * but it makes no sense to have a "cost" for the NONE filter, as
2518           * it has the minimum possible computational cost - none).
2519           */
2520          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2521              PNG_COST_SHIFT;
2522
2523          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2524              PNG_COST_SHIFT;
2525
2526          if (sumhi > PNG_HIMASK)
2527             sum = PNG_MAXSUM;
2528
2529          else
2530             sum = (sumhi << PNG_HISHIFT) + sumlo;
2531       }
2532 #endif
2533       mins = sum;
2534    }
2535
2536    /* Sub filter */
2537    if (filter_to_do == PNG_FILTER_SUB)
2538    /* It's the only filter so no testing is needed */
2539    {
2540       png_bytep rp, lp, dp;
2541       png_size_t i;
2542
2543       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2544            i++, rp++, dp++)
2545       {
2546          *dp = *rp;
2547       }
2548
2549       for (lp = row_buf + 1; i < row_bytes;
2550          i++, rp++, lp++, dp++)
2551       {
2552          *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2553       }
2554
2555       best_row = png_ptr->sub_row;
2556    }
2557
2558    else if (filter_to_do & PNG_FILTER_SUB)
2559    {
2560       png_bytep rp, dp, lp;
2561       png_uint_32 sum = 0, lmins = mins;
2562       png_size_t i;
2563       int v;
2564
2565 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2566       /* We temporarily increase the "minimum sum" by the factor we
2567        * would reduce the sum of this filter, so that we can do the
2568        * early exit comparison without scaling the sum each time.
2569        */
2570       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2571       {
2572          int j;
2573          png_uint_32 lmhi, lmlo;
2574          lmlo = lmins & PNG_LOMASK;
2575          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2576
2577          for (j = 0; j < num_p_filters; j++)
2578          {
2579             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2580             {
2581                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2582                    PNG_WEIGHT_SHIFT;
2583
2584                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2585                    PNG_WEIGHT_SHIFT;
2586             }
2587          }
2588
2589          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2590              PNG_COST_SHIFT;
2591
2592          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2593              PNG_COST_SHIFT;
2594
2595          if (lmhi > PNG_HIMASK)
2596             lmins = PNG_MAXSUM;
2597
2598          else
2599             lmins = (lmhi << PNG_HISHIFT) + lmlo;
2600       }
2601 #endif
2602
2603       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2604            i++, rp++, dp++)
2605       {
2606          v = *dp = *rp;
2607
2608          sum += (v < 128) ? v : 256 - v;
2609       }
2610
2611       for (lp = row_buf + 1; i < row_bytes;
2612          i++, rp++, lp++, dp++)
2613       {
2614          v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2615
2616          sum += (v < 128) ? v : 256 - v;
2617
2618          if (sum > lmins)  /* We are already worse, don't continue. */
2619             break;
2620       }
2621
2622 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2623       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2624       {
2625          int j;
2626          png_uint_32 sumhi, sumlo;
2627          sumlo = sum & PNG_LOMASK;
2628          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2629
2630          for (j = 0; j < num_p_filters; j++)
2631          {
2632             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2633             {
2634                sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
2635                    PNG_WEIGHT_SHIFT;
2636
2637                sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
2638                    PNG_WEIGHT_SHIFT;
2639             }
2640          }
2641
2642          sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2643              PNG_COST_SHIFT;
2644
2645          sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2646              PNG_COST_SHIFT;
2647
2648          if (sumhi > PNG_HIMASK)
2649             sum = PNG_MAXSUM;
2650
2651          else
2652             sum = (sumhi << PNG_HISHIFT) + sumlo;
2653       }
2654 #endif
2655
2656       if (sum < mins)
2657       {
2658          mins = sum;
2659          best_row = png_ptr->sub_row;
2660       }
2661    }
2662
2663    /* Up filter */
2664    if (filter_to_do == PNG_FILTER_UP)
2665    {
2666       png_bytep rp, dp, pp;
2667       png_size_t i;
2668
2669       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2670           pp = prev_row + 1; i < row_bytes;
2671           i++, rp++, pp++, dp++)
2672       {
2673          *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2674       }
2675
2676       best_row = png_ptr->up_row;
2677    }
2678
2679    else if (filter_to_do & PNG_FILTER_UP)
2680    {
2681       png_bytep rp, dp, pp;
2682       png_uint_32 sum = 0, lmins = mins;
2683       png_size_t i;
2684       int v;
2685
2686
2687 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2688       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2689       {
2690          int j;
2691          png_uint_32 lmhi, lmlo;
2692          lmlo = lmins & PNG_LOMASK;
2693          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2694
2695          for (j = 0; j < num_p_filters; j++)
2696          {
2697             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2698             {
2699                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2700                    PNG_WEIGHT_SHIFT;
2701
2702                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2703                    PNG_WEIGHT_SHIFT;
2704             }
2705          }
2706
2707          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2708              PNG_COST_SHIFT;
2709
2710          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2711              PNG_COST_SHIFT;
2712
2713          if (lmhi > PNG_HIMASK)
2714             lmins = PNG_MAXSUM;
2715
2716          else
2717             lmins = (lmhi << PNG_HISHIFT) + lmlo;
2718       }
2719 #endif
2720
2721       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2722           pp = prev_row + 1; i < row_bytes; i++)
2723       {
2724          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2725
2726          sum += (v < 128) ? v : 256 - v;
2727
2728          if (sum > lmins)  /* We are already worse, don't continue. */
2729             break;
2730       }
2731
2732 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2733       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2734       {
2735          int j;
2736          png_uint_32 sumhi, sumlo;
2737          sumlo = sum & PNG_LOMASK;
2738          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2739
2740          for (j = 0; j < num_p_filters; j++)
2741          {
2742             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2743             {
2744                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2745                    PNG_WEIGHT_SHIFT;
2746
2747                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2748                    PNG_WEIGHT_SHIFT;
2749             }
2750          }
2751
2752          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2753              PNG_COST_SHIFT;
2754
2755          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2756              PNG_COST_SHIFT;
2757
2758          if (sumhi > PNG_HIMASK)
2759             sum = PNG_MAXSUM;
2760
2761          else
2762             sum = (sumhi << PNG_HISHIFT) + sumlo;
2763       }
2764 #endif
2765
2766       if (sum < mins)
2767       {
2768          mins = sum;
2769          best_row = png_ptr->up_row;
2770       }
2771    }
2772
2773    /* Avg filter */
2774    if (filter_to_do == PNG_FILTER_AVG)
2775    {
2776       png_bytep rp, dp, pp, lp;
2777       png_uint_32 i;
2778
2779       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2780            pp = prev_row + 1; i < bpp; i++)
2781       {
2782          *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2783       }
2784
2785       for (lp = row_buf + 1; i < row_bytes; i++)
2786       {
2787          *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
2788                  & 0xff);
2789       }
2790       best_row = png_ptr->avg_row;
2791    }
2792
2793    else if (filter_to_do & PNG_FILTER_AVG)
2794    {
2795       png_bytep rp, dp, pp, lp;
2796       png_uint_32 sum = 0, lmins = mins;
2797       png_size_t i;
2798       int v;
2799
2800 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2801       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2802       {
2803          int j;
2804          png_uint_32 lmhi, lmlo;
2805          lmlo = lmins & PNG_LOMASK;
2806          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2807
2808          for (j = 0; j < num_p_filters; j++)
2809          {
2810             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
2811             {
2812                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2813                    PNG_WEIGHT_SHIFT;
2814
2815                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2816                    PNG_WEIGHT_SHIFT;
2817             }
2818          }
2819
2820          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2821              PNG_COST_SHIFT;
2822
2823          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2824              PNG_COST_SHIFT;
2825
2826          if (lmhi > PNG_HIMASK)
2827             lmins = PNG_MAXSUM;
2828
2829          else
2830             lmins = (lmhi << PNG_HISHIFT) + lmlo;
2831       }
2832 #endif
2833
2834       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2835            pp = prev_row + 1; i < bpp; i++)
2836       {
2837          v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2838
2839          sum += (v < 128) ? v : 256 - v;
2840       }
2841
2842       for (lp = row_buf + 1; i < row_bytes; i++)
2843       {
2844          v = *dp++ =
2845              (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
2846
2847          sum += (v < 128) ? v : 256 - v;
2848
2849          if (sum > lmins)  /* We are already worse, don't continue. */
2850             break;
2851       }
2852
2853 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2854       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2855       {
2856          int j;
2857          png_uint_32 sumhi, sumlo;
2858          sumlo = sum & PNG_LOMASK;
2859          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2860
2861          for (j = 0; j < num_p_filters; j++)
2862          {
2863             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2864             {
2865                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2866                    PNG_WEIGHT_SHIFT;
2867
2868                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2869                    PNG_WEIGHT_SHIFT;
2870             }
2871          }
2872
2873          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2874              PNG_COST_SHIFT;
2875
2876          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2877              PNG_COST_SHIFT;
2878
2879          if (sumhi > PNG_HIMASK)
2880             sum = PNG_MAXSUM;
2881
2882          else
2883             sum = (sumhi << PNG_HISHIFT) + sumlo;
2884       }
2885 #endif
2886
2887       if (sum < mins)
2888       {
2889          mins = sum;
2890          best_row = png_ptr->avg_row;
2891       }
2892    }
2893
2894    /* Paeth filter */
2895    if (filter_to_do == PNG_FILTER_PAETH)
2896    {
2897       png_bytep rp, dp, pp, cp, lp;
2898       png_size_t i;
2899
2900       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2901           pp = prev_row + 1; i < bpp; i++)
2902       {
2903          *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2904       }
2905
2906       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2907       {
2908          int a, b, c, pa, pb, pc, p;
2909
2910          b = *pp++;
2911          c = *cp++;
2912          a = *lp++;
2913
2914          p = b - c;
2915          pc = a - c;
2916
2917 #ifdef PNG_USE_ABS
2918          pa = abs(p);
2919          pb = abs(pc);
2920          pc = abs(p + pc);
2921 #else
2922          pa = p < 0 ? -p : p;
2923          pb = pc < 0 ? -pc : pc;
2924          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2925 #endif
2926
2927          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2928
2929          *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2930       }
2931       best_row = png_ptr->paeth_row;
2932    }
2933
2934    else if (filter_to_do & PNG_FILTER_PAETH)
2935    {
2936       png_bytep rp, dp, pp, cp, lp;
2937       png_uint_32 sum = 0, lmins = mins;
2938       png_size_t i;
2939       int v;
2940
2941 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2942       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2943       {
2944          int j;
2945          png_uint_32 lmhi, lmlo;
2946          lmlo = lmins & PNG_LOMASK;
2947          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2948
2949          for (j = 0; j < num_p_filters; j++)
2950          {
2951             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
2952             {
2953                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2954                    PNG_WEIGHT_SHIFT;
2955
2956                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2957                    PNG_WEIGHT_SHIFT;
2958             }
2959          }
2960
2961          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2962              PNG_COST_SHIFT;
2963
2964          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2965              PNG_COST_SHIFT;
2966
2967          if (lmhi > PNG_HIMASK)
2968             lmins = PNG_MAXSUM;
2969
2970          else
2971             lmins = (lmhi << PNG_HISHIFT) + lmlo;
2972       }
2973 #endif
2974
2975       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2976           pp = prev_row + 1; i < bpp; i++)
2977       {
2978          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2979
2980          sum += (v < 128) ? v : 256 - v;
2981       }
2982
2983       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2984       {
2985          int a, b, c, pa, pb, pc, p;
2986
2987          b = *pp++;
2988          c = *cp++;
2989          a = *lp++;
2990
2991 #ifndef PNG_SLOW_PAETH
2992          p = b - c;
2993          pc = a - c;
2994 #ifdef PNG_USE_ABS
2995          pa = abs(p);
2996          pb = abs(pc);
2997          pc = abs(p + pc);
2998 #else
2999          pa = p < 0 ? -p : p;
3000          pb = pc < 0 ? -pc : pc;
3001          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3002 #endif
3003          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
3004 #else /* PNG_SLOW_PAETH */
3005          p = a + b - c;
3006          pa = abs(p - a);
3007          pb = abs(p - b);
3008          pc = abs(p - c);
3009
3010          if (pa <= pb && pa <= pc)
3011             p = a;
3012
3013          else if (pb <= pc)
3014             p = b;
3015
3016          else
3017             p = c;
3018 #endif /* PNG_SLOW_PAETH */
3019
3020          v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
3021
3022          sum += (v < 128) ? v : 256 - v;
3023
3024          if (sum > lmins)  /* We are already worse, don't continue. */
3025             break;
3026       }
3027
3028 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
3029       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
3030       {
3031          int j;
3032          png_uint_32 sumhi, sumlo;
3033          sumlo = sum & PNG_LOMASK;
3034          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
3035
3036          for (j = 0; j < num_p_filters; j++)
3037          {
3038             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
3039             {
3040                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
3041                    PNG_WEIGHT_SHIFT;
3042
3043                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
3044                    PNG_WEIGHT_SHIFT;
3045             }
3046          }
3047
3048          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
3049              PNG_COST_SHIFT;
3050
3051          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
3052              PNG_COST_SHIFT;
3053
3054          if (sumhi > PNG_HIMASK)
3055             sum = PNG_MAXSUM;
3056
3057          else
3058             sum = (sumhi << PNG_HISHIFT) + sumlo;
3059       }
3060 #endif
3061
3062       if (sum < mins)
3063       {
3064          best_row = png_ptr->paeth_row;
3065       }
3066    }
3067 #endif /* PNG_WRITE_FILTER_SUPPORTED */
3068
3069    /* Do the actual writing of the filtered row data from the chosen filter. */
3070    png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
3071
3072 #ifdef PNG_WRITE_FILTER_SUPPORTED
3073 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
3074    /* Save the type of filter we picked this time for future calculations */
3075    if (png_ptr->num_prev_filters > 0)
3076    {
3077       int j;
3078
3079       for (j = 1; j < num_p_filters; j++)
3080       {
3081          png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
3082       }
3083
3084       png_ptr->prev_filters[j] = best_row[0];
3085    }
3086 #endif
3087 #endif /* PNG_WRITE_FILTER_SUPPORTED */
3088 }
3089
3090
3091 /* Do the actual writing of a previously filtered row. */
3092 static void
3093 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
3094    png_size_t avail/*includes filter byte*/)
3095 {
3096    png_debug(1, "in png_write_filtered_row");
3097
3098    png_debug1(2, "filter = %d", filtered_row[0]);
3099    /* Set up the zlib input buffer */
3100
3101    png_ptr->zstream.next_in = filtered_row;
3102    png_ptr->zstream.avail_in = 0;
3103    /* Repeat until we have compressed all the data */
3104    do
3105    {
3106       int ret; /* Return of zlib */
3107
3108       /* Record the number of bytes available - zlib supports at least 65535
3109        * bytes at one step, depending on the size of the zlib type 'uInt', the
3110        * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
3111        * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
3112        * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
3113        * uInt.  ZLIB_IO_MAX can be safely reduced to cause zlib to be called
3114        * with smaller chunks of data.
3115        */
3116       if (png_ptr->zstream.avail_in == 0)
3117       {
3118          if (avail > ZLIB_IO_MAX)
3119          {
3120             png_ptr->zstream.avail_in  = ZLIB_IO_MAX;
3121             avail -= ZLIB_IO_MAX;
3122          }
3123
3124          else
3125          {
3126             /* So this will fit in the available uInt space: */
3127             png_ptr->zstream.avail_in = (uInt)avail;
3128             avail = 0;
3129          }
3130       }
3131
3132       /* Compress the data */
3133       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
3134
3135       /* Check for compression errors */
3136       if (ret != Z_OK)
3137       {
3138          if (png_ptr->zstream.msg != NULL)
3139             png_error(png_ptr, png_ptr->zstream.msg);
3140
3141          else
3142             png_error(png_ptr, "zlib error");
3143       }
3144
3145       /* See if it is time to write another IDAT */
3146       if (!(png_ptr->zstream.avail_out))
3147       {
3148          /* Write the IDAT and reset the zlib output buffer */
3149          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
3150       }
3151    /* Repeat until all data has been compressed */
3152    } while (avail > 0 || png_ptr->zstream.avail_in > 0);
3153
3154    /* Swap the current and previous rows */
3155    if (png_ptr->prev_row != NULL)
3156    {
3157       png_bytep tptr;
3158
3159       tptr = png_ptr->prev_row;
3160       png_ptr->prev_row = png_ptr->row_buf;
3161       png_ptr->row_buf = tptr;
3162    }
3163
3164    /* Finish row - updates counters and flushes zlib if last row */
3165    png_write_finish_row(png_ptr);
3166
3167 #ifdef PNG_WRITE_FLUSH_SUPPORTED
3168    png_ptr->flush_rows++;
3169
3170    if (png_ptr->flush_dist > 0 &&
3171        png_ptr->flush_rows >= png_ptr->flush_dist)
3172    {
3173       png_write_flush(png_ptr);
3174    }
3175 #endif
3176 }
3177 #endif /* PNG_WRITE_SUPPORTED */