~ubuntu-branches/ubuntu/natty/ntop/natty

« back to all changes in this revision

Viewing changes to gdchart0.94c/gd-1.8.3/libpng-1.0.8/pngwutil.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2005-01-30 21:59:13 UTC
  • mfrom: (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050130215913-xc3ke963bw49b3k4
Tags: 2:3.0-5
* Updated README.Debian file so users will understand what to do at
  install, closes: #291794, #287802.
* Updated ntop init script to give better output.
* Also changed log directory from /var/lib/ntop to /var/log/ntop,
  closes: #252352.
* Quoted the interface list to allow whitespace, closes: #267248.
* Added a couple of logcheck ignores, closes: #269321, #269319.

Show diffs side-by-side

added added

removed removed

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