pngwutil.c 87.1 KB
Newer Older
G
Guy Schalnat 已提交
1

A
Andreas Dilger 已提交
2
/* pngwutil.c - utilities to write a PNG file
3
 *
4
 * Last changed in libpng 1.6.0 [(PENDING RELEASE)]
5
 * Copyright (c) 1998-2012 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 */
A
Andreas Dilger 已提交
13

14
#include "pngpriv.h"
G
Guy Schalnat 已提交
15

16 17
#ifdef PNG_WRITE_SUPPORTED

18
#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
A
Andreas Dilger 已提交
19 20 21 22
/* Place a 32-bit number into a buffer in PNG byte order.  We work
 * with unsigned numbers for convenience, although one supported
 * ancillary chunk uses signed (two's complement) numbers.
 */
23
void PNGAPI
G
Guy Schalnat 已提交
24
png_save_uint_32(png_bytep buf, png_uint_32 i)
G
Guy Schalnat 已提交
25 26 27 28 29 30 31
{
   buf[0] = (png_byte)((i >> 24) & 0xff);
   buf[1] = (png_byte)((i >> 16) & 0xff);
   buf[2] = (png_byte)((i >> 8) & 0xff);
   buf[3] = (png_byte)(i & 0xff);
}

32
#ifdef PNG_SAVE_INT_32_SUPPORTED
A
Andreas Dilger 已提交
33
/* The png_save_int_32 function assumes integers are stored in two's
34
 * complement format.  If this isn't the case, then this routine needs to
G
[devel]  
Glenn Randers-Pehrson 已提交
35 36 37
 * be modified to write data in two's complement format.  Note that,
 * the following works correctly even if png_int_32 has more than 32 bits
 * (compare the more complex code required on read for sign extention.)
38
 */
39
void PNGAPI
A
Andreas Dilger 已提交
40
png_save_int_32(png_bytep buf, png_int_32 i)
G
Guy Schalnat 已提交
41 42 43 44 45 46
{
   buf[0] = (png_byte)((i >> 24) & 0xff);
   buf[1] = (png_byte)((i >> 16) & 0xff);
   buf[2] = (png_byte)((i >> 8) & 0xff);
   buf[3] = (png_byte)(i & 0xff);
}
47
#endif
G
Guy Schalnat 已提交
48

49 50 51 52
/* Place a 16-bit number into a buffer in PNG byte order.
 * The parameter is declared unsigned int, not png_uint_16,
 * just to avoid potential problems on pre-ANSI C compilers.
 */
53
void PNGAPI
54
png_save_uint_16(png_bytep buf, unsigned int i)
G
Guy Schalnat 已提交
55 56 57 58
{
   buf[0] = (png_byte)((i >> 8) & 0xff);
   buf[1] = (png_byte)(i & 0xff);
}
59
#endif
G
Guy Schalnat 已提交
60

61 62 63 64 65 66
/* Simple function to write the signature.  If we have already written
 * the magic bytes of the signature, or more likely, the PNG stream is
 * being embedded into another stream and doesn't need its own signature,
 * we should call png_set_sig_bytes() to tell libpng how many of the
 * bytes have already been written.
 */
67
void PNGAPI
68
png_write_sig(png_structrp png_ptr)
69 70
{
   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
71

72 73 74 75 76
#ifdef PNG_IO_STATE_SUPPORTED
   /* Inform the I/O callback that the signature is being written */
   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
#endif

77
   /* Write the rest of the 8 byte signature */
78
   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
79
      (png_size_t)(8 - png_ptr->sig_bytes));
80

81
   if (png_ptr->sig_bytes < 3)
82 83 84
      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
}

A
Andreas Dilger 已提交
85
/* Write the start of a PNG chunk.  The type is the chunk type.
86 87 88
 * The total_length is the sum of the lengths of all the data you will be
 * passing in png_write_chunk_data().
 */
89
static void
90
png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
91
    png_uint_32 length)
G
Guy Schalnat 已提交
92
{
93 94
   png_byte buf[8];

95
#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
96 97 98
   PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
   png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
#endif
99 100 101 102

   if (png_ptr == NULL)
      return;

103 104 105 106 107 108 109
#ifdef PNG_IO_STATE_SUPPORTED
   /* Inform the I/O callback that the chunk header is being written.
    * PNG_IO_CHUNK_HDR requires a single I/O call.
    */
   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
#endif

110
   /* Write the length and the chunk name */
A
Andreas Dilger 已提交
111
   png_save_uint_32(buf, length);
112 113
   png_save_uint_32(buf + 4, chunk_name);
   png_write_data(png_ptr, buf, 8);
114

115
   /* Put the chunk name into png_ptr->chunk_name */
116
   png_ptr->chunk_name = chunk_name;
117

118
   /* Reset the crc and run it over the chunk name */
G
Guy Schalnat 已提交
119
   png_reset_crc(png_ptr);
120

121
   png_calculate_crc(png_ptr, buf + 4, 4);
122 123 124 125 126 127 128

#ifdef PNG_IO_STATE_SUPPORTED
   /* Inform the I/O callback that chunk data will (possibly) be written.
    * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
    */
   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
#endif
G
Guy Schalnat 已提交
129 130
}

131
void PNGAPI
132
png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
133 134 135 136 137 138
    png_uint_32 length)
{
   png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
}

/* Write the data of a PNG chunk started with png_write_chunk_header().
139 140
 * Note that multiple calls to this function are allowed, and that the
 * sum of the lengths from these calls *must* add up to the total_length
141
 * given to png_write_chunk_header().
142
 */
143
void PNGAPI
144
png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
145
    png_size_t length)
G
Guy Schalnat 已提交
146
{
147 148 149
   /* Write the data, and run the CRC over it */
   if (png_ptr == NULL)
      return;
150

A
Andreas Dilger 已提交
151
   if (data != NULL && length > 0)
G
Guy Schalnat 已提交
152
   {
G
Guy Schalnat 已提交
153
      png_write_data(png_ptr, data, length);
154

155
      /* Update the CRC after writing the data,
156 157 158
       * in case that the user I/O routine alters it.
       */
      png_calculate_crc(png_ptr, data, length);
G
Guy Schalnat 已提交
159 160 161
   }
}

162
/* Finish a chunk started with png_write_chunk_header(). */
163
void PNGAPI
164
png_write_chunk_end(png_structrp png_ptr)
G
Guy Schalnat 已提交
165
{
A
Andreas Dilger 已提交
166 167
   png_byte buf[4];

168 169
   if (png_ptr == NULL) return;

170 171 172 173 174 175 176
#ifdef PNG_IO_STATE_SUPPORTED
   /* Inform the I/O callback that the chunk CRC is being written.
    * PNG_IO_CHUNK_CRC requires a single I/O function call.
    */
   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
#endif

177
   /* Write the crc in a single operation */
A
Andreas Dilger 已提交
178 179
   png_save_uint_32(buf, png_ptr->crc);

180
   png_write_data(png_ptr, buf, (png_size_t)4);
G
Guy Schalnat 已提交
181 182
}

183 184 185 186 187 188 189 190 191 192
/* Write a PNG chunk all at once.  The type is an array of ASCII characters
 * representing the chunk name.  The array must be at least 4 bytes in
 * length, and does not need to be null terminated.  To be safe, pass the
 * pre-defined chunk names here, and if you need a new one, define it
 * where the others are defined.  The length is the length of the data.
 * All the data must be present.  If that is not possible, use the
 * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
 * functions instead.
 */
static void
193
png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
194 195 196 197 198 199
   png_const_bytep data, png_size_t length)
{
   if (png_ptr == NULL)
      return;

   /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
200
   if (length > PNG_UINT_31_MAX)
201 202 203 204 205 206 207 208 209
      png_error(png_ptr, "length exceeds PNG maxima");

   png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
   png_write_chunk_data(png_ptr, data, length);
   png_write_chunk_end(png_ptr);
}

/* This is the API that calls the internal function above. */
void PNGAPI
210
png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
211 212 213 214 215 216
   png_const_bytep data, png_size_t length)
{
   png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
      length);
}

217 218 219 220 221 222
/* This is used below to find the size of an image to pass to png_deflate_claim,
 * so it only needs to be accurate if the size is less than 16384 bytes (the
 * point at which a lower LZ window size can be used.)
 */
static png_alloc_size_t
png_image_size(png_structrp png_ptr)
223
{
224 225 226 227 228 229
   /* Only return sizes up to the maximum of a png_uint_32, do this by limiting
    * the width and height used to 15 bits.
    */
   png_uint_32 h = png_ptr->height;

   if (png_ptr->rowbytes < 32768 && h < 32768)
230
   {
231
      if (png_ptr->interlaced)
232
      {
233 234 235 236 237 238 239
         /* Interlacing makes the image larger because of the replication of
          * both the filter byte and the padding to a byte boundary.
          */
         png_uint_32 w = png_ptr->width;
         unsigned int pd = png_ptr->pixel_depth;
         png_alloc_size_t cbBase;
         int pass;
240

241
         for (cbBase=0, pass=0; pass<=6; ++pass)
242
         {
243
            png_uint_32 pw = PNG_PASS_COLS(w, pass);
244

245 246
            if (pw > 0)
               cbBase += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
247 248
         }

249
         return cbBase;
250 251
      }

252 253
      else
         return (png_ptr->rowbytes+1) * h;
254 255 256
   }

   else
257
      return 0xffffffffU;
258 259
}

260 261 262 263 264 265 266
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
   /* This is the code to hack the first two bytes of the deflate stream (the
    * deflate header) to correct the windowBits value to match the actual data
    * size.  Note that the second argument is the *uncompressed* size but the
    * first argument is the *compressed* data (and it must be deflate
    * compressed.)
    */
267
static void
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
optimize_cmf(png_bytep data, png_alloc_size_t data_size)
{
   /* Optimize the CMF field in the zlib stream.  The resultant zlib stream is
    * still compliant to the stream specification.
    */
   if (data_size <= 16384) /* else windowBits must be 15 */
   {
      unsigned int z_cmf = data[0];  /* zlib compression method and flags */

      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
      {
         unsigned int z_cinfo;
         unsigned int half_z_window_size;

         z_cinfo = z_cmf >> 4;
         half_z_window_size = 1U << (z_cinfo + 7);

         if (data_size <= half_z_window_size) /* else no change */
         {
            unsigned int tmp;

            do
            {
               half_z_window_size >>= 1;
               --z_cinfo;
            }
            while (z_cinfo > 0 && data_size <= half_z_window_size);

            z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);

            data[0] = (png_byte)z_cmf;
            tmp = data[1] & 0xe0;
            tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
            data[1] = (png_byte)tmp;
         }
      }
   }
}
#else
#  define optimize_cmf(dp,dl) ((void)0)
#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */

/* Initialize the compressor for the appropriate type of compression. */
static int
png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
313
   png_alloc_size_t data_size)
314
{
315 316 317 318 319 320 321 322 323 324 325 326 327
   if (png_ptr->zowner != 0)
   {
      char msg[64];

      PNG_STRING_FROM_CHUNK(msg, owner);
      msg[4] = ':';
      msg[5] = ' ';
      PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
      /* So the message that results is "<chunk> using zstream"; this is an
       * internal error, but is very useful for debugging.  i18n requirements
       * are minimal.
       */
      (void)png_safecat(msg, sizeof msg, 10, " using zstream");
328
#     if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
         png_warning(png_ptr, msg);

         /* Attempt sane error recovery */
         if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
         {
            png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
            return Z_STREAM_ERROR;
         }

         png_ptr->zowner = 0;
#     else
         png_error(png_ptr, msg);
#     endif
   }

344
   {
345 346 347 348 349 350
      int level = png_ptr->zlib_level;
      int method = png_ptr->zlib_method;
      int windowBits = png_ptr->zlib_window_bits;
      int memLevel = png_ptr->zlib_mem_level;
      int strategy; /* set below */
      int ret; /* zlib return code */
351

352
      if (owner == png_IDAT)
353
      {
354 355
         if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)
            strategy = png_ptr->zlib_strategy;
356

357 358
         else if (png_ptr->do_filter != PNG_FILTER_NONE)
            strategy = Z_FILTERED;
359

360 361 362
         else
            strategy = Z_DEFAULT_STRATEGY;
      }
363

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
      else
      {
#        ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
            level = png_ptr->zlib_text_level;
            method = png_ptr->zlib_text_method;
            windowBits = png_ptr->zlib_text_window_bits;
            memLevel = png_ptr->zlib_text_mem_level;
            strategy = png_ptr->zlib_text_strategy;
#        else
            /* If customization is not supported the values all come from the
             * IDAT values except for the strategy, which is fixed to the
             * default.  (This is the pre-1.6.0 behavior too, although it was
             * implemented in a very different way.)
             */
            strategy = Z_DEFAULT_STRATEGY;
#        endif
      }
381

382
      /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
383 384 385 386 387
       * happening just pass 32768 as the data_size parameter.  Notice that zlib
       * requires an extra 262 bytes in the window in addition to the data to be
       * able to see the whole of the data, so if data_size+262 takes us to the
       * next windowBits size we need to fix up the value later.  (Because even
       * though deflate needs the extra window, inflate does not!)
388
       */
389
      if (data_size <= 16384)
390
      {
391 392 393 394 395 396
         /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
          * work round a Microsoft Visual C misbehavior which, contrary to C-90,
          * widens the result of the following shift to 64-bits if (and,
          * apparently, only if) it is used in a test.
          */
         unsigned int half_window_size = 1U << (windowBits-1);
397

398
         while (data_size + 262 <= half_window_size)
399
         {
400 401
            half_window_size >>= 1;
            --windowBits;
402 403 404
         }
      }

405 406 407 408 409 410 411 412 413 414
      /* Check against the previous initialized values, if any. */
      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) &&
         (png_ptr->zlib_set_level != level ||
         png_ptr->zlib_set_method != method ||
         png_ptr->zlib_set_window_bits != windowBits ||
         png_ptr->zlib_set_mem_level != memLevel ||
         png_ptr->zlib_set_strategy != strategy))
      {
         if (deflateEnd(&png_ptr->zstream) != Z_OK)
            png_warning(png_ptr, "deflateEnd failed (ignored)");
415

416 417
         png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
      }
