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