418

419 420 421 422 423 424 425 426
      /* For safety clear out the input and output pointers (currently zlib
       * doesn't use them on Init, but it might in the future).
       */
      png_ptr->zstream.next_in = NULL;
      png_ptr->zstream.avail_in = 0;
      png_ptr->zstream.next_out = NULL;
      png_ptr->zstream.avail_out = 0;

427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
      /* Now initialize if required, setting the new parameters, otherwise just
       * to a simple reset to the previous parameters.
       */
      if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED)
         ret = deflateReset(&png_ptr->zstream);

      else
      {
         ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
            memLevel, strategy);

         if (ret == Z_OK)
            png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
      }

      /* The return code is from either deflateReset or deflateInit2; they have
       * pretty much the same set of error codes.
       */
      if (ret == Z_OK)
446
         png_ptr->zowner = owner;
447 448

      else
449
         png_zstream_error(png_ptr, ret);
450

451
      return ret;
452 453 454
   }
}

455
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
456
/* This pair of functions encapsulates the operation of (a) compressing a
457 458
 * text string, and (b) issuing it later as a series of chunk data writes.
 * The compression_state structure is shared context for these functions
459 460 461 462 463 464
 * set up by the caller to allow access to the relevant local variables.
 *
 * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
 * temporary buffers.  From 1.6.0 it is retained in png_struct so that it will
 * be correctly freed in the event of a write error (previous implementations
 * just leaked memory.)
465 466 467
 */
typedef struct
{
468 469 470 471
   png_const_bytep      input;        /* The uncompressed input data */
   png_alloc_size_t     input_len;    /* Its length */
   png_uint_32          output_len;   /* Final compressed length */
   png_byte             output[1024]; /* First block of output */
472 473
} compression_state;

474 475 476
static void
png_text_compress_init(compression_state *comp, png_const_bytep input,
   png_alloc_size_t input_len)
477
{
478 479 480 481
   comp->input = input;
   comp->input_len = input_len;
   comp->output_len = 0;
}
482

483 484 485 486
void /* PRIVATE */
png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
{
   png_compression_bufferp list = *listp;
487

488
   if (list != NULL)
489
   {
490
      *listp = NULL;
491

492 493 494
      do
      {
         png_compression_bufferp next = list->next;
495

496 497 498 499
         png_free(png_ptr, list);
         list = next;
      }
      while (list != NULL);
500
   }
501
}
502

503 504 505 506 507 508 509 510 511 512 513
/* Compress the data in the compression state input */
static int
png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
   compression_state *comp, png_uint_32 prefix_len)
{
   int ret;

   /* To find the length of the output it is necessary to first compress the
    * input, the result is buffered rather than using the two-pass algorithm
    * that is used on the inflate side; deflate is assumed to be slower and a
    * PNG writer is assumed to have more memory available than a PNG reader.
514
    *
515 516 517 518
    * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
    * upper limit on the output size, but it is always bigger than the input
    * size so it is likely to be more efficient to use this linked-list
    * approach.
519
    */
520
   ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
521

522 523
   if (ret != Z_OK)
      return ret;
524

525 526 527 528 529 530
   /* Set up the compression buffers, we need a loop here to avoid overflowing a
    * uInt.  Use ZLIB_IO_MAX to limit the input.  The output is always limited
    * by the output buffer size, so there is no need to check that.  Since this
    * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
    * in size.
    */
531
   {
532 533 534
      png_compression_bufferp *end = &png_ptr->zbuffer_list;
      png_alloc_size_t input_len = comp->input_len; /* may be zero! */
      png_uint_32 output_len;
535

536 537 538 539 540
      /* zlib updates these for us: */
      png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
      png_ptr->zstream.avail_in = 0; /* Set below */
      png_ptr->zstream.next_out = comp->output;
      png_ptr->zstream.avail_out = sizeof comp->output;
541

542
      output_len = png_ptr->zstream.avail_out;
543

544
      do
545
      {
546
         uInt avail_in = ZLIB_IO_MAX;
547

548 549
         if (avail_in > input_len)
            avail_in = (uInt)input_len;
550

551
         input_len -= avail_in;
552

553
         png_ptr->zstream.avail_in = avail_in;
554

555 556 557
         if (png_ptr->zstream.avail_out == 0)
         {
            png_compression_buffer *next;
558

559 560 561 562 563 564 565
            /* Chunk data is limited to 2^31 bytes in length, so the prefix
             * length must be counted here.
             */
            if (output_len + prefix_len > PNG_UINT_31_MAX)
            {
               ret = Z_MEM_ERROR;
               break;
566 567
            }

568 569 570 571 572
            /* Need a new (malloc'ed) buffer, but there may be one present
             * already.
             */
            next = *end;
            if (next == NULL)
573
            {
574 575
               next = png_voidcast(png_compression_bufferp, png_malloc_base
                  (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
576

577
               if (next == NULL)
578
               {
579 580
                  ret = Z_MEM_ERROR;
                  break;
581
               }
582

583 584 585
               /* Link in this buffer (so that it will be freed later) */
               next->next = NULL;
               *end = next;
586 587
            }

588 589 590
            png_ptr->zstream.next_out = next->output;
            png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
            output_len += png_ptr->zstream.avail_out;
591

592 593 594
            /* Move 'end' to the next buffer pointer. */
            end = &next->next;
         }
595

596 597 598
         /* Compress the data */
         ret = deflate(&png_ptr->zstream,
            input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
599

600 601 602 603 604
         /* Claw back input data that was not consumed (because avail_in is
          * reset above every time round the loop).
          */
         input_len += png_ptr->zstream.avail_in;
         png_ptr->zstream.avail_in = 0; /* safety */
605
      }
606
      while (ret == Z_OK);
607

608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
      /* There may be some space left in the last output buffer, this needs to
       * be subtracted from output_len.
       */
      output_len -= png_ptr->zstream.avail_out;
      png_ptr->zstream.avail_out = 0; /* safety */
      comp->output_len = output_len;

      /* Now double check the output length, put in a custom message if it is
       * too long.  Otherwise ensure the z_stream::msg pointer is set to
       * something.
       */
      if (output_len + prefix_len >= PNG_UINT_31_MAX)
      {
         png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
         ret = Z_MEM_ERROR;
623 624
      }

625 626
      else
         png_zstream_error(png_ptr, ret);
627

628 629 630 631 632 633 634 635 636 637
      /* Reset zlib for another zTXt/iTXt or image data */
      png_ptr->zowner = 0;

      /* The only success case is Z_STREAM_END, input_len must be 0, if not this
       * is an internal error.
       */
      if (ret == Z_STREAM_END && input_len == 0)
      {
         /* Fix up the deflate header, if required */
         optimize_cmf(comp->output, comp->input_len);
638

639 640 641 642 643 644 645 646 647 648
         /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
          * function above to return Z_STREAM_END on an error (though it never
          * does in the current versions of zlib.)
          */
         return Z_OK;
      }

      else
         return ret;
   }
649 650
}

651
/* Ship the compressed text out via chunk writes */
652
static void
653
png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
654
{
655 656 657 658
   png_uint_32 output_len = comp->output_len;
   png_const_bytep output = comp->output;
   png_uint_32 avail = sizeof comp->output;
   png_compression_buffer *next = png_ptr->zbuffer_list;
659

660
   for (;;)
661
   {
662 663
      if (avail > output_len)
         avail = output_len;
664

665
      png_write_chunk_data(png_ptr, output, avail);
666

667
      output_len -= avail;
668

669 670
      if (output_len == 0 || next == NULL)
         break;
671

672 673 674 675
      avail = png_ptr->zbuffer_size;
      output = next->output;
      next = next->next;
   }
676

677 678 679 680 681
   /* This is an internal error; 'next' must have been NULL! */
   if (output_len > 0)
      png_error(png_ptr, "error writing ancilliary chunked compressed data");
}
#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
682

683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
 * and if invalid, correct the keyword rather than discarding the entire
 * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
 * length, forbids leading or trailing whitespace, multiple internal spaces,
 * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
 *
 * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
 * trailing '\0').  If this routine returns 0 then there was no keyword, or a
 * valid one could not be generated, and the caller must png_error.
 */
static png_uint_32
png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
{
   png_const_charp orig_key = key;
   png_uint_32 key_len = 0;
   int bad_character = 0;
   int space = 1;
702

703
   png_debug(1, "in png_check_keyword");
704

705 706 707 708 709 710 711 712 713
   if (key == NULL)
   {
      *new_key = 0;
      return 0;
   }
   
   while (*key && key_len < 79)
   {
      png_byte ch = (png_byte)(0xff & *key++);
714

715 716
      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
         *new_key++ = ch, ++key_len, space = 0;
717

718 719 720 721 722 723
      else if (!space)
      {
         /* A space or an invalid character when one wasn't seen immediately
          * before; output just a space.
          */
         *new_key++ = 32, ++key_len, space = 1;
724

725 726 727
         /* If the character was not a space then it is inalid. */
         if (ch != 32)
            bad_character = ch;
728 729
      }

730 731
      else if (!bad_character)
         bad_character = ch; /* just skip it, record the first error */
732 733
   }

734
   if (key_len > 0 && space) /* trailing space */
735
   {
736 737 738
      --key_len, --new_key;
      if (!bad_character)
         bad_character = 32;
739
   }
740

741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
   /* Terminate the keyword */
   *new_key = 0;

   if (key_len == 0)
      return 0;

   /* Try to only output one warning per keyword: */
   if (*key) /* keyword too long */
      png_warning(png_ptr, "keyword truncated");

   else if (bad_character)
   {
      PNG_WARNING_PARAMETERS(p)

      png_warning_parameter(p, 1, orig_key);
      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
757

758 759
      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
   }
760

761
   return key_len;
762
}
763
#endif
764

G
Guy Schalnat 已提交
765
/* Write the IHDR chunk, and update the png_struct with the necessary
766 767 768
 * information.  Note that the rest of this code depends upon this
 * information being correct.
 */
769
void /* PRIVATE */
770
png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
771 772
    int bit_depth, int color_type, int compression_type, int filter_type,
    int interlace_type)
G
Guy Schalnat 已提交
773
{
774
   png_byte buf[13]; /* Buffer to store the IHDR info */
G
Guy Schalnat 已提交
775

776
   png_debug(1, "in png_write_IHDR");
777

G
Guy Schalnat 已提交
778
   /* Check that we have valid input data from the application info */
G
Guy Schalnat 已提交
779 780
   switch (color_type)
   {
A
Andreas Dilger 已提交
781
      case PNG_COLOR_TYPE_GRAY:
G
Guy Schalnat 已提交
782 783 784 785 786 787
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
            case 8:
788
#ifdef PNG_WRITE_16BIT_SUPPORTED
789
            case 16:
790
#endif
791
               png_ptr->channels = 1; break;
792

793 794 795
            default:
               png_error(png_ptr,
                   "Invalid bit depth for grayscale image");
G
Guy Schalnat 已提交
796
         }
G
Guy Schalnat 已提交
797
         break;
798

A
Andreas Dilger 已提交
799
      case PNG_COLOR_TYPE_RGB:
800
#ifdef PNG_WRITE_16BIT_SUPPORTED
G
Guy Schalnat 已提交
801
         if (bit_depth != 8 && bit_depth != 16)
802 803 804
#else
         if (bit_depth != 8)
#endif
G
Guy Schalnat 已提交
805
            png_error(png_ptr, "Invalid bit depth for RGB image");
806

G
Guy Schalnat 已提交
807 808
         png_ptr->channels = 3;
         break;
809

A
Andreas Dilger 已提交
810
      case PNG_COLOR_TYPE_PALETTE:
G
Guy Schalnat 已提交
811 812 813 814 815
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
816 817 818
            case 8:
               png_ptr->channels = 1;
               break;
819

820 821
            default:
               png_error(png_ptr, "Invalid bit depth for paletted image");
G
Guy Schalnat 已提交
822 823
         }
         break;
824

A
Andreas Dilger 已提交
825
      case PNG_COLOR_TYPE_GRAY_ALPHA:
G
Guy Schalnat 已提交
826 827
         if (bit_depth != 8 && bit_depth != 16)
            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
828

G
Guy Schalnat 已提交
829 830
         png_ptr->channels = 2;
         break;
831

A
Andreas Dilger 已提交
832
      case PNG_COLOR_TYPE_RGB_ALPHA:
833
#ifdef PNG_WRITE_16BIT_SUPPORTED
G
Guy Schalnat 已提交
834
         if (bit_depth != 8 && bit_depth != 16)
835 836 837
#else
         if (bit_depth != 8)
#endif
G
Guy Schalnat 已提交
838
            png_error(png_ptr, "Invalid bit depth for RGBA image");
839

G
Guy Schalnat 已提交
840 841
         png_ptr->channels = 4;
         break;
842

G
Guy Schalnat 已提交
843 844 845 846
      default:
         png_error(png_ptr, "Invalid image color type specified");
   }

A
Andreas Dilger 已提交
847
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
G
Guy Schalnat 已提交
848 849
   {
      png_warning(png_ptr, "Invalid compression type specified");
A
Andreas Dilger 已提交
850
      compression_type = PNG_COMPRESSION_TYPE_BASE;
G
Guy Schalnat 已提交
851 852
   }

853 854 855 856 857 858 859 860 861
   /* Write filter_method 64 (intrapixel differencing) only if
    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
    * 2. Libpng did not write a PNG signature (this filter_method is only
    *    used in PNG datastreams that are embedded in MNG datastreams) and
    * 3. The application called png_permit_mng_features with a mask that
    *    included PNG_FLAG_MNG_FILTER_64 and
    * 4. The filter_method is 64 and
    * 5. The color_type is RGB or RGBA
    */
862
   if (
863
#ifdef PNG_MNG_FEATURES_SUPPORTED
864 865 866 867 868
       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
       (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
869
#endif
870
       filter_type != PNG_FILTER_TYPE_BASE)
G
Guy Schalnat 已提交
871 872
   {
      png_warning(png_ptr, "Invalid filter type specified");
A
Andreas Dilger 已提交
873
      filter_type = PNG_FILTER_TYPE_BASE;
G
Guy Schalnat 已提交
874 875
   }

876
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
A
Andreas Dilger 已提交
877
   if (interlace_type != PNG_INTERLACE_NONE &&
878
       interlace_type != PNG_INTERLACE_ADAM7)
G
Guy Schalnat 已提交
879 880
   {
      png_warning(png_ptr, "Invalid interlace type specified");
A
Andreas Dilger 已提交
881
      interlace_type = PNG_INTERLACE_ADAM7;
G
Guy Schalnat 已提交
882
   }
883 884 885
#else
   interlace_type=PNG_INTERLACE_NONE;
#endif
G
Guy Schalnat 已提交
886

887
   /* Save the relevent information */
G
Guy Schalnat 已提交
888 889 890
   png_ptr->bit_depth = (png_byte)bit_depth;
   png_ptr->color_type = (png_byte)color_type;
   png_ptr->interlaced = (png_byte)interlace_type;
891
#ifdef PNG_MNG_FEATURES_SUPPORTED
892
   png_ptr->filter_type = (png_byte)filter_type;
893
#endif
894
   png_ptr->compression_type = (png_byte)compression_type;
G
Guy Schalnat 已提交
895 896 897
   png_ptr->width = width;
   png_ptr->height = height;

G
Guy Schalnat 已提交
898
   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
899
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
900
   /* Set the usr info, so any transformations can modify it */
G
Guy Schalnat 已提交
901 902
   png_ptr->usr_width = png_ptr->width;
   png_ptr->usr_bit_depth = png_ptr->bit_depth;
G
Guy Schalnat 已提交
903 904
   png_ptr->usr_channels = png_ptr->channels;

905
   /* Pack the header information into the buffer */
G
Guy Schalnat 已提交
906 907 908 909 910 911 912
   png_save_uint_32(buf, width);
   png_save_uint_32(buf + 4, height);
   buf[8] = (png_byte)bit_depth;
   buf[9] = (png_byte)color_type;
   buf[10] = (png_byte)compression_type;
   buf[11] = (png_byte)filter_type;
   buf[12] = (png_byte)interlace_type;
G
Guy Schalnat 已提交
913

914
   /* Write the chunk */
915
   png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
G
Guy Schalnat 已提交
916

G
Guy Schalnat 已提交
917
   if (!(png_ptr->do_filter))
G
Guy Schalnat 已提交
918
   {
A
Andreas Dilger 已提交
919
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
920
          png_ptr->bit_depth < 8)
G
Guy Schalnat 已提交
921
         png_ptr->do_filter = PNG_FILTER_NONE;
922

G
Guy Schalnat 已提交
923
      else
G
Guy Schalnat 已提交
924
         png_ptr->do_filter = PNG_ALL_FILTERS;
G
Guy Schalnat 已提交
925
   }
926

927
   png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
G
Guy Schalnat 已提交
928 929
}

930
/* Write the palette.  We are careful not to trust png_color to be in the
931
 * correct order for PNG, so people can redefine it to any convenient
932 933
 * structure.
 */
934
void /* PRIVATE */
935
png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
936
    png_uint_32 num_pal)
G
Guy Schalnat 已提交
937
{
A
Andreas Dilger 已提交
938
   png_uint_32 i;
939
   png_const_colorp pal_ptr;
G
Guy Schalnat 已提交
940 941
   png_byte buf[3];

942
   png_debug(1, "in png_write_PLTE");
943

944
   if ((
945
#ifdef PNG_MNG_FEATURES_SUPPORTED
946
       !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
947
#endif
948
       num_pal == 0) || num_pal > 256)
949
   {
950 951 952 953
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_error(png_ptr, "Invalid number of colors in palette");
      }
954

955 956 957 958 959
      else
      {
         png_warning(png_ptr, "Invalid number of colors in palette");
         return;
      }
960 961 962 963 964
   }

   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
   {
      png_warning(png_ptr,
965
          "Ignoring request to write a PLTE chunk in grayscale PNG");
966

967
      return;
G
Guy Schalnat 已提交
968 969
   }

A
Andreas Dilger 已提交
970
   png_ptr->num_palette = (png_uint_16)num_pal;
971
   png_debug1(3, "num_palette = %d", png_ptr->num_palette);
G
Guy Schalnat 已提交
972

973
   png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
974
#ifdef PNG_POINTER_INDEXING_SUPPORTED
975

A
Andreas Dilger 已提交
976
   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
G
Guy Schalnat 已提交
977 978 979 980
   {
      buf[0] = pal_ptr->red;
      buf[1] = pal_ptr->green;
      buf[2] = pal_ptr->blue;
981
      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
G
Guy Schalnat 已提交
982
   }
983

984
#else
985 986 987
   /* This is a little slower but some buggy compilers need to do this
    * instead
    */
988
   pal_ptr=palette;
989

990 991 992 993 994
   for (i = 0; i < num_pal; i++)
   {
      buf[0] = pal_ptr[i].red;
      buf[1] = pal_ptr[i].green;
      buf[2] = pal_ptr[i].blue;
995
      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
996
   }
997

998
#endif
G
Guy Schalnat 已提交
999
   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
1000
   png_ptr->mode |= PNG_HAVE_PLTE;
G
Guy Schalnat 已提交
1001 1002
}

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
/* This is similar to png_text_compress, above, except that it does not require
 * all of the data at once and, instead of buffering the compressed result,
 * writes it as IDAT chunks.  Unlike png_text_compress it *can* png_error out
 * because it calls the write interface.  As a result it does its own error
 * reporting and does not return an error code.  In the event of error it will
 * just call png_error.  The input data length may exceed 32-bits.  The 'flush'
 * parameter is exactly the same as that to deflate, with the following
 * meanings:
 *
 * Z_NO_FLUSH: normal incremental output of compressed data
 * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
 * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
 *
 * The routine manages the acquire and release of the png_ptr->zstream by
 * checking and (at the end) clearing png_ptr->zowner, it does some sanity
 * checks on the 'mode' flags while doing this.
 */
1020
void /* PRIVATE */
1021 1022
png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
   png_alloc_size_t input_len, int flush)
G
Guy Schalnat 已提交
1023
{
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
   if (png_ptr->zowner != png_IDAT)
   {
      /* First time.   Ensure we have a temporary buffer for compression and
       * trim the buffer list if it has more than one entry to free memory.
       */
      if (png_ptr->zbuffer_list == NULL)
      {
         png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
            png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
         png_ptr->zbuffer_list->next = NULL;
      }
1035

1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
      else
         png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);

      /* It is a terminal error if we can't claim the zstream. */
      if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
         png_error(png_ptr, png_ptr->zstream.msg);

      /* The output state is maintained in png_ptr->zstream, so it must be
       * initialized here after the claim.
       */
      png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
      png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
   }

   /* Now loop reading and writing until all the input is consumed or an error
    * terminates the operation.  The _out values are maintained across calls to
    * this function, but the input must be reset each time.
    */
   png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
   png_ptr->zstream.avail_in = 0; /* set below */
   for (;;)
1057
   {
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
      int ret;

      /* INPUT: from the row data */
      uInt avail = ZLIB_IO_MAX;

      if (avail > input_len)
         avail = (uInt)input_len; /* safe because of the check */

      png_ptr->zstream.avail_in = avail;
      input_len -= avail;

      ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);

      /* Include as-yet unconsumed input */
      input_len += png_ptr->zstream.avail_in;
      png_ptr->zstream.avail_in = 0;

      /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note
       * that these two zstream fields are preserved across the calls, therefore
       * there is no need to set these up on entry to the loop.
1078
       */
1079 1080 1081 1082
      if (png_ptr->zstream.avail_out == 0)
      {
         png_bytep data = png_ptr->zbuffer_list->output;
         uInt size = png_ptr->zbuffer_size;
1083

1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
         /* Write an IDAT containing the data then reset the buffer.  The
          * first IDAT may need deflate header optimization.
          */
#        ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
            if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
               png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
               optimize_cmf(data, png_image_size(png_ptr));
#        endif

         png_write_complete_chunk(png_ptr, png_IDAT, data, size);
         png_ptr->mode |= PNG_HAVE_IDAT;

         png_ptr->zstream.next_out = data;
         png_ptr->zstream.avail_out = size;

         /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
          * the same flush parameter until it has finished output, for NO_FLUSH
          * it doesn't matter.
          */
         if (ret == Z_OK && flush != Z_NO_FLUSH)
            continue;
      }

      /* The order of these checks doesn't matter much; it just effect which
       * possible error might be detected if multiple things go wrong at once.
       */
      if (ret == Z_OK) /* most likely return code! */
1111
      {
1112 1113 1114
         /* If all the input has been consumed then just return.  If Z_FINISH
          * was used as the flush parameter something has gone wrong if we get
          * here.
1115
          */
1116
         if (input_len == 0)
1117
         {
1118 1119
            if (flush == Z_FINISH)
               png_error(png_ptr, "Z_OK on Z_FINISH with output space");
1120

1121 1122 1123
            return;
         }
      }
1124

1125 1126 1127 1128 1129 1130 1131
      else if (ret == Z_STREAM_END && flush == Z_FINISH)
      {
         /* This is the end of the IDAT data; any pending output must be
          * flushed.  For small PNG files we may still be at the beginning.
          */
         png_bytep data = png_ptr->zbuffer_list->output;
         uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
1132

1133 1134 1135 1136 1137
#        ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
            if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
               png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
               optimize_cmf(data, png_image_size(png_ptr));
#        endif
1138

1139 1140 1141 1142
         png_write_complete_chunk(png_ptr, png_IDAT, data, size);
         png_ptr->zstream.avail_out = 0;
         png_ptr->zstream.next_out = NULL;
         png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
1143

1144 1145
         png_ptr->zowner = 0; /* Release the stream */
         return;
1146
      }
1147

1148
      else
1149 1150 1151 1152 1153
      {
         /* This is an error condition. */
         png_zstream_error(png_ptr, ret);
         png_error(png_ptr, png_ptr->zstream.msg);
      }
1154
   }
G
Guy Schalnat 已提交
1155 1156
}

1157
/* Write an IEND chunk */
1158
void /* PRIVATE */
1159
png_write_IEND(png_structrp png_ptr)
G
Guy Schalnat 已提交
1160
{
1161
   png_debug(1, "in png_write_IEND");
1162

1163
   png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
A
Andreas Dilger 已提交
1164
   png_ptr->mode |= PNG_HAVE_IEND;
G
Guy Schalnat 已提交
1165 1166
}

1167
#ifdef PNG_WRITE_gAMA_SUPPORTED
1168
/* Write a gAMA chunk */
1169
void /* PRIVATE */
1170
png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
1171 1172 1173
{
   png_byte buf[4];

1174
   png_debug(1, "in png_write_gAMA");
1175

1176
   /* file_gamma is saved in 1/100,000ths */
1177
   png_save_uint_32(buf, (png_uint_32)file_gamma);
1178
   png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
1179 1180
}
#endif
G
Guy Schalnat 已提交
1181

1182
#ifdef PNG_WRITE_sRGB_SUPPORTED
1183
/* Write a sRGB chunk */
1184
void /* PRIVATE */
1185
png_write_sRGB(png_structrp png_ptr, int srgb_intent)
1186 1187 1188
{
   png_byte buf[1];

1189
   png_debug(1, "in png_write_sRGB");
1190

1191
   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1192 1193
      png_warning(png_ptr,
          "Invalid sRGB rendering intent specified");
1194

1195
   buf[0]=(png_byte)srgb_intent;
1196
   png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
1197 1198 1199
}
#endif

1200
#ifdef PNG_WRITE_iCCP_SUPPORTED
1201
/* Write an iCCP chunk */
1202
void /* PRIVATE */
1203 1204
png_write_iCCP(png_structrp png_ptr, png_const_charp name,
    png_const_bytep profile)
1205
{
1206
   png_uint_32 name_len;
1207
   png_uint_32 profile_len;
1208
   png_byte new_name[81]; /* 1 byte for the compression byte */
1209 1210
   compression_state comp;

1211
   png_debug(1, "in png_write_iCCP");
1212

1213 1214 1215
   /* These are all internal problems: the profile should have been checked
    * before when it was stored.
    */
1216
   if (profile == NULL)
1217 1218 1219
      png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */

   profile_len = png_get_uint_32(profile);
1220

1221 1222
   if (profile_len < 132)
      png_error(png_ptr, "ICC profile too short");
1223

1224
   if (profile_len & 0x03)
1225
      png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
1226

1227
   {
1228
      png_uint_32 embedded_profile_len = png_get_uint_32(profile);
1229

1230 1231 1232
      if (profile_len != embedded_profile_len)
         png_error(png_ptr, "Profile length does not match profile");
   }
1233

1234
   name_len = png_check_keyword(png_ptr, name, new_name);
1235

1236 1237
   if (name_len == 0)
      png_error(png_ptr, "iCCP: invalid keyword");
1238

1239
   new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
1240

1241 1242
   /* Make sure we include the NULL after the name and the compression type */
   ++name_len;
1243

1244
   png_text_compress_init(&comp, profile, profile_len);
1245

1246 1247 1248
   /* Allow for keyword terminator and compression byte */
   if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
      png_error(png_ptr, png_ptr->zstream.msg);
1249

1250
   png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
1251

1252
   png_write_chunk_data(png_ptr, new_name, name_len);
1253

1254
   png_write_compressed_data_out(png_ptr, &comp);
1255 1256 1257 1258 1259

   png_write_chunk_end(png_ptr);
}
#endif

1260
#ifdef PNG_WRITE_sPLT_SUPPORTED
1261
/* Write a sPLT chunk */
1262
void /* PRIVATE */
1263
png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
1264
{
1265 1266
   png_uint_32 name_len;
   png_byte new_name[80];
1267
   png_byte entrybuf[10];
1268 1269
   png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
   png_size_t palette_size = entry_size * spalette->nentries;
1270
   png_sPLT_entryp ep;
1271
#ifndef PNG_POINTER_INDEXING_SUPPORTED
1272 1273
   int i;
#endif
1274

1275
   png_debug(1, "in png_write_sPLT");
1276

1277 1278 1279 1280
   name_len = png_check_keyword(png_ptr, spalette->name, new_name);

   if (name_len == 0)
      png_error(png_ptr, "sPLT: invalid keyword");
1281

1282
   /* Make sure we include the NULL after the name */
1283
   png_write_chunk_header(png_ptr, png_sPLT,
1284
       (png_uint_32)(name_len + 2 + palette_size));
1285

1286
   png_write_chunk_data(png_ptr, (png_bytep)new_name,
1287
       (png_size_t)(name_len + 1));
1288

1289
   png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
1290

1291
   /* Loop through each palette entry, writing appropriately */
1292
#ifdef PNG_POINTER_INDEXING_SUPPORTED
1293
   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1294
   {
1295 1296
      if (spalette->depth == 8)
      {
1297 1298 1299 1300 1301
         entrybuf[0] = (png_byte)ep->red;
         entrybuf[1] = (png_byte)ep->green;
         entrybuf[2] = (png_byte)ep->blue;
         entrybuf[3] = (png_byte)ep->alpha;
         png_save_uint_16(entrybuf + 4, ep->frequency);
1302
      }
1303

1304 1305
      else
      {
1306 1307 1308 1309 1310
         png_save_uint_16(entrybuf + 0, ep->red);
         png_save_uint_16(entrybuf + 2, ep->green);
         png_save_uint_16(entrybuf + 4, ep->blue);
         png_save_uint_16(entrybuf + 6, ep->alpha);
         png_save_uint_16(entrybuf + 8, ep->frequency);
1311
      }
1312

1313
      png_write_chunk_data(png_ptr, entrybuf, entry_size);
1314
   }
1315 1316
#else
   ep=spalette->entries;
1317
   for (i = 0; i>spalette->nentries; i++)
1318
   {
1319 1320
      if (spalette->depth == 8)
      {
1321 1322 1323 1324 1325
         entrybuf[0] = (png_byte)ep[i].red;
         entrybuf[1] = (png_byte)ep[i].green;
         entrybuf[2] = (png_byte)ep[i].blue;
         entrybuf[3] = (png_byte)ep[i].alpha;
         png_save_uint_16(entrybuf + 4, ep[i].frequency);
1326
      }
1327

1328 1329
      else
      {
1330 1331 1332 1333 1334
         png_save_uint_16(entrybuf + 0, ep[i].red);
         png_save_uint_16(entrybuf + 2, ep[i].green);
         png_save_uint_16(entrybuf + 4, ep[i].blue);
         png_save_uint_16(entrybuf + 6, ep[i].alpha);
         png_save_uint_16(entrybuf + 8, ep[i].frequency);
1335
      }
1336

1337
      png_write_chunk_data(png_ptr, entrybuf, entry_size);
1338 1339
   }
#endif
1340 1341 1342 1343 1344

   png_write_chunk_end(png_ptr);
}
#endif

1345
#ifdef PNG_WRITE_sBIT_SUPPORTED
1346
/* Write the sBIT chunk */
1347
void /* PRIVATE */
1348
png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
G
Guy Schalnat 已提交
1349 1350
{
   png_byte buf[4];
A
Andreas Dilger 已提交
1351
   png_size_t size;
G
Guy Schalnat 已提交
1352

1353
   png_debug(1, "in png_write_sBIT");
1354

1355
   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
G
Guy Schalnat 已提交
1356 1357
   if (color_type & PNG_COLOR_MASK_COLOR)
   {
1358
      png_byte maxbits;
G
Guy Schalnat 已提交
1359

1360
      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
1361
          png_ptr->usr_bit_depth);
1362

1363 1364
      if (sbit->red == 0 || sbit->red > maxbits ||
          sbit->green == 0 || sbit->green > maxbits ||
G
Guy Schalnat 已提交
1365 1366 1367 1368 1369
          sbit->blue == 0 || sbit->blue > maxbits)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1370

G
Guy Schalnat 已提交
1371 1372 1373 1374 1375
      buf[0] = sbit->red;
      buf[1] = sbit->green;
      buf[2] = sbit->blue;
      size = 3;
   }
1376

G
Guy Schalnat 已提交
1377 1378
   else
   {
G
Guy Schalnat 已提交
1379 1380 1381 1382 1383
      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1384

G
Guy Schalnat 已提交
1385 1386 1387 1388 1389 1390
      buf[0] = sbit->gray;
      size = 1;
   }

   if (color_type & PNG_COLOR_MASK_ALPHA)
   {
G
Guy Schalnat 已提交
1391 1392 1393 1394 1395
      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1396

G
Guy Schalnat 已提交
1397 1398 1399
      buf[size++] = sbit->alpha;
   }

1400
   png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
G
Guy Schalnat 已提交
1401
}
G
Guy Schalnat 已提交
1402
#endif
G
Guy Schalnat 已提交
1403

1404
#ifdef PNG_WRITE_cHRM_SUPPORTED
1405
/* Write the cHRM chunk */
1406
void /* PRIVATE */
1407
png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
1408 1409 1410
{
   png_byte buf[32];

1411
   png_debug(1, "in png_write_cHRM");
1412

1413
   /* Each value is saved in 1/100,000ths */
1414 1415
   png_save_int_32(buf,      xy->whitex);
   png_save_int_32(buf +  4, xy->whitey);
1416

1417 1418
   png_save_int_32(buf +  8, xy->redx);
   png_save_int_32(buf + 12, xy->redy);
1419

1420 1421
   png_save_int_32(buf + 16, xy->greenx);
   png_save_int_32(buf + 20, xy->greeny);
1422

1423 1424
   png_save_int_32(buf + 24, xy->bluex);
   png_save_int_32(buf + 28, xy->bluey);
1425

1426
   png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
1427 1428
}
#endif
G
Guy Schalnat 已提交
1429

1430
#ifdef PNG_WRITE_tRNS_SUPPORTED
1431
/* Write the tRNS chunk */
1432
void /* PRIVATE */
1433
png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
1434
    png_const_color_16p tran, int num_trans, int color_type)
G
Guy Schalnat 已提交
1435 1436 1437
{
   png_byte buf[6];

1438
   png_debug(1, "in png_write_tRNS");
1439

G
Guy Schalnat 已提交
1440 1441
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1442
      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1443
      {
1444
         png_warning(png_ptr, "Invalid number of transparent colors specified");
G
Guy Schalnat 已提交
1445 1446
         return;
      }
1447

1448
      /* Write the chunk out as it is */
1449
      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
G
Guy Schalnat 已提交
1450
   }
1451

G
Guy Schalnat 已提交
1452 1453
   else if (color_type == PNG_COLOR_TYPE_GRAY)
   {
1454
      /* One 16 bit value */
1455
      if (tran->gray >= (1 << png_ptr->bit_depth))
1456 1457
      {
         png_warning(png_ptr,
1458
             "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1459

1460 1461
         return;
      }
1462

G
Guy Schalnat 已提交
1463
      png_save_uint_16(buf, tran->gray);
1464
      png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1465
   }
1466

G
Guy Schalnat 已提交
1467 1468
   else if (color_type == PNG_COLOR_TYPE_RGB)
   {
1469
      /* Three 16 bit values */
G
Guy Schalnat 已提交
1470 1471 1472
      png_save_uint_16(buf, tran->red);
      png_save_uint_16(buf + 2, tran->green);
      png_save_uint_16(buf + 4, tran->blue);
1473
#ifdef PNG_WRITE_16BIT_SUPPORTED
1474
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1475 1476 1477
#else
      if (buf[0] | buf[2] | buf[4])
#endif
1478 1479
      {
         png_warning(png_ptr,
1480
           "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1481 1482
         return;
      }
1483

1484
      png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
G
Guy Schalnat 已提交
1485
   }
1486

G
Guy Schalnat 已提交
1487 1488
   else
   {
1489
      png_warning(png_ptr, "Can't write tRNS with an alpha channel");
G
Guy Schalnat 已提交
1490
   }
G
Guy Schalnat 已提交
1491
}
G
Guy Schalnat 已提交
1492
#endif
G
Guy Schalnat 已提交
1493

1494
#ifdef PNG_WRITE_bKGD_SUPPORTED
1495
/* Write the background chunk */
1496
void /* PRIVATE */
1497
png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
G
Guy Schalnat 已提交
1498 1499 1500
{
   png_byte buf[6];

1501
   png_debug(1, "in png_write_bKGD");
1502

G
Guy Schalnat 已提交
1503 1504
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1505
      if (
1506
#ifdef PNG_MNG_FEATURES_SUPPORTED
1507 1508
          (png_ptr->num_palette ||
          (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
1509
#endif
1510
         back->index >= png_ptr->num_palette)
G
Guy Schalnat 已提交
1511 1512 1513 1514
      {
         png_warning(png_ptr, "Invalid background palette index");
         return;
      }
1515

G
Guy Schalnat 已提交
1516
      buf[0] = back->index;
1517
      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
G
Guy Schalnat 已提交
1518
   }
1519

G
Guy Schalnat 已提交
1520 1521 1522 1523 1524
   else if (color_type & PNG_COLOR_MASK_COLOR)
   {
      png_save_uint_16(buf, back->red);
      png_save_uint_16(buf + 2, back->green);
      png_save_uint_16(buf + 4, back->blue);
1525
#ifdef PNG_WRITE_16BIT_SUPPORTED
1526
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1527 1528 1529
#else
      if (buf[0] | buf[2] | buf[4])
#endif
1530 1531
      {
         png_warning(png_ptr,
1532
             "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
1533

1534 1535
         return;
      }
1536

1537
      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
G
Guy Schalnat 已提交
1538
   }
1539

G
Guy Schalnat 已提交
1540
   else
G
Guy Schalnat 已提交
1541
   {
1542
      if (back->gray >= (1 << png_ptr->bit_depth))
1543 1544
      {
         png_warning(png_ptr,
1545
             "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1546

1547 1548
         return;
      }
1549

G
Guy Schalnat 已提交
1550
      png_save_uint_16(buf, back->gray);
1551
      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1552 1553
   }
}
G
Guy Schalnat 已提交
1554
#endif
G
Guy Schalnat 已提交
1555

1556
#ifdef PNG_WRITE_hIST_SUPPORTED
1557
/* Write the histogram */
1558
void /* PRIVATE */
1559
png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
G
Guy Schalnat 已提交
1560
{
1561
   int i;
G
Guy Schalnat 已提交
1562 1563
   png_byte buf[3];

1564
   png_debug(1, "in png_write_hIST");
1565

1566
   if (num_hist > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1567
   {
1568
      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1569
          png_ptr->num_palette);
1570

G
Guy Schalnat 已提交
1571 1572 1573 1574
      png_warning(png_ptr, "Invalid number of histogram entries specified");
      return;
   }

1575
   png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1576

A
Andreas Dilger 已提交
1577
   for (i = 0; i < num_hist; i++)
G
Guy Schalnat 已提交
1578
   {
G
Guy Schalnat 已提交
1579
      png_save_uint_16(buf, hist[i]);
1580
      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1581
   }
1582

G
Guy Schalnat 已提交
1583 1584
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1585
#endif
G
Guy Schalnat 已提交
1586

1587
#ifdef PNG_WRITE_tEXt_SUPPORTED
1588
/* Write a tEXt chunk */
1589
void /* PRIVATE */
1590
png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1591
    png_size_t text_len)
G
Guy Schalnat 已提交
1592
{
1593 1594
   png_uint_32 key_len;
   png_byte new_key[80];
A
Andreas Dilger 已提交
1595

1596
   png_debug(1, "in png_write_tEXt");
1597

1598 1599 1600 1601
   key_len = png_check_keyword(png_ptr, key, new_key);

   if (key_len == 0)
      png_error(png_ptr, "tEXt: invalid keyword");
G
Guy Schalnat 已提交
1602

A
Andreas Dilger 已提交
1603
   if (text == NULL || *text == '\0')
A
Andreas Dilger 已提交
1604
      text_len = 0;
1605

1606 1607
   else
      text_len = png_strlen(text);
A
Andreas Dilger 已提交
1608

1609 1610 1611
   if (text_len > PNG_UINT_31_MAX - (key_len+1))
      png_error(png_ptr, "tEXt: text too long");

1612
   /* Make sure we include the 0 after the key */
1613
   png_write_chunk_header(png_ptr, png_tEXt,
1614
       (png_uint_32)/*checked above*/(key_len + text_len + 1));
1615 1616 1617 1618
   /*
    * We leave it to the application to meet PNG-1.0 requirements on the
    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
1619
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1620
    */
1621
   png_write_chunk_data(png_ptr, new_key, key_len + 1);
1622

A
Andreas Dilger 已提交
1623
   if (text_len)
1624
      png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
A
Andreas Dilger 已提交
1625

G
Guy Schalnat 已提交
1626 1627
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1628
#endif
G
Guy Schalnat 已提交
1629

1630
#ifdef PNG_WRITE_zTXt_SUPPORTED
1631
/* Write a compressed text chunk */
1632
void /* PRIVATE */
1633
png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1634
    png_size_t text_len, int compression)
G
Guy Schalnat 已提交
1635
{
1636 1637
   png_uint_32 key_len;
   png_byte new_key[81];
1638
   compression_state comp;
G
Guy Schalnat 已提交
1639

1640
   png_debug(1, "in png_write_zTXt");
1641
   PNG_UNUSED(text_len); /* Always use strlen */
A
Andreas Dilger 已提交
1642

1643
   if (compression == PNG_TEXT_COMPRESSION_NONE)
A
Andreas Dilger 已提交
1644
   {
1645
      png_write_tEXt(png_ptr, key, text, 0);
G
Guy Schalnat 已提交
1646
      return;
A
Andreas Dilger 已提交
1647
   }
A
Andreas Dilger 已提交
1648

1649 1650
   if (compression != PNG_TEXT_COMPRESSION_zTXt)
      png_error(png_ptr, "zTXt: invalid compression type");
A
Andreas Dilger 已提交
1651

1652
   key_len = png_check_keyword(png_ptr, key, new_key);
1653

1654 1655
   if (key_len == 0)
      png_error(png_ptr, "zTXt: invalid keyword");
G
Guy Schalnat 已提交
1656

1657 1658 1659
   /* Add the compression method and 1 for the keyword separator. */
   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
   ++key_len;
1660

1661 1662 1663
   /* Compute the compressed data; do it now for the length */
   png_text_compress_init(&comp, (png_const_bytep)text,
      text == NULL ? 0 : strlen(text));
1664

1665 1666
   if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
      png_error(png_ptr, png_ptr->zstream.msg);
1667

1668 1669
   /* Write start of chunk */
   png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
1670

1671 1672
   /* Write key */
   png_write_chunk_data(png_ptr, new_key, key_len);
1673

1674
   /* Write the compressed data */
1675
   png_write_compressed_data_out(png_ptr, &comp);
G
Guy Schalnat 已提交
1676

1677
   /* Close the chunk */
1678 1679 1680
   png_write_chunk_end(png_ptr);
}
#endif
G
Guy Schalnat 已提交
1681

1682
#ifdef PNG_WRITE_iTXt_SUPPORTED
1683
/* Write an iTXt chunk */
1684
void /* PRIVATE */
1685
png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
1686
    png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1687
{
1688 1689 1690
   png_uint_32 key_len, prefix_len;
   png_size_t lang_len, lang_key_len;
   png_byte new_key[82];
1691
   compression_state comp;
G
Guy Schalnat 已提交
1692

1693
   png_debug(1, "in png_write_iTXt");
G
Guy Schalnat 已提交
1694

1695 1696 1697 1698
   key_len = png_check_keyword(png_ptr, key, new_key);
   
   if (key_len == 0)
      png_error(png_ptr, "iTXt: invalid keyword");
1699

1700 1701
   /* Set the compression flag */
   switch (compression)
1702
   {
1703 1704 1705 1706
      case PNG_ITXT_COMPRESSION_NONE:
      case PNG_TEXT_COMPRESSION_NONE:
         compression = new_key[++key_len] = 0; /* no compression */
         break;
G
Guy Schalnat 已提交
1707

1708 1709 1710 1711
      case PNG_TEXT_COMPRESSION_zTXt:
      case PNG_ITXT_COMPRESSION_zTXt:
         compression = new_key[++key_len] = 1; /* compressed */
         break;
1712

1713 1714 1715
      default:
         png_error(png_ptr, "iTXt: invalid compression");
   }
G
Guy Schalnat 已提交
1716

1717 1718
   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
   ++key_len; /* for the keywod separator */
G
Guy Schalnat 已提交
1719

1720
   /* We leave it to the application to meet PNG-1.0 requirements on the
1721
    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
1722 1723 1724 1725
    * any non-Latin-1 characters except for NEWLINE.  ISO PNG, however,
    * specifies that the text is UTF-8 and this really doesn't require any
    * checking.
    *
1726
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1727 1728
    *
    * TODO: validate the language tag correctly (see the spec.)
1729
    */
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740
   if (lang == NULL) lang = ""; /* empty language is valid */
   lang_len = strlen(lang)+1;
   if (lang_key == NULL) lang_key = ""; /* may be empty */
   lang_key_len = strlen(lang_key)+1;
   if (text == NULL) text = ""; /* may be empty */

   prefix_len = key_len;
   if (lang_len > PNG_UINT_31_MAX-prefix_len)
      prefix_len = PNG_UINT_31_MAX;
   else
      prefix_len = (png_uint_32)(prefix_len + lang_len);
1741

1742 1743 1744 1745
   if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
      prefix_len = PNG_UINT_31_MAX;
   else
      prefix_len = (png_uint_32)(prefix_len + lang_key_len);
1746

1747
   png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
1748

1749 1750 1751 1752 1753
   if (compression)
   {
      if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
         png_error(png_ptr, png_ptr->zstream.msg);
   }
1754

1755 1756 1757 1758 1759
   else
   {
      if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
         png_error(png_ptr, "iTXt: uncompressed text too long");
   }
1760

1761
   png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
1762

1763
   png_write_chunk_data(png_ptr, new_key, key_len);
1764

1765
   png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
G
Guy Schalnat 已提交
1766

1767 1768 1769 1770
   png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);

   if (compression)
      png_write_compressed_data_out(png_ptr, &comp);
1771

1772 1773 1774 1775
   else
      png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len);

   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
1776
}
G
Guy Schalnat 已提交
1777
#endif
G
Guy Schalnat 已提交
1778

1779
#ifdef PNG_WRITE_oFFs_SUPPORTED
1780
/* Write the oFFs chunk */
1781
void /* PRIVATE */
1782
png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1783
    int unit_type)
G
Guy Schalnat 已提交
1784 1785 1786
{
   png_byte buf[9];

1787
   png_debug(1, "in png_write_oFFs");
1788

A
Andreas Dilger 已提交
1789 1790
   if (unit_type >= PNG_OFFSET_LAST)
      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
G
Guy Schalnat 已提交
1791

1792 1793
   png_save_int_32(buf, x_offset);
   png_save_int_32(buf + 4, y_offset);
G
Guy Schalnat 已提交
1794
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1795

1796
   png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
G
Guy Schalnat 已提交
1797
}
G
Guy Schalnat 已提交
1798
#endif
1799
#ifdef PNG_WRITE_pCAL_SUPPORTED
1800
/* Write the pCAL chunk (described in the PNG extensions document) */
1801
void /* PRIVATE */
1802
png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
1803 1804
    png_int_32 X1, int type, int nparams, png_const_charp units,
    png_charpp params)
A
Andreas Dilger 已提交
1805
{
1806 1807
   png_uint_32 purpose_len;
   png_size_t units_len, total_len;
1808
   png_size_tp params_len;
A
Andreas Dilger 已提交
1809
   png_byte buf[10];
1810
   png_byte new_purpose[80];
A
Andreas Dilger 已提交
1811 1812
   int i;

1813
   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1814

A
Andreas Dilger 已提交
1815
   if (type >= PNG_EQUATION_LAST)
1816 1817 1818 1819 1820 1821 1822 1823
      png_error(png_ptr, "Unrecognized equation type for pCAL chunk");

   purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);

   if (purpose_len == 0)
      png_error(png_ptr, "pCAL: invalid keyword");
   
   ++purpose_len; /* terminator */
A
Andreas Dilger 已提交
1824

1825
   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
A
Andreas Dilger 已提交
1826
   units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
1827
   png_debug1(3, "pCAL units length = %d", (int)units_len);
A
Andreas Dilger 已提交
1828 1829
   total_len = purpose_len + units_len + 10;

1830 1831
   params_len = (png_size_tp)png_malloc(png_ptr,
       (png_alloc_size_t)(nparams * png_sizeof(png_size_t)));
A
Andreas Dilger 已提交
1832 1833

   /* Find the length of each parameter, making sure we don't count the
1834 1835
    * null terminator for the last parameter.
    */
A
Andreas Dilger 已提交
1836 1837 1838
   for (i = 0; i < nparams; i++)
   {
      params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1839
      png_debug2(3, "pCAL parameter %d length = %lu", i,
1840
          (unsigned long)params_len[i]);
1841
      total_len += params_len[i];
A
Andreas Dilger 已提交
1842 1843
   }

1844
   png_debug1(3, "pCAL total length = %d", (int)total_len);
1845
   png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
1846
   png_write_chunk_data(png_ptr, new_purpose, purpose_len);
A
Andreas Dilger 已提交
1847 1848 1849 1850
   png_save_int_32(buf, X0);
   png_save_int_32(buf + 4, X1);
   buf[8] = (png_byte)type;
   buf[9] = (png_byte)nparams;
1851
   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
1852
   png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
A
Andreas Dilger 已提交
1853 1854 1855

   for (i = 0; i < nparams; i++)
   {
1856
      png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
A
Andreas Dilger 已提交
1857 1858
   }

1859
   png_free(png_ptr, params_len);
A
Andreas Dilger 已提交
1860 1861 1862 1863
   png_write_chunk_end(png_ptr);
}
#endif

1864
#ifdef PNG_WRITE_sCAL_SUPPORTED
1865
/* Write the sCAL chunk */
1866
void /* PRIVATE */
1867
png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
1868
    png_const_charp height)
1869
{
1870 1871
   png_byte buf[64];
   png_size_t wlen, hlen, total_len;
1872

1873
   png_debug(1, "in png_write_sCAL_s");
1874

1875 1876 1877
   wlen = png_strlen(width);
   hlen = png_strlen(height);
   total_len = wlen + hlen + 2;
1878

1879 1880 1881 1882 1883
   if (total_len > 64)
   {
      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
      return;
   }
1884

1885
   buf[0] = (png_byte)unit;
1886 1887
   png_memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
   png_memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
1888

1889
   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1890
   png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1891 1892 1893
}
#endif

1894
#ifdef PNG_WRITE_pHYs_SUPPORTED
1895
/* Write the pHYs chunk */
1896
void /* PRIVATE */
1897
png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
1898 1899
    png_uint_32 y_pixels_per_unit,
    int unit_type)
G
Guy Schalnat 已提交
1900 1901 1902
{
   png_byte buf[9];

1903
   png_debug(1, "in png_write_pHYs");
1904

A
Andreas Dilger 已提交
1905 1906
   if (unit_type >= PNG_RESOLUTION_LAST)
      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
G
Guy Schalnat 已提交
1907

A
Andreas Dilger 已提交
1908 1909
   png_save_uint_32(buf, x_pixels_per_unit);
   png_save_uint_32(buf + 4, y_pixels_per_unit);
G
Guy Schalnat 已提交
1910
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1911

1912
   png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
G
Guy Schalnat 已提交
1913
}
G
Guy Schalnat 已提交
1914
#endif
G
Guy Schalnat 已提交
1915

1916
#ifdef PNG_WRITE_tIME_SUPPORTED
1917 1918 1919
/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
 * or png_convert_from_time_t(), or fill in the structure yourself.
 */
1920
void /* PRIVATE */
1921
png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
G
Guy Schalnat 已提交
1922 1923 1924
{
   png_byte buf[7];

1925
   png_debug(1, "in png_write_tIME");
1926

G
Guy Schalnat 已提交
1927 1928 1929 1930 1931 1932 1933 1934
   if (mod_time->month  > 12 || mod_time->month  < 1 ||
       mod_time->day    > 31 || mod_time->day    < 1 ||
       mod_time->hour   > 23 || mod_time->second > 60)
   {
      png_warning(png_ptr, "Invalid time specified for tIME chunk");
      return;
   }

G
Guy Schalnat 已提交
1935 1936 1937 1938 1939 1940 1941
   png_save_uint_16(buf, mod_time->year);
   buf[2] = mod_time->month;
   buf[3] = mod_time->day;
   buf[4] = mod_time->hour;
   buf[5] = mod_time->minute;
   buf[6] = mod_time->second;

1942
   png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
G
Guy Schalnat 已提交
1943
}
G
Guy Schalnat 已提交
1944
#endif
G
Guy Schalnat 已提交
1945

1946
/* Initializes the row writing capability of libpng */
1947
void /* PRIVATE */
1948
png_write_start_row(png_structrp png_ptr)
G
Guy Schalnat 已提交
1949
{
1950
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1951
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1952

1953
   /* Start of interlace block */
1954
   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1955

1956
   /* Offset to next interlace block */
1957
   static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1958

1959
   /* Start of interlace block in the y direction */
1960
   static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1961

1962
   /* Offset to next interlace block in the y direction */
1963
   static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1964
#endif
1965

1966 1967
   png_alloc_size_t buf_size;
   int usr_pixel_depth;
A
Andreas Dilger 已提交
1968

1969
   png_debug(1, "in png_write_start_row");
1970

1971 1972 1973 1974 1975 1976
   usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
   buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;

   /* 1.5.6: added to allow checking in the row write code. */
   png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
   png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
A
Andreas Dilger 已提交
1977

1978
   /* Set up row buffer */
1979
   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
1980

A
Andreas Dilger 已提交
1981
   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
G
Guy Schalnat 已提交
1982

1983
#ifdef PNG_WRITE_FILTER_SUPPORTED
1984
   /* Set up filtering buffer, if using this filter */
G
Guy Schalnat 已提交
1985
   if (png_ptr->do_filter & PNG_FILTER_SUB)
G
Guy Schalnat 已提交
1986
   {
1987
      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
1988

A
Andreas Dilger 已提交
1989
      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
G
Guy Schalnat 已提交
1990 1991
   }

A
Andreas Dilger 已提交
1992
   /* We only need to keep the previous row if we are using one of these. */
G
Guy Schalnat 已提交
1993 1994
   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
   {
1995
      /* Set up previous row buffer */
1996
      png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
G
Guy Schalnat 已提交
1997 1998 1999

      if (png_ptr->do_filter & PNG_FILTER_UP)
      {
2000
         png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
2001
            png_ptr->rowbytes + 1);
2002

A
Andreas Dilger 已提交
2003
         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
G
Guy Schalnat 已提交
2004 2005 2006 2007
      }

      if (png_ptr->do_filter & PNG_FILTER_AVG)
      {
2008
         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
2009
             png_ptr->rowbytes + 1);
2010

A
Andreas Dilger 已提交
2011
         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
G
Guy Schalnat 已提交
2012 2013 2014 2015
      }

      if (png_ptr->do_filter & PNG_FILTER_PAETH)
      {
2016
         png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
2017
             png_ptr->rowbytes + 1);
2018

A
Andreas Dilger 已提交
2019
         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
G
Guy Schalnat 已提交
2020
      }
G
Guy Schalnat 已提交
2021
   }
2022
#endif /* PNG_WRITE_FILTER_SUPPORTED */
G
Guy Schalnat 已提交
2023

2024
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2025
   /* If interlaced, we need to set up width and height of pass */
G
Guy Schalnat 已提交
2026
   if (png_ptr->interlaced)
G
Guy Schalnat 已提交
2027 2028 2029 2030
   {
      if (!(png_ptr->transformations & PNG_INTERLACE))
      {
         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2031
             png_pass_ystart[0]) / png_pass_yinc[0];
2032

A
Andreas Dilger 已提交
2033
         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2034
             png_pass_start[0]) / png_pass_inc[0];
G
Guy Schalnat 已提交
2035
      }
2036

G
Guy Schalnat 已提交
2037 2038 2039 2040 2041 2042
      else
      {
         png_ptr->num_rows = png_ptr->height;
         png_ptr->usr_width = png_ptr->width;
      }
   }
2043

G
Guy Schalnat 已提交
2044
   else
2045
#endif
G
Guy Schalnat 已提交
2046
   {
G
Guy Schalnat 已提交
2047 2048 2049 2050 2051
      png_ptr->num_rows = png_ptr->height;
      png_ptr->usr_width = png_ptr->width;
   }
}

A
Andreas Dilger 已提交
2052
/* Internal use only.  Called when finished processing a row of data. */
2053
void /* PRIVATE */
2054
png_write_finish_row(png_structrp png_ptr)
G
Guy Schalnat 已提交
2055
{
2056
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2057
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2058

2059
   /* Start of interlace block */
2060
   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2061

2062
   /* Offset to next interlace block */
2063
   static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2064

2065
   /* Start of interlace block in the y direction */
2066
   static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2067

2068
   /* Offset to next interlace block in the y direction */
2069
   static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2070
#endif
2071

2072
   png_debug(1, "in png_write_finish_row");
2073

2074
   /* Next row */
G
Guy Schalnat 已提交
2075
   png_ptr->row_number++;
G
Guy Schalnat 已提交
2076

2077
   /* See if we are done */
G
Guy Schalnat 已提交
2078
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
2079
      return;
G
Guy Schalnat 已提交
2080

2081
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2082
   /* If interlaced, go to next pass */
G
Guy Schalnat 已提交
2083 2084 2085 2086 2087 2088 2089
   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
      if (png_ptr->transformations & PNG_INTERLACE)
      {
         png_ptr->pass++;
      }
2090

G
Guy Schalnat 已提交
2091 2092
      else
      {
2093
         /* Loop until we find a non-zero width or height pass */
G
Guy Schalnat 已提交
2094 2095 2096
         do
         {
            png_ptr->pass++;
2097

G
Guy Schalnat 已提交
2098 2099
            if (png_ptr->pass >= 7)
               break;
2100

G
Guy Schalnat 已提交
2101
            png_ptr->usr_width = (png_ptr->width +
2102 2103 2104
                png_pass_inc[png_ptr->pass] - 1 -
                png_pass_start[png_ptr->pass]) /
                png_pass_inc[png_ptr->pass];
2105

G
Guy Schalnat 已提交
2106
            png_ptr->num_rows = (png_ptr->height +
2107 2108 2109
                png_pass_yinc[png_ptr->pass] - 1 -
                png_pass_ystart[png_ptr->pass]) /
                png_pass_yinc[png_ptr->pass];
2110

G
Guy Schalnat 已提交
2111 2112
            if (png_ptr->transformations & PNG_INTERLACE)
               break;
2113

G
Guy Schalnat 已提交
2114 2115 2116 2117
         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);

      }

2118
      /* Reset the row above the image for the next pass */
G
Guy Schalnat 已提交
2119
      if (png_ptr->pass < 7)
G
Guy Schalnat 已提交
2120
      {
A
Andreas Dilger 已提交
2121
         if (png_ptr->prev_row != NULL)
2122
            png_memset(png_ptr->prev_row, 0,
2123 2124
                (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
                png_ptr->usr_bit_depth, png_ptr->width)) + 1);
2125

G
Guy Schalnat 已提交
2126
         return;
G
Guy Schalnat 已提交
2127
      }
G
Guy Schalnat 已提交
2128
   }
2129
#endif
G
Guy Schalnat 已提交
2130

2131
   /* If we get here, we've just written the last row, so we need
G
Guy Schalnat 已提交
2132
      to flush the compressor */
2133
   png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
G
Guy Schalnat 已提交
2134 2135
}

2136
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2137 2138 2139 2140 2141 2142 2143
/* Pick out the correct pixels for the interlace pass.
 * The basic idea here is to go through the row with a source
 * pointer and a destination pointer (sp and dp), and copy the
 * correct pixels for the pass.  As the row gets compacted,
 * sp will always be >= dp, so we should never overwrite anything.
 * See the default: case for the easiest code to understand.
 */
2144
void /* PRIVATE */
G
Guy Schalnat 已提交
2145
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
G
Guy Schalnat 已提交
2146
{
2147
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2148

2149
   /* Start of interlace block */
2150
   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2151

2152
   /* Offset to next interlace block */
2153
   static PNG_CONST png_byte  png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2154

2155
   png_debug(1, "in png_do_write_interlace");
2156

2157
   /* We don't have to do anything on the last pass (6) */
A
Andreas Dilger 已提交
2158
   if (pass < 6)
G
Guy Schalnat 已提交
2159
   {
2160
      /* Each pixel depth is handled separately */
G
Guy Schalnat 已提交
2161
      switch (row_info->pixel_depth)
G
Guy Schalnat 已提交
2162
      {
G
Guy Schalnat 已提交
2163 2164
         case 1:
         {
G
Guy Schalnat 已提交
2165 2166
            png_bytep sp;
            png_bytep dp;
G
Guy Schalnat 已提交
2167 2168 2169
            int shift;
            int d;
            int value;
2170 2171
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2172 2173 2174 2175

            dp = row;
            d = 0;
            shift = 7;
2176

2177
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2178 2179 2180
               i += png_pass_inc[pass])
            {
               sp = row + (png_size_t)(i >> 3);
2181
               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
G
Guy Schalnat 已提交
2182 2183 2184 2185 2186
               d |= (value << shift);

               if (shift == 0)
               {
                  shift = 7;
G
Guy Schalnat 已提交
2187
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2188 2189
                  d = 0;
               }
2190

G
Guy Schalnat 已提交
2191 2192 2193 2194 2195
               else
                  shift--;

            }
            if (shift != 7)
G
Guy Schalnat 已提交
2196
               *dp = (png_byte)d;
2197

G
Guy Schalnat 已提交
2198 2199
            break;
         }
2200

G
Guy Schalnat 已提交
2201
         case 2:
G
Guy Schalnat 已提交
2202
         {
G
Guy Schalnat 已提交
2203 2204
            png_bytep sp;
            png_bytep dp;
G
Guy Schalnat 已提交
2205 2206 2207
            int shift;
            int d;
            int value;
2208 2209
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2210 2211 2212 2213

            dp = row;
            shift = 6;
            d = 0;
2214

2215
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2216 2217 2218
               i += png_pass_inc[pass])
            {
               sp = row + (png_size_t)(i >> 2);
2219
               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
G
Guy Schalnat 已提交
2220 2221 2222 2223 2224
               d |= (value << shift);

               if (shift == 0)
               {
                  shift = 6;
G
Guy Schalnat 已提交
2225
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2226 2227
                  d = 0;
               }
2228

G
Guy Schalnat 已提交
2229 2230 2231 2232
               else
                  shift -= 2;
            }
            if (shift != 6)
2233 2234
               *dp = (png_byte)d;

G
Guy Schalnat 已提交
2235 2236
            break;
         }
2237

G
Guy Schalnat 已提交
2238 2239
         case 4:
         {
G
Guy Schalnat 已提交
2240 2241
            png_bytep sp;
            png_bytep dp;
G
Guy Schalnat 已提交
2242
            int shift;
G
Guy Schalnat 已提交
2243 2244
            int d;
            int value;
2245 2246
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2247 2248 2249 2250

            dp = row;
            shift = 4;
            d = 0;
2251
            for (i = png_pass_start[pass]; i < row_width;
2252
                i += png_pass_inc[pass])
G
Guy Schalnat 已提交
2253 2254
            {
               sp = row + (png_size_t)(i >> 1);
2255
               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
G
Guy Schalnat 已提交
2256 2257 2258 2259
               d |= (value << shift);

               if (shift == 0)
               {
G
Guy Schalnat 已提交
2260 2261
                  shift = 4;
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2262 2263
                  d = 0;
               }
2264

G
Guy Schalnat 已提交
2265 2266 2267 2268
               else
                  shift -= 4;
            }
            if (shift != 4)
G
Guy Schalnat 已提交
2269
               *dp = (png_byte)d;
2270

G
Guy Schalnat 已提交
2271 2272
            break;
         }
2273

G
Guy Schalnat 已提交
2274 2275
         default:
         {
G
Guy Schalnat 已提交
2276 2277
            png_bytep sp;
            png_bytep dp;
2278 2279
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2280
            png_size_t pixel_bytes;
G
Guy Schalnat 已提交
2281

2282
            /* Start at the beginning */
G
Guy Schalnat 已提交
2283
            dp = row;
2284

2285
            /* Find out how many bytes each pixel takes up */
G
Guy Schalnat 已提交
2286
            pixel_bytes = (row_info->pixel_depth >> 3);
2287 2288

            /* Loop through the row, only looking at the pixels that matter */
2289
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2290 2291
               i += png_pass_inc[pass])
            {
2292
               /* Find out where the original pixel is */
2293
               sp = row + (png_size_t)i * pixel_bytes;
2294

2295
               /* Move the pixel */
G
Guy Schalnat 已提交
2296
               if (dp != sp)
G
Guy Schalnat 已提交
2297
                  png_memcpy(dp, sp, pixel_bytes);
2298

2299
               /* Next pixel */
G
Guy Schalnat 已提交
2300 2301
               dp += pixel_bytes;
            }
G
Guy Schalnat 已提交
2302
            break;
G
Guy Schalnat 已提交
2303 2304
         }
      }
2305
      /* Set new row width */
G
Guy Schalnat 已提交
2306
      row_info->width = (row_info->width +
2307 2308 2309
          png_pass_inc[pass] - 1 -
          png_pass_start[pass]) /
          png_pass_inc[pass];
2310

2311 2312
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
          row_info->width);
G
Guy Schalnat 已提交
2313 2314
   }
}
G
Guy Schalnat 已提交
2315
#endif
G
Guy Schalnat 已提交
2316

A
Andreas Dilger 已提交
2317 2318
/* This filters the row, chooses which filter to use, if it has not already
 * been specified by the application, and then writes the row out with the
2319 2320
 * chosen filter.
 */
2321
static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2322
   png_size_t row_bytes);
2323

2324
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
A
Andreas Dilger 已提交
2325
#define PNG_HISHIFT 10
2326 2327
#define PNG_LOMASK ((png_uint_32)0xffffL)
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
2328
void /* PRIVATE */
2329
png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
G
Guy Schalnat 已提交
2330
{
2331
   png_bytep best_row;
2332
#ifdef PNG_WRITE_FILTER_SUPPORTED
2333
   png_bytep prev_row, row_buf;
A
Andreas Dilger 已提交
2334
   png_uint_32 mins, bpp;
2335
   png_byte filter_to_do = png_ptr->do_filter;
2336
   png_size_t row_bytes = row_info->rowbytes;
2337
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2338
   int num_p_filters = png_ptr->num_prev_filters;
2339
#endif
2340 2341 2342 2343

   png_debug(1, "in png_write_find_filter");

#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2344
  if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
2345
  {
2346 2347
     /* These will never be selected so we need not test them. */
     filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
2348
  }
2349
#endif
G
Guy Schalnat 已提交
2350

2351
   /* Find out how many bytes offset each pixel is */
2352
   bpp = (row_info->pixel_depth + 7) >> 3;
G
Guy Schalnat 已提交
2353 2354

   prev_row = png_ptr->prev_row;
2355 2356
#endif
   best_row = png_ptr->row_buf;
2357
#ifdef PNG_WRITE_FILTER_SUPPORTED
2358
   row_buf = best_row;
A
Andreas Dilger 已提交
2359 2360 2361 2362
   mins = PNG_MAXSUM;

   /* The prediction method we use is to find which method provides the
    * smallest value when summing the absolute values of the distances
2363
    * from zero, using anything >= 128 as negative numbers.  This is known
A
Andreas Dilger 已提交
2364
    * as the "minimum sum of absolute differences" heuristic.  Other
2365
    * heuristics are the "weighted minimum sum of absolute differences"
A
Andreas Dilger 已提交
2366
    * (experimental and can in theory improve compression), and the "zlib
2367 2368 2369
    * predictive" method (not implemented yet), which does test compressions
    * of lines using different filter methods, and then chooses the
    * (series of) filter(s) that give minimum compressed data size (VERY
A
Andreas Dilger 已提交
2370
    * computationally expensive).
2371 2372
    *
    * GRR 980525:  consider also
2373
    *
2374 2375 2376
    *   (1) minimum sum of absolute differences from running average (i.e.,
    *       keep running sum of non-absolute differences & count of bytes)
    *       [track dispersion, too?  restart average if dispersion too large?]
2377
    *
2378 2379
    *  (1b) minimum sum of absolute differences from sliding average, probably
    *       with window size <= deflate window (usually 32K)
2380
    *
2381 2382
    *   (2) minimum sum of squared differences from zero or running average
    *       (i.e., ~ root-mean-square approach)
A
Andreas Dilger 已提交
2383
    */
G
Guy Schalnat 已提交
2384

2385

G
Guy Schalnat 已提交
2386
   /* We don't need to test the 'no filter' case if this is the only filter
A
Andreas Dilger 已提交
2387 2388
    * that has been chosen, as it doesn't actually do anything to the data.
    */
2389
   if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
G
Guy Schalnat 已提交
2390
   {
G
Guy Schalnat 已提交
2391 2392
      png_bytep rp;
      png_uint_32 sum = 0;
2393
      png_size_t i;
A
Andreas Dilger 已提交
2394
      int v;
G
Guy Schalnat 已提交
2395

2396
      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
G
Guy Schalnat 已提交
2397 2398 2399 2400
      {
         v = *rp;
         sum += (v < 128) ? v : 256 - v;
      }
A
Andreas Dilger 已提交
2401

2402
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2403 2404 2405
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
         png_uint_32 sumhi, sumlo;
2406
         int j;
A
Andreas Dilger 已提交
2407 2408 2409 2410
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */

         /* Reduce the sum if we match any of the previous rows */
2411
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2412
         {
2413
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
A
Andreas Dilger 已提交
2414
            {
2415
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2416
                   PNG_WEIGHT_SHIFT;
2417

2418
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2419
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2420 2421 2422 2423 2424 2425 2426 2427
            }
         }

         /* Factor in the cost of this filter (this is here for completeness,
          * but it makes no sense to have a "cost" for the NONE filter, as
          * it has the minimum possible computational cost - none).
          */
         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2428
             PNG_COST_SHIFT;
2429

A
Andreas Dilger 已提交
2430
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2431
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2432 2433 2434

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2435

A
Andreas Dilger 已提交
2436 2437 2438 2439
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif
G
Guy Schalnat 已提交
2440 2441
      mins = sum;
   }
G
Guy Schalnat 已提交
2442

2443
   /* Sub filter */
2444
   if (filter_to_do == PNG_FILTER_SUB)
2445
   /* It's the only filter so no testing is needed */
2446 2447
   {
      png_bytep rp, lp, dp;
2448
      png_size_t i;
2449

2450 2451 2452 2453 2454
      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
           i++, rp++, dp++)
      {
         *dp = *rp;
      }
2455

2456
      for (lp = row_buf + 1; i < row_bytes;
2457 2458 2459 2460
         i++, rp++, lp++, dp++)
      {
         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
      }
2461

2462 2463 2464 2465
      best_row = png_ptr->sub_row;
   }

   else if (filter_to_do & PNG_FILTER_SUB)
G
Guy Schalnat 已提交
2466 2467
   {
      png_bytep rp, dp, lp;
A
Andreas Dilger 已提交
2468
      png_uint_32 sum = 0, lmins = mins;
2469
      png_size_t i;
A
Andreas Dilger 已提交
2470 2471
      int v;

2472
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2473
      /* We temporarily increase the "minimum sum" by the factor we
A
Andreas Dilger 已提交
2474 2475 2476 2477 2478
       * would reduce the sum of this filter, so that we can do the
       * early exit comparison without scaling the sum each time.
       */
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2479
         int j;
A
Andreas Dilger 已提交
2480 2481 2482 2483
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2484
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2485
         {
2486
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
A
Andreas Dilger 已提交
2487
            {
2488
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2489
                   PNG_WEIGHT_SHIFT;
2490

2491
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2492
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2493 2494 2495 2496
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2497
             PNG_COST_SHIFT;
2498

A
Andreas Dilger 已提交
2499
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2500
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2501 2502 2503

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2504

A
Andreas Dilger 已提交
2505 2506 2507 2508
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2509

G
Guy Schalnat 已提交
2510 2511 2512 2513
      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
           i++, rp++, dp++)
      {
         v = *dp = *rp;
G
Guy Schalnat 已提交
2514

G
Guy Schalnat 已提交
2515 2516
         sum += (v < 128) ? v : 256 - v;
      }
2517

2518
      for (lp = row_buf + 1; i < row_bytes;
2519
         i++, rp++, lp++, dp++)
G
Guy Schalnat 已提交
2520 2521 2522 2523
      {
         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);

         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2524 2525 2526 2527 2528

         if (sum > lmins)  /* We are already worse, don't continue. */
            break;
      }

2529
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2530 2531
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2532
         int j;
A
Andreas Dilger 已提交
2533 2534 2535 2536
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2537
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2538
         {
2539
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
A
Andreas Dilger 已提交
2540
            {
2541
               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
2542
                   PNG_WEIGHT_SHIFT;
2543

2544
               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
2545
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2546 2547 2548 2549
            }
         }

         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2550
             PNG_COST_SHIFT;
2551

A
Andreas Dilger 已提交
2552
         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2553
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2554 2555 2556

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2557

A
Andreas Dilger 已提交
2558 2559
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
G
Guy Schalnat 已提交
2560
      }
A
Andreas Dilger 已提交
2561 2562
#endif

G
Guy Schalnat 已提交
2563 2564 2565 2566 2567
      if (sum < mins)
      {
         mins = sum;
         best_row = png_ptr->sub_row;
      }
G
Guy Schalnat 已提交
2568 2569
   }

2570
   /* Up filter */
2571 2572 2573
   if (filter_to_do == PNG_FILTER_UP)
   {
      png_bytep rp, dp, pp;
2574
      png_size_t i;
2575 2576

      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2577 2578
          pp = prev_row + 1; i < row_bytes;
          i++, rp++, pp++, dp++)
2579 2580 2581
      {
         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
      }
2582

2583 2584 2585 2586
      best_row = png_ptr->up_row;
   }

   else if (filter_to_do & PNG_FILTER_UP)
G
Guy Schalnat 已提交
2587 2588
   {
      png_bytep rp, dp, pp;
A
Andreas Dilger 已提交
2589
      png_uint_32 sum = 0, lmins = mins;
2590
      png_size_t i;
A
Andreas Dilger 已提交
2591 2592
      int v;

2593

2594
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2595 2596
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2597
         int j;
A
Andreas Dilger 已提交
2598 2599 2600 2601
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2602
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2603
         {
2604
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
A
Andreas Dilger 已提交
2605
            {
2606
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2607
                   PNG_WEIGHT_SHIFT;
2608

2609
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2610
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2611 2612 2613 2614
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2615
             PNG_COST_SHIFT;
2616

A
Andreas Dilger 已提交
2617
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2618
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2619 2620 2621

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2622

A
Andreas Dilger 已提交
2623 2624 2625 2626
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2627

G
Guy Schalnat 已提交
2628
      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2629
          pp = prev_row + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2630
      {
2631
         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
G
Guy Schalnat 已提交
2632 2633

         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2634 2635 2636

         if (sum > lmins)  /* We are already worse, don't continue. */
            break;
G
Guy Schalnat 已提交
2637
      }
A
Andreas Dilger 已提交
2638

2639
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2640 2641
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2642
         int j;
A
Andreas Dilger 已提交
2643 2644 2645 2646
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2647
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2648
         {
2649
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
A
Andreas Dilger 已提交
2650
            {
2651
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2652
                   PNG_WEIGHT_SHIFT;
2653

2654
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2655
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2656 2657 2658 2659
            }
         }

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2660
             PNG_COST_SHIFT;
2661

A
Andreas Dilger 已提交
2662
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2663
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2664 2665 2666

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2667

A
Andreas Dilger 已提交
2668 2669 2670 2671 2672
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2673 2674 2675 2676 2677 2678 2679
      if (sum < mins)
      {
         mins = sum;
         best_row = png_ptr->up_row;
      }
   }

2680
   /* Avg filter */
2681 2682 2683
   if (filter_to_do == PNG_FILTER_AVG)
   {
      png_bytep rp, dp, pp, lp;
2684
      png_uint_32 i;
2685

2686
      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2687
           pp = prev_row + 1; i < bpp; i++)
2688
      {
2689
         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2690
      }
2691

2692
      for (lp = row_buf + 1; i < row_bytes; i++)
2693
      {
2694 2695
         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
                 & 0xff);
2696 2697 2698 2699 2700
      }
      best_row = png_ptr->avg_row;
   }

   else if (filter_to_do & PNG_FILTER_AVG)
G
Guy Schalnat 已提交
2701
   {
G
Guy Schalnat 已提交
2702
      png_bytep rp, dp, pp, lp;
A
Andreas Dilger 已提交
2703
      png_uint_32 sum = 0, lmins = mins;
2704
      png_size_t i;
A
Andreas Dilger 已提交
2705 2706
      int v;

2707
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2708 2709
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2710
         int j;
A
Andreas Dilger 已提交
2711 2712 2713 2714
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2715
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2716
         {
2717
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
A
Andreas Dilger 已提交
2718
            {
2719
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2720
                   PNG_WEIGHT_SHIFT;
2721

2722
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2723
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2724 2725 2726 2727
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2728
             PNG_COST_SHIFT;
2729

A
Andreas Dilger 已提交
2730
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2731
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2732 2733 2734

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2735

A
Andreas Dilger 已提交
2736 2737 2738 2739
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2740

G
Guy Schalnat 已提交
2741
      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2742
           pp = prev_row + 1; i < bpp; i++)
G
Guy Schalnat 已提交
2743
      {
2744
         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
G
Guy Schalnat 已提交
2745

G
Guy Schalnat 已提交
2746 2747
         sum += (v < 128) ? v : 256 - v;
      }
2748

2749
      for (lp = row_buf + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2750
      {
2751
         v = *dp++ =
2752
             (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
G
Guy Schalnat 已提交
2753

G
Guy Schalnat 已提交
2754
         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2755 2756 2757

         if (sum > lmins)  /* We are already worse, don't continue. */
            break;
G
Guy Schalnat 已提交
2758
      }
A
Andreas Dilger 已提交
2759

2760
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2761 2762
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2763
         int j;
A
Andreas Dilger 已提交
2764 2765 2766 2767
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2768
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2769
         {
2770
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
A
Andreas Dilger 已提交
2771
            {
2772
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2773
                   PNG_WEIGHT_SHIFT;
2774

2775
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2776
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2777 2778 2779 2780
            }
         }

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2781
             PNG_COST_SHIFT;
2782

A
Andreas Dilger 已提交
2783
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2784
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2785 2786 2787

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2788

A
Andreas Dilger 已提交
2789 2790 2791 2792 2793
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2794 2795 2796 2797 2798 2799
      if (sum < mins)
      {
         mins = sum;
         best_row = png_ptr->avg_row;
      }
   }
G
Guy Schalnat 已提交
2800

A
Andreas Dilger 已提交
2801
   /* Paeth filter */
2802 2803 2804
   if (filter_to_do == PNG_FILTER_PAETH)
   {
      png_bytep rp, dp, pp, cp, lp;
2805
      png_size_t i;
2806

2807
      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2808
          pp = prev_row + 1; i < bpp; i++)
2809
      {
2810
         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2811 2812
      }

2813
      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2814 2815 2816
      {
         int a, b, c, pa, pb, pc, p;

2817 2818 2819
         b = *pp++;
         c = *cp++;
         a = *lp++;
2820

2821 2822
         p = b - c;
         pc = a - c;
2823 2824

#ifdef PNG_USE_ABS
2825 2826 2827
         pa = abs(p);
         pb = abs(pc);
         pc = abs(p + pc);
2828
#else
2829 2830 2831
         pa = p < 0 ? -p : p;
         pb = pc < 0 ? -pc : pc;
         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2832 2833 2834 2835
#endif

         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;

2836
         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2837 2838 2839 2840 2841
      }
      best_row = png_ptr->paeth_row;
   }

   else if (filter_to_do & PNG_FILTER_PAETH)
G
Guy Schalnat 已提交
2842 2843
   {
      png_bytep rp, dp, pp, cp, lp;
A
Andreas Dilger 已提交
2844
      png_uint_32 sum = 0, lmins = mins;
2845
      png_size_t i;
A
Andreas Dilger 已提交
2846 2847
      int v;

2848
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2849 2850
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2851
         int j;
A
Andreas Dilger 已提交
2852 2853 2854 2855
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2856
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2857
         {
2858
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
A
Andreas Dilger 已提交
2859
            {
2860
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2861
                   PNG_WEIGHT_SHIFT;
2862

2863
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2864
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2865 2866 2867 2868
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2869
             PNG_COST_SHIFT;
2870

A
Andreas Dilger 已提交
2871
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2872
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2873 2874 2875

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2876

A
Andreas Dilger 已提交
2877 2878 2879 2880
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2881

G
Guy Schalnat 已提交
2882
      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2883
          pp = prev_row + 1; i < bpp; i++)
G
Guy Schalnat 已提交
2884
      {
2885
         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
G
Guy Schalnat 已提交
2886

G
Guy Schalnat 已提交
2887 2888
         sum += (v < 128) ? v : 256 - v;
      }
2889

2890
      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2891 2892
      {
         int a, b, c, pa, pb, pc, p;
G
Guy Schalnat 已提交
2893

2894 2895 2896
         b = *pp++;
         c = *cp++;
         a = *lp++;
2897 2898

#ifndef PNG_SLOW_PAETH
2899 2900
         p = b - c;
         pc = a - c;
2901
#ifdef PNG_USE_ABS
2902 2903 2904
         pa = abs(p);
         pb = abs(pc);
         pc = abs(p + pc);
2905
#else
2906 2907 2908
         pa = p < 0 ? -p : p;
         pb = pc < 0 ? -pc : pc;
         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2909 2910 2911
#endif
         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
#else /* PNG_SLOW_PAETH */
2912
         p = a + b - c;
2913 2914 2915
         pa = abs(p - a);
         pb = abs(p - b);
         pc = abs(p - c);
2916

G
Guy Schalnat 已提交
2917 2918
         if (pa <= pb && pa <= pc)
            p = a;
2919

G
Guy Schalnat 已提交
2920 2921
         else if (pb <= pc)
            p = b;
2922

G
Guy Schalnat 已提交
2923 2924
         else
            p = c;
2925
#endif /* PNG_SLOW_PAETH */
G
Guy Schalnat 已提交
2926

2927
         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
G
Guy Schalnat 已提交
2928

G
Guy Schalnat 已提交
2929
         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2930 2931 2932

         if (sum > lmins)  /* We are already worse, don't continue. */
            break;
G
Guy Schalnat 已提交
2933
      }
A
Andreas Dilger 已提交
2934

2935
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2936 2937
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2938
         int j;
A
Andreas Dilger 已提交
2939 2940 2941 2942
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2943
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2944
         {
2945
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
A
Andreas Dilger 已提交
2946
            {
2947
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2948
                   PNG_WEIGHT_SHIFT;
2949

2950
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2951
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2952 2953 2954 2955
            }
         }

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2956
             PNG_COST_SHIFT;
2957

A
Andreas Dilger 已提交
2958
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2959
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2960 2961 2962

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2963

A
Andreas Dilger 已提交
2964 2965 2966 2967 2968
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2969 2970 2971 2972
      if (sum < mins)
      {
         best_row = png_ptr->paeth_row;
      }
G
Guy Schalnat 已提交
2973
   }
2974
#endif /* PNG_WRITE_FILTER_SUPPORTED */
2975

2976 2977
   /* Do the actual writing of the filtered row data from the chosen filter. */
   png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
A
Andreas Dilger 已提交
2978

2979
#ifdef PNG_WRITE_FILTER_SUPPORTED
2980
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2981 2982 2983
   /* Save the type of filter we picked this time for future calculations */
   if (png_ptr->num_prev_filters > 0)
   {
2984
      int j;
2985

2986
      for (j = 1; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2987
      {
2988
         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
A
Andreas Dilger 已提交
2989
      }
2990

2991
      png_ptr->prev_filters[j] = best_row[0];
A
Andreas Dilger 已提交
2992 2993
   }
#endif
2994
#endif /* PNG_WRITE_FILTER_SUPPORTED */
G
Guy Schalnat 已提交
2995
}
G
Guy Schalnat 已提交
2996

G
Guy Schalnat 已提交
2997

A
Andreas Dilger 已提交
2998
/* Do the actual writing of a previously filtered row. */
2999
static void
3000
png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
3001
   png_size_t full_row_length/*includes filter byte*/)
G
Guy Schalnat 已提交
3002
{
3003
   png_debug(1, "in png_write_filtered_row");
3004

3005
   png_debug1(2, "filter = %d", filtered_row[0]);
3006

3007
   png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
G
Guy Schalnat 已提交
3008

3009
   /* Swap the current and previous rows */
A
Andreas Dilger 已提交
3010
   if (png_ptr->prev_row != NULL)
G
Guy Schalnat 已提交
3011 3012 3013 3014 3015 3016 3017 3018
   {
      png_bytep tptr;

      tptr = png_ptr->prev_row;
      png_ptr->prev_row = png_ptr->row_buf;
      png_ptr->row_buf = tptr;
   }

3019
   /* Finish row - updates counters and flushes zlib if last row */
G
Guy Schalnat 已提交
3020
   png_write_finish_row(png_ptr);
G
Guy Schalnat 已提交
3021

3022
#ifdef PNG_WRITE_FLUSH_SUPPORTED
G
Guy Schalnat 已提交
3023 3024 3025 3026 3027 3028
   png_ptr->flush_rows++;

   if (png_ptr->flush_dist > 0 &&
       png_ptr->flush_rows >= png_ptr->flush_dist)
   {
      png_write_flush(png_ptr);
G
Guy Schalnat 已提交
3029
   }
3030
#endif
G
Guy Schalnat 已提交
3031
}
3032
#endif /* PNG_WRITE_SUPPORTED */