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.17 [March 26, 2015]
5
 * Copyright (c) 1998-2015 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
   buf[0] = (png_byte)(i >> 24);
   buf[1] = (png_byte)(i >> 16);
   buf[2] = (png_byte)(i >> 8);
   buf[3] = (png_byte)(i     );
G
Guy Schalnat 已提交
30 31
}

32 33 34 35
/* 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.
 */
36
void PNGAPI
37
png_save_uint_16(png_bytep buf, unsigned int i)
G
Guy Schalnat 已提交
38
{
39 40
   buf[0] = (png_byte)(i >> 8);
   buf[1] = (png_byte)(i     );
G
Guy Schalnat 已提交
41
}
42
#endif
G
Guy Schalnat 已提交
43

44 45 46 47 48 49
/* 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.
 */
50
void PNGAPI
51
png_write_sig(png_structrp png_ptr)
52 53
{
   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
54

55 56 57 58 59
#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

60
   /* Write the rest of the 8 byte signature */
61
   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
62
      (png_size_t)(8 - png_ptr->sig_bytes));
63

64
   if (png_ptr->sig_bytes < 3)
65 66 67
      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
}

A
Andreas Dilger 已提交
68
/* Write the start of a PNG chunk.  The type is the chunk type.
69 70 71
 * The total_length is the sum of the lengths of all the data you will be
 * passing in png_write_chunk_data().
 */
72
static void
73
png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
74
    png_uint_32 length)
G
Guy Schalnat 已提交
75
{
76 77
   png_byte buf[8];

78
#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
79 80 81
   PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
   png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
#endif
82 83 84 85

   if (png_ptr == NULL)
      return;

86 87 88 89 90 91 92
#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

93
   /* Write the length and the chunk name */
A
Andreas Dilger 已提交
94
   png_save_uint_32(buf, length);
95 96
   png_save_uint_32(buf + 4, chunk_name);
   png_write_data(png_ptr, buf, 8);
97

98
   /* Put the chunk name into png_ptr->chunk_name */
99
   png_ptr->chunk_name = chunk_name;
100

101
   /* Reset the crc and run it over the chunk name */
G
Guy Schalnat 已提交
102
   png_reset_crc(png_ptr);
103

104
   png_calculate_crc(png_ptr, buf + 4, 4);
105 106 107 108 109 110 111

#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 已提交
112 113
}

114
void PNGAPI
115
png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
116 117 118 119 120 121
    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().
122 123
 * 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
124
 * given to png_write_chunk_header().
125
 */
126
void PNGAPI
127
png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
128
    png_size_t length)
G
Guy Schalnat 已提交
129
{
130 131 132
   /* Write the data, and run the CRC over it */
   if (png_ptr == NULL)
      return;
133

A
Andreas Dilger 已提交
134
   if (data != NULL && length > 0)
G
Guy Schalnat 已提交
135
   {
G
Guy Schalnat 已提交
136
      png_write_data(png_ptr, data, length);
137

138
      /* Update the CRC after writing the data,
139
       * in case the user I/O routine alters it.
140 141
       */
      png_calculate_crc(png_ptr, data, length);
G
Guy Schalnat 已提交
142 143 144
   }
}

145
/* Finish a chunk started with png_write_chunk_header(). */
146
void PNGAPI
147
png_write_chunk_end(png_structrp png_ptr)
G
Guy Schalnat 已提交
148
{
A
Andreas Dilger 已提交
149 150
   png_byte buf[4];

151 152
   if (png_ptr == NULL) return;

153 154 155 156 157 158 159
#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

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

163
   png_write_data(png_ptr, buf, (png_size_t)4);
G
Guy Schalnat 已提交
164 165
}

166 167 168 169 170 171 172 173 174 175
/* 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
176
png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
177 178 179 180 181 182
   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. */
183
   if (length > PNG_UINT_31_MAX)
184
      png_error(png_ptr, "length exceeds PNG maximum");
185 186 187 188 189 190 191 192

   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
193
png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
194 195 196 197 198 199
   png_const_bytep data, png_size_t length)
{
   png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
      length);
}

200 201 202 203 204 205
/* 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)
206
{
207
   /* Only return sizes up to the maximum of a png_uint_32; do this by limiting
208 209 210 211 212
    * the width and height used to 15 bits.
    */
   png_uint_32 h = png_ptr->height;

   if (png_ptr->rowbytes < 32768 && h < 32768)
213
   {
214
      if (png_ptr->interlaced != 0)
215
      {
216 217 218 219 220 221 222
         /* 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 cb_base;
         int pass;
223

224
         for (cb_base=0, pass=0; pass<=6; ++pass)
225
         {
226
            png_uint_32 pw = PNG_PASS_COLS(w, pass);
227

228 229
            if (pw > 0)
               cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
230 231
         }

232 233
         return cb_base;
      }
234

235 236 237
      else
         return (png_ptr->rowbytes+1) * h;
   }
238

239 240 241
   else
      return 0xffffffffU;
}
242

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
#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.)
    */
static void
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 */
259

260 261 262 263
      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
      {
         unsigned int z_cinfo;
         unsigned int half_z_window_size;
264

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

268 269 270 271 272 273 274 275
         if (data_size <= half_z_window_size) /* else no change */
         {
            unsigned int tmp;

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

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

281
            data[0] = (png_byte)z_cmf;
282 283
            tmp = data[1] & 0xe0;
            tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
284
            data[1] = (png_byte)tmp;
285 286
         }
      }
287 288
   }
}
289
#endif /* WRITE_OPTIMIZE_CMF */
290

291 292 293 294
/* Initialize the compressor for the appropriate type of compression. */
static int
png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
   png_alloc_size_t data_size)
295
{
296
   if (png_ptr->zowner != 0)
297
   {
298
#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
299
      char msg[64];
300

301 302 303 304 305 306 307 308 309
      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");
310
#endif
311
#if PNG_RELEASE_BUILD
312 313 314 315 316 317 318 319 320 321
         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;
322
#else
323
         png_error(png_ptr, msg);
324
#endif
325 326 327 328 329 330 331 332 333
   }

   {
      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 */
334

335
      if (owner == png_IDAT)
336
      {
337
         if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
338
            strategy = png_ptr->zlib_strategy;
339

340 341
         else if (png_ptr->do_filter != PNG_FILTER_NONE)
            strategy = PNG_Z_DEFAULT_STRATEGY;
342

343 344 345
         else
            strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
      }
346

347 348
      else
      {
349
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
350 351 352 353 354
            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;
355
#else
356 357 358 359 360 361
            /* 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;
362
#endif
363
      }
364

365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
      /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
       * 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!)
       */
      if (data_size <= 16384)
      {
         /* 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);

         while (data_size + 262 <= half_window_size)
         {
            half_window_size >>= 1;
            --windowBits;
385
         }
386
      }
387

388
      /* Check against the previous initialized values, if any. */
389
      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
390 391 392 393 394 395 396 397
         (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)");
398

399 400
         png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
      }
401

402 403 404 405 406 407 408
      /* 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;
409

410 411 412
      /* Now initialize if required, setting the new parameters, otherwise just
       * to a simple reset to the previous parameters.
       */
413
      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
414 415 416 417 418 419 420 421 422
         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;
423
      }
424 425 426 427 428 429 430 431 432 433 434

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

      else
         png_zstream_error(png_ptr, ret);

      return ret;
435
   }
436
}
437

438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
/* Clean up (or trim) a linked list of compression buffers. */
void /* PRIVATE */
png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
{
   png_compression_bufferp list = *listp;

   if (list != NULL)
   {
      *listp = NULL;

      do
      {
         png_compression_bufferp next = list->next;

         png_free(png_ptr, list);
         list = next;
      }
      while (list != NULL);
   }
457 458
}

459
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
460
/* This pair of functions encapsulates the operation of (a) compressing a
461 462
 * text string, and (b) issuing it later as a series of chunk data writes.
 * The compression_state structure is shared context for these functions
463 464 465 466 467 468
 * 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.)
469 470 471
 */
typedef struct
{
472 473 474 475
   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 */
476 477
} compression_state;

478 479 480
static void
png_text_compress_init(compression_state *comp, png_const_bytep input,
   png_alloc_size_t input_len)
481
{
482 483 484 485
   comp->input = input;
   comp->input_len = input_len;
   comp->output_len = 0;
}
486

487 488 489 490 491 492
/* 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;
493

494
   /* To find the length of the output it is necessary to first compress the
495
    * input. The result is buffered rather than using the two-pass algorithm
496 497
    * 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.
498
    *
499 500 501 502
    * 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.
503
    */
504
   ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
505

506 507
   if (ret != Z_OK)
      return ret;
508

509 510 511 512 513 514
   /* 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.
    */
515
   {
516 517 518
      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;
519

520 521 522 523 524
      /* 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);
525

526
      output_len = png_ptr->zstream.avail_out;
527

528
      do
529
      {
530
         uInt avail_in = ZLIB_IO_MAX;
531

532 533
         if (avail_in > input_len)
            avail_in = (uInt)input_len;
534

535
         input_len -= avail_in;
536

537
         png_ptr->zstream.avail_in = avail_in;
538

539 540 541
         if (png_ptr->zstream.avail_out == 0)
         {
            png_compression_buffer *next;
542

543 544 545 546 547 548 549
            /* 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;
550 551
            }

552 553 554 555 556
            /* Need a new (malloc'ed) buffer, but there may be one present
             * already.
             */
            next = *end;
            if (next == NULL)
557
            {
558 559
               next = png_voidcast(png_compression_bufferp, png_malloc_base
                  (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
560

561
               if (next == NULL)
562
               {
563 564
                  ret = Z_MEM_ERROR;
                  break;
565 566
               }

567 568 569
               /* Link in this buffer (so that it will be freed later) */
               next->next = NULL;
               *end = next;
570 571
            }

572 573 574
            png_ptr->zstream.next_out = next->output;
            png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
            output_len += png_ptr->zstream.avail_out;
575

576 577 578
            /* Move 'end' to the next buffer pointer. */
            end = &next->next;
         }
579

580 581 582
         /* Compress the data */
         ret = deflate(&png_ptr->zstream,
            input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
583

584 585 586 587 588
         /* 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 */
589
      }
590
      while (ret == Z_OK);
591

592
      /* There may be some space left in the last output buffer. This needs to
593 594 595 596 597 598 599 600 601 602 603 604 605 606
       * 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;
607 608
      }

609 610
      else
         png_zstream_error(png_ptr, ret);
611

612 613
      /* Reset zlib for another zTXt/iTXt or image data */
      png_ptr->zowner = 0;
614

615
      /* The only success case is Z_STREAM_END, input_len must be 0; if not this
616 617 618 619
       * is an internal error.
       */
      if (ret == Z_STREAM_END && input_len == 0)
      {
620
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
621 622
         /* Fix up the deflate header, if required */
         optimize_cmf(comp->output, comp->input_len);
623
#endif
624 625 626 627 628 629 630 631 632 633
         /* 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;
   }
634 635
}

636
/* Ship the compressed text out via chunk writes */
637
static void
638
png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
639
{
640 641 642 643
   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;
644

645
   for (;;)
646
   {
647 648
      if (avail > output_len)
         avail = output_len;
649

650
      png_write_chunk_data(png_ptr, output, avail);
651

652
      output_len -= avail;
653

654 655
      if (output_len == 0 || next == NULL)
         break;
656

657 658 659 660
      avail = png_ptr->zbuffer_size;
      output = next->output;
      next = next->next;
   }
661

662 663 664 665
   /* This is an internal error; 'next' must have been NULL! */
   if (output_len > 0)
      png_error(png_ptr, "error writing ancillary chunked compressed data");
}
666
#endif /* WRITE_COMPRESSED_TEXT */
667

668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
#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;
687

688
   png_debug(1, "in png_check_keyword");
689

690 691 692 693 694
   if (key == NULL)
   {
      *new_key = 0;
      return 0;
   }
695

696 697
   while (*key && key_len < 79)
   {
698
      png_byte ch = (png_byte)*key++;
699

700 701
      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
         *new_key++ = ch, ++key_len, space = 0;
702

703
      else if (space == 0)
704 705 706 707 708
      {
         /* A space or an invalid character when one wasn't seen immediately
          * before; output just a space.
          */
         *new_key++ = 32, ++key_len, space = 1;
709

710 711 712
         /* If the character was not a space then it is invalid. */
         if (ch != 32)
            bad_character = ch;
713 714
      }

715
      else if (bad_character == 0)
716
         bad_character = ch; /* just skip it, record the first error */
717 718
   }

719
   if (key_len > 0 && space != 0) /* trailing space */
720
   {
721
      --key_len, --new_key;
722
      if (bad_character == 0)
723
         bad_character = 32;
724
   }
725

726 727
   /* Terminate the keyword */
   *new_key = 0;
728

729 730 731
   if (key_len == 0)
      return 0;

732
#ifdef PNG_WARNINGS_SUPPORTED
733
   /* Try to only output one warning per keyword: */
734
   if (*key != 0) /* keyword too long */
735 736
      png_warning(png_ptr, "keyword truncated");

737
   else if (bad_character != 0)
738 739 740 741 742 743 744 745
   {
      PNG_WARNING_PARAMETERS(p)

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

      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
   }
746
#endif /* WARNINGS */
747

748
   return key_len;
749
}
750
#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */
751

G
Guy Schalnat 已提交
752
/* Write the IHDR chunk, and update the png_struct with the necessary
753 754 755
 * information.  Note that the rest of this code depends upon this
 * information being correct.
 */
756
void /* PRIVATE */
757
png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
758 759
    int bit_depth, int color_type, int compression_type, int filter_type,
    int interlace_type)
G
Guy Schalnat 已提交
760
{
761
   png_byte buf[13]; /* Buffer to store the IHDR info */
G
Guy Schalnat 已提交
762

763
   png_debug(1, "in png_write_IHDR");
764

G
Guy Schalnat 已提交
765
   /* Check that we have valid input data from the application info */
G
Guy Schalnat 已提交
766 767
   switch (color_type)
   {
A
Andreas Dilger 已提交
768
      case PNG_COLOR_TYPE_GRAY:
G
Guy Schalnat 已提交
769 770 771 772 773 774
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
            case 8:
775
#ifdef PNG_WRITE_16BIT_SUPPORTED
776
            case 16:
777
#endif
778
               png_ptr->channels = 1; break;
779

780 781 782
            default:
               png_error(png_ptr,
                   "Invalid bit depth for grayscale image");
G
Guy Schalnat 已提交
783
         }
G
Guy Schalnat 已提交
784
         break;
785

A
Andreas Dilger 已提交
786
      case PNG_COLOR_TYPE_RGB:
787
#ifdef PNG_WRITE_16BIT_SUPPORTED
G
Guy Schalnat 已提交
788
         if (bit_depth != 8 && bit_depth != 16)
789 790 791
#else
         if (bit_depth != 8)
#endif
G
Guy Schalnat 已提交
792
            png_error(png_ptr, "Invalid bit depth for RGB image");
793

G
Guy Schalnat 已提交
794 795
         png_ptr->channels = 3;
         break;
796

A
Andreas Dilger 已提交
797
      case PNG_COLOR_TYPE_PALETTE:
G
Guy Schalnat 已提交
798 799 800 801 802
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
803 804 805
            case 8:
               png_ptr->channels = 1;
               break;
806

807 808
            default:
               png_error(png_ptr, "Invalid bit depth for paletted image");
G
Guy Schalnat 已提交
809 810
         }
         break;
811

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

G
Guy Schalnat 已提交
816 817
         png_ptr->channels = 2;
         break;
818

A
Andreas Dilger 已提交
819
      case PNG_COLOR_TYPE_RGB_ALPHA:
820
#ifdef PNG_WRITE_16BIT_SUPPORTED
G
Guy Schalnat 已提交
821
         if (bit_depth != 8 && bit_depth != 16)
822 823 824
#else
         if (bit_depth != 8)
#endif
G
Guy Schalnat 已提交
825
            png_error(png_ptr, "Invalid bit depth for RGBA image");
826

G
Guy Schalnat 已提交
827 828
         png_ptr->channels = 4;
         break;
829

G
Guy Schalnat 已提交
830 831 832 833
      default:
         png_error(png_ptr, "Invalid image color type specified");
   }

A
Andreas Dilger 已提交
834
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
G
Guy Schalnat 已提交
835 836
   {
      png_warning(png_ptr, "Invalid compression type specified");
A
Andreas Dilger 已提交
837
      compression_type = PNG_COMPRESSION_TYPE_BASE;
G
Guy Schalnat 已提交
838 839
   }

840 841 842 843 844 845 846 847 848
   /* 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
    */
849
   if (
850
#ifdef PNG_MNG_FEATURES_SUPPORTED
851 852
       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
       ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
853 854 855
       (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
856
#endif
857
       filter_type != PNG_FILTER_TYPE_BASE)
G
Guy Schalnat 已提交
858 859
   {
      png_warning(png_ptr, "Invalid filter type specified");
A
Andreas Dilger 已提交
860
      filter_type = PNG_FILTER_TYPE_BASE;
G
Guy Schalnat 已提交
861 862
   }

863
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
A
Andreas Dilger 已提交
864
   if (interlace_type != PNG_INTERLACE_NONE &&
865
       interlace_type != PNG_INTERLACE_ADAM7)
G
Guy Schalnat 已提交
866 867
   {
      png_warning(png_ptr, "Invalid interlace type specified");
A
Andreas Dilger 已提交
868
      interlace_type = PNG_INTERLACE_ADAM7;
G
Guy Schalnat 已提交
869
   }
870 871 872
#else
   interlace_type=PNG_INTERLACE_NONE;
#endif
G
Guy Schalnat 已提交
873

874
   /* Save the relevant information */
875 876 877
   png_ptr->bit_depth = (png_byte)bit_depth;
   png_ptr->color_type = (png_byte)color_type;
   png_ptr->interlaced = (png_byte)interlace_type;
878
#ifdef PNG_MNG_FEATURES_SUPPORTED
879
   png_ptr->filter_type = (png_byte)filter_type;
880
#endif
881
   png_ptr->compression_type = (png_byte)compression_type;
G
Guy Schalnat 已提交
882 883 884
   png_ptr->width = width;
   png_ptr->height = height;

885
   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
886
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
887
   /* Set the usr info, so any transformations can modify it */
G
Guy Schalnat 已提交
888 889
   png_ptr->usr_width = png_ptr->width;
   png_ptr->usr_bit_depth = png_ptr->bit_depth;
G
Guy Schalnat 已提交
890 891
   png_ptr->usr_channels = png_ptr->channels;

892
   /* Pack the header information into the buffer */
G
Guy Schalnat 已提交
893 894
   png_save_uint_32(buf, width);
   png_save_uint_32(buf + 4, height);
895 896 897 898 899
   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 已提交
900

901
   /* Write the chunk */
902
   png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
G
Guy Schalnat 已提交
903

904
   if ((png_ptr->do_filter) == PNG_NO_FILTERS)
G
Guy Schalnat 已提交
905
   {
A
Andreas Dilger 已提交
906
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
907
          png_ptr->bit_depth < 8)
G
Guy Schalnat 已提交
908
         png_ptr->do_filter = PNG_FILTER_NONE;
909

G
Guy Schalnat 已提交
910
      else
G
Guy Schalnat 已提交
911
         png_ptr->do_filter = PNG_ALL_FILTERS;
G
Guy Schalnat 已提交
912
   }
913

914
   png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
G
Guy Schalnat 已提交
915 916
}

917
/* Write the palette.  We are careful not to trust png_color to be in the
918
 * correct order for PNG, so people can redefine it to any convenient
919 920
 * structure.
 */
921
void /* PRIVATE */
922
png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
923
    png_uint_32 num_pal)
G
Guy Schalnat 已提交
924
{
A
Andreas Dilger 已提交
925
   png_uint_32 i;
926
   png_const_colorp pal_ptr;
G
Guy Schalnat 已提交
927 928
   png_byte buf[3];

929
   png_debug(1, "in png_write_PLTE");
930

931
   if ((
932
#ifdef PNG_MNG_FEATURES_SUPPORTED
933
       (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
934
#endif
935
       num_pal == 0) || num_pal > 256)
936
   {
937 938 939 940
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_error(png_ptr, "Invalid number of colors in palette");
      }
941

942 943 944 945 946
      else
      {
         png_warning(png_ptr, "Invalid number of colors in palette");
         return;
      }
947 948
   }

949
   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
950 951
   {
      png_warning(png_ptr,
952
          "Ignoring request to write a PLTE chunk in grayscale PNG");
953

954
      return;
G
Guy Schalnat 已提交
955 956
   }

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

960
   png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
961
#ifdef PNG_POINTER_INDEXING_SUPPORTED
962

A
Andreas Dilger 已提交
963
   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
G
Guy Schalnat 已提交
964 965 966 967
   {
      buf[0] = pal_ptr->red;
      buf[1] = pal_ptr->green;
      buf[2] = pal_ptr->blue;
968
      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
G
Guy Schalnat 已提交
969
   }
970

971
#else
972 973 974
   /* This is a little slower but some buggy compilers need to do this
    * instead
    */
975
   pal_ptr=palette;
976

977 978 979 980 981
   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;
982
      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
983
   }
984

985
#endif
G
Guy Schalnat 已提交
986
   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
987
   png_ptr->mode |= PNG_HAVE_PLTE;
G
Guy Schalnat 已提交
988 989
}

990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
/* 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
1004
 * checking and (at the end) clearing png_ptr->zowner; it does some sanity
1005 1006
 * checks on the 'mode' flags while doing this.
 */
1007
void /* PRIVATE */
1008 1009
png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
   png_alloc_size_t input_len, int flush)
G
Guy Schalnat 已提交
1010
{
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
   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 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
       * created at this point, but the check here is quick and safe.
       */
      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;
      }
1024

1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
      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 (;;)
1046
   {
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
      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;

1064
      /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
1065 1066
       * that these two zstream fields are preserved across the calls, therefore
       * there is no need to set these up on entry to the loop.
1067
       */
1068 1069 1070 1071
      if (png_ptr->zstream.avail_out == 0)
      {
         png_bytep data = png_ptr->zbuffer_list->output;
         uInt size = png_ptr->zbuffer_size;
1072

1073 1074 1075
         /* Write an IDAT containing the data then reset the buffer.  The
          * first IDAT may need deflate header optimization.
          */
1076 1077 1078
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
            if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
                png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
1079
               optimize_cmf(data, png_image_size(png_ptr));
1080
#endif
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095

         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;
      }

1096
      /* The order of these checks doesn't matter much; it just affects which
1097 1098 1099
       * possible error might be detected if multiple things go wrong at once.
       */
      if (ret == Z_OK) /* most likely return code! */
1100
      {
1101 1102 1103
         /* 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.
1104
          */
1105
         if (input_len == 0)
1106
         {
1107 1108
            if (flush == Z_FINISH)
               png_error(png_ptr, "Z_OK on Z_FINISH with output space");
1109

1110 1111 1112
            return;
         }
      }
1113

1114 1115 1116 1117 1118 1119 1120
      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;
1121

1122 1123 1124 1125 1126
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
         if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
             png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
            optimize_cmf(data, png_image_size(png_ptr));
#endif
1127

1128 1129 1130 1131
         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;
1132

1133 1134
         png_ptr->zowner = 0; /* Release the stream */
         return;
1135
      }
1136

1137
      else
1138 1139 1140 1141 1142
      {
         /* This is an error condition. */
         png_zstream_error(png_ptr, ret);
         png_error(png_ptr, png_ptr->zstream.msg);
      }
1143
   }
G
Guy Schalnat 已提交
1144 1145
}

1146
/* Write an IEND chunk */
1147
void /* PRIVATE */
1148
png_write_IEND(png_structrp png_ptr)
G
Guy Schalnat 已提交
1149
{
1150
   png_debug(1, "in png_write_IEND");
1151

1152
   png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
A
Andreas Dilger 已提交
1153
   png_ptr->mode |= PNG_HAVE_IEND;
G
Guy Schalnat 已提交
1154 1155
}

1156
#ifdef PNG_WRITE_gAMA_SUPPORTED
1157
/* Write a gAMA chunk */
1158
void /* PRIVATE */
1159
png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
1160 1161 1162
{
   png_byte buf[4];

1163
   png_debug(1, "in png_write_gAMA");
1164

1165
   /* file_gamma is saved in 1/100,000ths */
1166
   png_save_uint_32(buf, (png_uint_32)file_gamma);
1167
   png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
1168 1169
}
#endif
G
Guy Schalnat 已提交
1170

1171
#ifdef PNG_WRITE_sRGB_SUPPORTED
1172
/* Write a sRGB chunk */
1173
void /* PRIVATE */
1174
png_write_sRGB(png_structrp png_ptr, int srgb_intent)
1175 1176 1177
{
   png_byte buf[1];

1178
   png_debug(1, "in png_write_sRGB");
1179

1180
   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1181 1182
      png_warning(png_ptr,
          "Invalid sRGB rendering intent specified");
1183

1184
   buf[0]=(png_byte)srgb_intent;
1185
   png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
1186 1187 1188
}
#endif

1189
#ifdef PNG_WRITE_iCCP_SUPPORTED
1190
/* Write an iCCP chunk */
1191
void /* PRIVATE */
1192 1193
png_write_iCCP(png_structrp png_ptr, png_const_charp name,
    png_const_bytep profile)
1194
{
1195 1196 1197
   png_uint_32 name_len;
   png_uint_32 profile_len;
   png_byte new_name[81]; /* 1 byte for the compression byte */
1198
   compression_state comp;
1199
   png_uint_32 temp;
1200

1201
   png_debug(1, "in png_write_iCCP");
1202

1203 1204 1205
   /* These are all internal problems: the profile should have been checked
    * before when it was stored.
    */
1206
   if (profile == NULL)
1207
      png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
1208

1209
   profile_len = png_get_uint_32(profile);
1210

1211 1212
   if (profile_len < 132)
      png_error(png_ptr, "ICC profile too short");
1213

1214 1215
   temp = (png_uint_32) (*(profile+8));
   if (temp > 3 && (profile_len & 0x03))
1216
      png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
1217

1218
   {
1219
      png_uint_32 embedded_profile_len = png_get_uint_32(profile);
1220

1221 1222
      if (profile_len != embedded_profile_len)
         png_error(png_ptr, "Profile length does not match profile");
1223
   }
1224

1225
   name_len = png_check_keyword(png_ptr, name, new_name);
1226

1227 1228
   if (name_len == 0)
      png_error(png_ptr, "iCCP: invalid keyword");
1229

1230
   new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
1231

1232
   /* Make sure we include the NULL after the name and the compression type */
1233
   ++name_len;
1234

1235
   png_text_compress_init(&comp, profile, profile_len);
1236

1237 1238 1239
   /* 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);
1240

1241 1242 1243 1244 1245
   png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);

   png_write_chunk_data(png_ptr, new_name, name_len);

   png_write_compressed_data_out(png_ptr, &comp);
1246 1247 1248 1249 1250

   png_write_chunk_end(png_ptr);
}
#endif

1251
#ifdef PNG_WRITE_sPLT_SUPPORTED
1252
/* Write a sPLT chunk */
1253
void /* PRIVATE */
1254
png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
1255
{
1256 1257
   png_uint_32 name_len;
   png_byte new_name[80];
1258
   png_byte entrybuf[10];
1259 1260
   png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
   png_size_t palette_size = entry_size * spalette->nentries;
1261
   png_sPLT_entryp ep;
1262
#ifndef PNG_POINTER_INDEXING_SUPPORTED
1263 1264
   int i;
#endif
1265

1266
   png_debug(1, "in png_write_sPLT");
1267

1268 1269 1270 1271
   name_len = png_check_keyword(png_ptr, spalette->name, new_name);

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

1273
   /* Make sure we include the NULL after the name */
1274
   png_write_chunk_header(png_ptr, png_sPLT,
1275
       (png_uint_32)(name_len + 2 + palette_size));
1276

1277
   png_write_chunk_data(png_ptr, (png_bytep)new_name,
1278
       (png_size_t)(name_len + 1));
1279

1280
   png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
1281

1282
   /* Loop through each palette entry, writing appropriately */
1283
#ifdef PNG_POINTER_INDEXING_SUPPORTED
1284
   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1285
   {
1286 1287
      if (spalette->depth == 8)
      {
1288 1289 1290 1291
         entrybuf[0] = (png_byte)ep->red;
         entrybuf[1] = (png_byte)ep->green;
         entrybuf[2] = (png_byte)ep->blue;
         entrybuf[3] = (png_byte)ep->alpha;
1292
         png_save_uint_16(entrybuf + 4, ep->frequency);
1293
      }
1294

1295 1296
      else
      {
1297 1298 1299 1300 1301
         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);
1302
      }
1303

1304
      png_write_chunk_data(png_ptr, entrybuf, entry_size);
1305
   }
1306 1307
#else
   ep=spalette->entries;
1308
   for (i = 0; i>spalette->nentries; i++)
1309
   {
1310 1311
      if (spalette->depth == 8)
      {
1312 1313 1314 1315
         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;
1316
         png_save_uint_16(entrybuf + 4, ep[i].frequency);
1317
      }
1318

1319 1320
      else
      {
1321 1322 1323 1324 1325
         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);
1326
      }
1327

1328
      png_write_chunk_data(png_ptr, entrybuf, entry_size);
1329 1330
   }
#endif
1331 1332 1333 1334 1335

   png_write_chunk_end(png_ptr);
}
#endif

1336
#ifdef PNG_WRITE_sBIT_SUPPORTED
1337
/* Write the sBIT chunk */
1338
void /* PRIVATE */
1339
png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
G
Guy Schalnat 已提交
1340 1341
{
   png_byte buf[4];
A
Andreas Dilger 已提交
1342
   png_size_t size;
G
Guy Schalnat 已提交
1343

1344
   png_debug(1, "in png_write_sBIT");
1345

1346
   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
1347
   if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
1348
   {
1349
      png_byte maxbits;
G
Guy Schalnat 已提交
1350

1351 1352
      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
          png_ptr->usr_bit_depth);
1353

1354 1355
      if (sbit->red == 0 || sbit->red > maxbits ||
          sbit->green == 0 || sbit->green > maxbits ||
G
Guy Schalnat 已提交
1356 1357 1358 1359 1360
          sbit->blue == 0 || sbit->blue > maxbits)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1361

G
Guy Schalnat 已提交
1362 1363 1364 1365 1366
      buf[0] = sbit->red;
      buf[1] = sbit->green;
      buf[2] = sbit->blue;
      size = 3;
   }
1367

G
Guy Schalnat 已提交
1368 1369
   else
   {
G
Guy Schalnat 已提交
1370 1371 1372 1373 1374
      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1375

G
Guy Schalnat 已提交
1376 1377 1378 1379
      buf[0] = sbit->gray;
      size = 1;
   }

1380
   if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
G
Guy Schalnat 已提交
1381
   {
G
Guy Schalnat 已提交
1382 1383 1384 1385 1386
      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1387

G
Guy Schalnat 已提交
1388 1389 1390
      buf[size++] = sbit->alpha;
   }

1391
   png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
G
Guy Schalnat 已提交
1392
}
G
Guy Schalnat 已提交
1393
#endif
G
Guy Schalnat 已提交
1394

1395
#ifdef PNG_WRITE_cHRM_SUPPORTED
1396
/* Write the cHRM chunk */
1397
void /* PRIVATE */
1398
png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
1399 1400 1401
{
   png_byte buf[32];

1402
   png_debug(1, "in png_write_cHRM");
1403

1404
   /* Each value is saved in 1/100,000ths */
1405 1406
   png_save_int_32(buf,      xy->whitex);
   png_save_int_32(buf +  4, xy->whitey);
1407

1408 1409
   png_save_int_32(buf +  8, xy->redx);
   png_save_int_32(buf + 12, xy->redy);
1410

1411 1412
   png_save_int_32(buf + 16, xy->greenx);
   png_save_int_32(buf + 20, xy->greeny);
1413

1414 1415
   png_save_int_32(buf + 24, xy->bluex);
   png_save_int_32(buf + 28, xy->bluey);
1416

1417
   png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
1418 1419
}
#endif
G
Guy Schalnat 已提交
1420

1421
#ifdef PNG_WRITE_tRNS_SUPPORTED
1422
/* Write the tRNS chunk */
1423
void /* PRIVATE */
1424
png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
1425
    png_const_color_16p tran, int num_trans, int color_type)
G
Guy Schalnat 已提交
1426 1427 1428
{
   png_byte buf[6];

1429
   png_debug(1, "in png_write_tRNS");
1430

G
Guy Schalnat 已提交
1431 1432
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1433
      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1434
      {
1435 1436
         png_app_warning(png_ptr,
             "Invalid number of transparent colors specified");
G
Guy Schalnat 已提交
1437 1438
         return;
      }
1439

1440
      /* Write the chunk out as it is */
1441 1442
      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
         (png_size_t)num_trans);
G
Guy Schalnat 已提交
1443
   }
1444

G
Guy Schalnat 已提交
1445 1446
   else if (color_type == PNG_COLOR_TYPE_GRAY)
   {
1447
      /* One 16 bit value */
1448
      if (tran->gray >= (1 << png_ptr->bit_depth))
1449
      {
1450
         png_app_warning(png_ptr,
1451
             "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1452

1453 1454
         return;
      }
1455

G
Guy Schalnat 已提交
1456
      png_save_uint_16(buf, tran->gray);
1457
      png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1458
   }
1459

G
Guy Schalnat 已提交
1460 1461
   else if (color_type == PNG_COLOR_TYPE_RGB)
   {
1462
      /* Three 16 bit values */
G
Guy Schalnat 已提交
1463 1464 1465
      png_save_uint_16(buf, tran->red);
      png_save_uint_16(buf + 2, tran->green);
      png_save_uint_16(buf + 4, tran->blue);
1466
#ifdef PNG_WRITE_16BIT_SUPPORTED
1467
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1468
#else
1469
      if ((buf[0] | buf[2] | buf[4]) != 0)
1470
#endif
1471
      {
1472
         png_app_warning(png_ptr,
1473
           "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1474 1475
         return;
      }
1476

1477
      png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
G
Guy Schalnat 已提交
1478
   }
1479

G
Guy Schalnat 已提交
1480 1481
   else
   {
1482
      png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
G
Guy Schalnat 已提交
1483
   }
G
Guy Schalnat 已提交
1484
}
G
Guy Schalnat 已提交
1485
#endif
G
Guy Schalnat 已提交
1486

1487
#ifdef PNG_WRITE_bKGD_SUPPORTED
1488
/* Write the background chunk */
1489
void /* PRIVATE */
1490
png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
G
Guy Schalnat 已提交
1491 1492 1493
{
   png_byte buf[6];

1494
   png_debug(1, "in png_write_bKGD");
1495

G
Guy Schalnat 已提交
1496 1497
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1498
      if (
1499
#ifdef PNG_MNG_FEATURES_SUPPORTED
1500 1501
          (png_ptr->num_palette != 0 ||
          (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
1502
#endif
1503
         back->index >= png_ptr->num_palette)
G
Guy Schalnat 已提交
1504 1505 1506 1507
      {
         png_warning(png_ptr, "Invalid background palette index");
         return;
      }
1508

G
Guy Schalnat 已提交
1509
      buf[0] = back->index;
1510
      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
G
Guy Schalnat 已提交
1511
   }
1512

1513
   else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
1514 1515 1516 1517
   {
      png_save_uint_16(buf, back->red);
      png_save_uint_16(buf + 2, back->green);
      png_save_uint_16(buf + 4, back->blue);
1518
#ifdef PNG_WRITE_16BIT_SUPPORTED
1519
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1520
#else
1521
      if ((buf[0] | buf[2] | buf[4]) != 0)
1522
#endif
1523 1524
      {
         png_warning(png_ptr,
1525
             "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
1526

1527 1528
         return;
      }
1529

1530
      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
G
Guy Schalnat 已提交
1531
   }
1532

G
Guy Schalnat 已提交
1533
   else
G
Guy Schalnat 已提交
1534
   {
1535
      if (back->gray >= (1 << png_ptr->bit_depth))
1536 1537
      {
         png_warning(png_ptr,
1538
             "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1539

1540 1541
         return;
      }
1542

G
Guy Schalnat 已提交
1543
      png_save_uint_16(buf, back->gray);
1544
      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1545 1546
   }
}
G
Guy Schalnat 已提交
1547
#endif
G
Guy Schalnat 已提交
1548

1549
#ifdef PNG_WRITE_hIST_SUPPORTED
1550
/* Write the histogram */
1551
void /* PRIVATE */
1552
png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
G
Guy Schalnat 已提交
1553
{
1554
   int i;
G
Guy Schalnat 已提交
1555 1556
   png_byte buf[3];

1557
   png_debug(1, "in png_write_hIST");
1558

1559
   if (num_hist > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1560
   {
1561
      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1562
          png_ptr->num_palette);
1563

G
Guy Schalnat 已提交
1564 1565 1566 1567
      png_warning(png_ptr, "Invalid number of histogram entries specified");
      return;
   }

1568
   png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1569

A
Andreas Dilger 已提交
1570
   for (i = 0; i < num_hist; i++)
G
Guy Schalnat 已提交
1571
   {
G
Guy Schalnat 已提交
1572
      png_save_uint_16(buf, hist[i]);
1573
      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1574
   }
1575

G
Guy Schalnat 已提交
1576 1577
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1578
#endif
G
Guy Schalnat 已提交
1579

1580
#ifdef PNG_WRITE_tEXt_SUPPORTED
1581
/* Write a tEXt chunk */
1582
void /* PRIVATE */
1583
png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1584
    png_size_t text_len)
G
Guy Schalnat 已提交
1585
{
1586 1587
   png_uint_32 key_len;
   png_byte new_key[80];
A
Andreas Dilger 已提交
1588

1589
   png_debug(1, "in png_write_tEXt");
1590

1591 1592 1593 1594
   key_len = png_check_keyword(png_ptr, key, new_key);

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

A
Andreas Dilger 已提交
1596
   if (text == NULL || *text == '\0')
A
Andreas Dilger 已提交
1597
      text_len = 0;
1598

1599
   else
1600 1601 1602 1603
      text_len = strlen(text);

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

1605
   /* Make sure we include the 0 after the key */
1606
   png_write_chunk_header(png_ptr, png_tEXt,
1607
       (png_uint_32)/*checked above*/(key_len + text_len + 1));
1608 1609 1610 1611
   /*
    * 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.
1612
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1613
    */
1614
   png_write_chunk_data(png_ptr, new_key, key_len + 1);
1615

1616
   if (text_len != 0)
1617
      png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
A
Andreas Dilger 已提交
1618

G
Guy Schalnat 已提交
1619 1620
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1621
#endif
G
Guy Schalnat 已提交
1622

1623
#ifdef PNG_WRITE_zTXt_SUPPORTED
1624
/* Write a compressed text chunk */
1625
void /* PRIVATE */
1626
png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1627
    int compression)
G
Guy Schalnat 已提交
1628
{
1629 1630
   png_uint_32 key_len;
   png_byte new_key[81];
1631
   compression_state comp;
G
Guy Schalnat 已提交
1632

1633
   png_debug(1, "in png_write_zTXt");
A
Andreas Dilger 已提交
1634

1635
   if (compression == PNG_TEXT_COMPRESSION_NONE)
A
Andreas Dilger 已提交
1636
   {
1637
      png_write_tEXt(png_ptr, key, text, 0);
G
Guy Schalnat 已提交
1638
      return;
A
Andreas Dilger 已提交
1639
   }
A
Andreas Dilger 已提交
1640

1641 1642
   if (compression != PNG_TEXT_COMPRESSION_zTXt)
      png_error(png_ptr, "zTXt: invalid compression type");
G
Guy Schalnat 已提交
1643

1644
   key_len = png_check_keyword(png_ptr, key, new_key);
1645

1646 1647
   if (key_len == 0)
      png_error(png_ptr, "zTXt: invalid keyword");
1648

1649 1650 1651
   /* Add the compression method and 1 for the keyword separator. */
   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
   ++key_len;
1652

1653 1654 1655
   /* Compute the compressed data; do it now for the length */
   png_text_compress_init(&comp, (png_const_bytep)text,
      text == NULL ? 0 : strlen(text));
1656

1657 1658
   if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
      png_error(png_ptr, png_ptr->zstream.msg);
1659

1660 1661
   /* Write start of chunk */
   png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
1662

1663 1664
   /* Write key */
   png_write_chunk_data(png_ptr, new_key, key_len);
1665

1666
   /* Write the compressed data */
1667
   png_write_compressed_data_out(png_ptr, &comp);
G
Guy Schalnat 已提交
1668

1669
   /* Close the chunk */
1670 1671 1672
   png_write_chunk_end(png_ptr);
}
#endif
G
Guy Schalnat 已提交
1673

1674
#ifdef PNG_WRITE_iTXt_SUPPORTED
1675
/* Write an iTXt chunk */
1676
void /* PRIVATE */
1677
png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
1678
    png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1679
{
1680 1681 1682
   png_uint_32 key_len, prefix_len;
   png_size_t lang_len, lang_key_len;
   png_byte new_key[82];
1683
   compression_state comp;
G
Guy Schalnat 已提交
1684

1685
   png_debug(1, "in png_write_iTXt");
G
Guy Schalnat 已提交
1686

1687
   key_len = png_check_keyword(png_ptr, key, new_key);
1688

1689 1690
   if (key_len == 0)
      png_error(png_ptr, "iTXt: invalid keyword");
1691

1692 1693
   /* Set the compression flag */
   switch (compression)
1694
   {
1695 1696 1697 1698
      case PNG_ITXT_COMPRESSION_NONE:
      case PNG_TEXT_COMPRESSION_NONE:
         compression = new_key[++key_len] = 0; /* no compression */
         break;
1699

1700 1701 1702 1703
      case PNG_TEXT_COMPRESSION_zTXt:
      case PNG_ITXT_COMPRESSION_zTXt:
         compression = new_key[++key_len] = 1; /* compressed */
         break;
1704

1705 1706 1707
      default:
         png_error(png_ptr, "iTXt: invalid compression");
   }
1708

1709 1710
   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
   ++key_len; /* for the keywod separator */
1711

1712 1713
   /* 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
1714 1715 1716 1717
    * 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.
    *
1718
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1719 1720
    *
    * TODO: validate the language tag correctly (see the spec.)
1721
    */
1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732
   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);
1733

1734 1735 1736 1737
   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);
G
Guy Schalnat 已提交
1738

1739
   png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
1740

1741
   if (compression != 0)
1742 1743 1744 1745
   {
      if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
         png_error(png_ptr, png_ptr->zstream.msg);
   }
1746

1747 1748 1749 1750
   else
   {
      if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
         png_error(png_ptr, "iTXt: uncompressed text too long");
1751 1752 1753

      /* So the string will fit in a chunk: */
      comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
1754
   }
1755

1756 1757
   png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);

1758
   png_write_chunk_data(png_ptr, new_key, key_len);
1759

1760
   png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
1761

1762
   png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
1763

1764
   if (compression != 0)
1765 1766 1767
      png_write_compressed_data_out(png_ptr, &comp);

   else
1768
      png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
1769 1770

   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
1771
}
G
Guy Schalnat 已提交
1772
#endif
G
Guy Schalnat 已提交
1773

1774
#ifdef PNG_WRITE_oFFs_SUPPORTED
1775
/* Write the oFFs chunk */
1776
void /* PRIVATE */
1777
png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1778
    int unit_type)
G
Guy Schalnat 已提交
1779 1780 1781
{
   png_byte buf[9];

1782
   png_debug(1, "in png_write_oFFs");
1783

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

1787 1788
   png_save_int_32(buf, x_offset);
   png_save_int_32(buf + 4, y_offset);
1789
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1790

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

1808
   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1809

A
Andreas Dilger 已提交
1810
   if (type >= PNG_EQUATION_LAST)
1811 1812 1813 1814 1815 1816 1817 1818
      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 已提交
1819

1820
   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
1821
   units_len = strlen(units) + (nparams == 0 ? 0 : 1);
1822
   png_debug1(3, "pCAL units length = %d", (int)units_len);
A
Andreas Dilger 已提交
1823 1824
   total_len = purpose_len + units_len + 10;

1825
   params_len = (png_size_tp)png_malloc(png_ptr,
1826
       (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
A
Andreas Dilger 已提交
1827 1828

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

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

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

1854
   png_free(png_ptr, params_len);
A
Andreas Dilger 已提交
1855 1856 1857 1858
   png_write_chunk_end(png_ptr);
}
#endif

1859
#ifdef PNG_WRITE_sCAL_SUPPORTED
1860
/* Write the sCAL chunk */
1861
void /* PRIVATE */
1862
png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
1863
    png_const_charp height)
1864
{
1865 1866
   png_byte buf[64];
   png_size_t wlen, hlen, total_len;
1867

1868
   png_debug(1, "in png_write_sCAL_s");
1869

1870 1871
   wlen = strlen(width);
   hlen = strlen(height);
1872
   total_len = wlen + hlen + 2;
1873

1874 1875 1876 1877 1878
   if (total_len > 64)
   {
      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
      return;
   }
1879

1880
   buf[0] = (png_byte)unit;
1881 1882
   memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
   memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
1883

1884
   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1885
   png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1886 1887 1888
}
#endif

1889
#ifdef PNG_WRITE_pHYs_SUPPORTED
1890
/* Write the pHYs chunk */
1891
void /* PRIVATE */
1892
png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
1893 1894
    png_uint_32 y_pixels_per_unit,
    int unit_type)
G
Guy Schalnat 已提交
1895 1896 1897
{
   png_byte buf[9];

1898
   png_debug(1, "in png_write_pHYs");
1899

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

A
Andreas Dilger 已提交
1903 1904
   png_save_uint_32(buf, x_pixels_per_unit);
   png_save_uint_32(buf + 4, y_pixels_per_unit);
1905
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1906

1907
   png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
G
Guy Schalnat 已提交
1908
}
G
Guy Schalnat 已提交
1909
#endif
G
Guy Schalnat 已提交
1910

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

1920
   png_debug(1, "in png_write_tIME");
1921

G
Guy Schalnat 已提交
1922 1923 1924 1925 1926 1927 1928 1929
   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 已提交
1930 1931 1932 1933 1934 1935 1936
   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;

1937
   png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
G
Guy Schalnat 已提交
1938
}
G
Guy Schalnat 已提交
1939
#endif
G
Guy Schalnat 已提交
1940

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

1948
   /* Start of interlace block */
1949
   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1950

1951
   /* Offset to next interlace block */
1952
   static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1953

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

1957
   /* Offset to next interlace block in the y direction */
1958
   static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1959
#endif
1960

1961 1962
   png_alloc_size_t buf_size;
   int usr_pixel_depth;
A
Andreas Dilger 已提交
1963

1964
   png_debug(1, "in png_write_start_row");
1965

1966 1967 1968 1969 1970
   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;
1971
   png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
A
Andreas Dilger 已提交
1972

1973
   /* Set up row buffer */
1974
   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
1975

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

1978
#ifdef PNG_WRITE_FILTER_SUPPORTED
1979
   /* Set up filtering buffer, if using this filter */
G
Guy Schalnat 已提交
1980
   if (png_ptr->do_filter & PNG_FILTER_SUB)
G
Guy Schalnat 已提交
1981
   {
1982
      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
1983

A
Andreas Dilger 已提交
1984
      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
G
Guy Schalnat 已提交
1985 1986
   }

A
Andreas Dilger 已提交
1987
   /* We only need to keep the previous row if we are using one of these. */
1988 1989
   if ((png_ptr->do_filter &
      (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
G
Guy Schalnat 已提交
1990
   {
1991
      /* Set up previous row buffer */
1992
      png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
G
Guy Schalnat 已提交
1993

1994
      if ((png_ptr->do_filter & PNG_FILTER_UP) != 0)
G
Guy Schalnat 已提交
1995
      {
1996
         png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
1997
            png_ptr->rowbytes + 1);
1998

A
Andreas Dilger 已提交
1999
         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
G
Guy Schalnat 已提交
2000 2001
      }

2002
      if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0)
G
Guy Schalnat 已提交
2003
      {
2004
         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
2005
             png_ptr->rowbytes + 1);
2006

A
Andreas Dilger 已提交
2007
         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
G
Guy Schalnat 已提交
2008 2009
      }

2010
      if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0)
G
Guy Schalnat 已提交
2011
      {
2012
         png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
2013
             png_ptr->rowbytes + 1);
2014

A
Andreas Dilger 已提交
2015
         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
G
Guy Schalnat 已提交
2016
      }
G
Guy Schalnat 已提交
2017
   }
2018
#endif /* WRITE_FILTER */
G
Guy Schalnat 已提交
2019

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

A
Andreas Dilger 已提交
2029
         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2030
             png_pass_start[0]) / png_pass_inc[0];
G
Guy Schalnat 已提交
2031
      }
2032

G
Guy Schalnat 已提交
2033 2034 2035 2036 2037 2038
      else
      {
         png_ptr->num_rows = png_ptr->height;
         png_ptr->usr_width = png_ptr->width;
      }
   }
2039

G
Guy Schalnat 已提交
2040
   else
2041
#endif
G
Guy Schalnat 已提交
2042
   {
G
Guy Schalnat 已提交
2043 2044 2045 2046 2047
      png_ptr->num_rows = png_ptr->height;
      png_ptr->usr_width = png_ptr->width;
   }
}

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

2055
   /* Start of interlace block */
2056
   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2057

2058
   /* Offset to next interlace block */
2059
   static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2060

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

2064
   /* Offset to next interlace block in the y direction */
2065
   static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2066
#endif
2067

2068
   png_debug(1, "in png_write_finish_row");
2069

2070
   /* Next row */
G
Guy Schalnat 已提交
2071
   png_ptr->row_number++;
G
Guy Schalnat 已提交
2072

2073
   /* See if we are done */
G
Guy Schalnat 已提交
2074
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
2075
      return;
G
Guy Schalnat 已提交
2076

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

G
Guy Schalnat 已提交
2087 2088
      else
      {
2089
         /* Loop until we find a non-zero width or height pass */
G
Guy Schalnat 已提交
2090 2091 2092
         do
         {
            png_ptr->pass++;
2093

G
Guy Schalnat 已提交
2094 2095
            if (png_ptr->pass >= 7)
               break;
2096

G
Guy Schalnat 已提交
2097
            png_ptr->usr_width = (png_ptr->width +
2098 2099 2100
                png_pass_inc[png_ptr->pass] - 1 -
                png_pass_start[png_ptr->pass]) /
                png_pass_inc[png_ptr->pass];
2101

G
Guy Schalnat 已提交
2102
            png_ptr->num_rows = (png_ptr->height +
2103 2104 2105
                png_pass_yinc[png_ptr->pass] - 1 -
                png_pass_ystart[png_ptr->pass]) /
                png_pass_yinc[png_ptr->pass];
2106

2107
            if ((png_ptr->transformations & PNG_INTERLACE) != 0)
G
Guy Schalnat 已提交
2108
               break;
2109

G
Guy Schalnat 已提交
2110 2111 2112 2113
         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);

      }

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

G
Guy Schalnat 已提交
2122
         return;
G
Guy Schalnat 已提交
2123
      }
G
Guy Schalnat 已提交
2124
   }
2125
#endif
G
Guy Schalnat 已提交
2126

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

2132
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2133 2134 2135 2136 2137 2138 2139
/* 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.
 */
2140
void /* PRIVATE */
G
Guy Schalnat 已提交
2141
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
G
Guy Schalnat 已提交
2142
{
2143
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2144

2145
   /* Start of interlace block */
2146
   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2147

2148
   /* Offset to next interlace block */
2149
   static PNG_CONST png_byte  png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2150

2151
   png_debug(1, "in png_do_write_interlace");
2152

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

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

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

               if (shift == 0)
               {
                  shift = 7;
2183
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2184 2185
                  d = 0;
               }
2186

G
Guy Schalnat 已提交
2187 2188 2189 2190 2191
               else
                  shift--;

            }
            if (shift != 7)
2192
               *dp = (png_byte)d;
2193

G
Guy Schalnat 已提交
2194 2195
            break;
         }
2196

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

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

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

               if (shift == 0)
               {
                  shift = 6;
2221
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2222 2223
                  d = 0;
               }
2224

G
Guy Schalnat 已提交
2225 2226 2227 2228
               else
                  shift -= 2;
            }
            if (shift != 6)
2229
               *dp = (png_byte)d;
2230

G
Guy Schalnat 已提交
2231 2232
            break;
         }
2233

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

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

               if (shift == 0)
               {
G
Guy Schalnat 已提交
2256
                  shift = 4;
2257
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2258 2259
                  d = 0;
               }
2260

G
Guy Schalnat 已提交
2261 2262 2263 2264
               else
                  shift -= 4;
            }
            if (shift != 4)
2265
               *dp = (png_byte)d;
2266

G
Guy Schalnat 已提交
2267 2268
            break;
         }
2269

G
Guy Schalnat 已提交
2270 2271
         default:
         {
G
Guy Schalnat 已提交
2272 2273
            png_bytep sp;
            png_bytep dp;
2274 2275
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2276
            png_size_t pixel_bytes;
G
Guy Schalnat 已提交
2277

2278
            /* Start at the beginning */
G
Guy Schalnat 已提交
2279
            dp = row;
2280

2281
            /* Find out how many bytes each pixel takes up */
G
Guy Schalnat 已提交
2282
            pixel_bytes = (row_info->pixel_depth >> 3);
2283 2284

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

2291
               /* Move the pixel */
G
Guy Schalnat 已提交
2292
               if (dp != sp)
2293
                  memcpy(dp, sp, pixel_bytes);
2294

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

2307 2308
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
          row_info->width);
G
Guy Schalnat 已提交
2309 2310
   }
}
G
Guy Schalnat 已提交
2311
#endif
G
Guy Schalnat 已提交
2312

A
Andreas Dilger 已提交
2313 2314
/* 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
2315 2316
 * chosen filter.
 */
2317
static void /* PRIVATE */
2318
png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2319
   png_size_t row_bytes);
2320

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

   png_debug(1, "in png_write_find_filter");

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

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

   prev_row = png_ptr->prev_row;
2352 2353
#endif
   best_row = png_ptr->row_buf;
2354
#ifdef PNG_WRITE_FILTER_SUPPORTED
2355
   row_buf = best_row;
A
Andreas Dilger 已提交
2356 2357 2358 2359
   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
2360
    * from zero, using anything >= 128 as negative numbers.  This is known
A
Andreas Dilger 已提交
2361
    * as the "minimum sum of absolute differences" heuristic.  Other
2362
    * heuristics are the "weighted minimum sum of absolute differences"
A
Andreas Dilger 已提交
2363
    * (experimental and can in theory improve compression), and the "zlib
2364 2365 2366
    * 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 已提交
2367
    * computationally expensive).
2368 2369
    *
    * GRR 980525:  consider also
2370
    *
2371 2372 2373
    *   (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?]
2374
    *
2375 2376
    *  (1b) minimum sum of absolute differences from sliding average, probably
    *       with window size <= deflate window (usually 32K)
2377
    *
2378 2379
    *   (2) minimum sum of squared differences from zero or running average
    *       (i.e., ~ root-mean-square approach)
A
Andreas Dilger 已提交
2380
    */
G
Guy Schalnat 已提交
2381

2382

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

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

2399
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2400 2401 2402
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
         png_uint_32 sumhi, sumlo;
2403
         int j;
A
Andreas Dilger 已提交
2404 2405 2406 2407
         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 */
2408
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2409
         {
2410
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
A
Andreas Dilger 已提交
2411
            {
2412
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2413
                   PNG_WEIGHT_SHIFT;
2414

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

         /* 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]) >>
2425
             PNG_COST_SHIFT;
2426

A
Andreas Dilger 已提交
2427
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2428
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2429 2430 2431

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2432

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

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

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

2453
      for (lp = row_buf + 1; i < row_bytes;
2454 2455
         i++, rp++, lp++, dp++)
      {
2456
         *dp = (png_byte)((int)*rp - (int)*lp);
2457
      }
2458

2459 2460 2461
      best_row = png_ptr->sub_row;
   }

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

2469
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2470
      /* We temporarily increase the "minimum sum" by the factor we
A
Andreas Dilger 已提交
2471 2472 2473 2474 2475
       * 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)
      {
2476
         int j;
A
Andreas Dilger 已提交
2477 2478 2479 2480
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

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

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

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2494
             PNG_COST_SHIFT;
2495

A
Andreas Dilger 已提交
2496
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2497
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2498 2499 2500

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2501

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

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

G
Guy Schalnat 已提交
2512 2513
         sum += (v < 128) ? v : 256 - v;
      }
2514

2515
      for (lp = row_buf + 1; i < row_bytes;
2516
         i++, rp++, lp++, dp++)
G
Guy Schalnat 已提交
2517
      {
2518
         v = *dp = (png_byte)((int)*rp - (int)*lp);
G
Guy Schalnat 已提交
2519 2520

         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2521 2522 2523 2524 2525

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

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

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

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

         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2547
             PNG_COST_SHIFT;
2548

A
Andreas Dilger 已提交
2549
         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2550
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2551 2552 2553

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2554

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

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

2567
   /* Up filter */
2568 2569 2570
   if (filter_to_do == PNG_FILTER_UP)
   {
      png_bytep rp, dp, pp;
2571
      png_size_t i;
2572 2573

      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2574 2575
          pp = prev_row + 1; i < row_bytes;
          i++, rp++, pp++, dp++)
2576
      {
2577
         *dp = (png_byte)((int)*rp - (int)*pp);
2578
      }
2579

2580 2581 2582
      best_row = png_ptr->up_row;
   }

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

2590

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

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

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

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2612
             PNG_COST_SHIFT;
2613

A
Andreas Dilger 已提交
2614
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2615
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2616 2617 2618

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2619

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

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

         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2631 2632 2633

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

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

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

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

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2657
             PNG_COST_SHIFT;
2658

A
Andreas Dilger 已提交
2659
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2660
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2661 2662 2663

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2664

A
Andreas Dilger 已提交
2665 2666 2667 2668 2669
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

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

2677
   /* Avg filter */
2678 2679 2680
   if (filter_to_do == PNG_FILTER_AVG)
   {
      png_bytep rp, dp, pp, lp;
2681
      png_uint_32 i;
2682

2683
      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2684
           pp = prev_row + 1; i < bpp; i++)
2685
      {
2686
         *dp++ = (png_byte)((int)*rp++ - ((int)*pp++ / 2));
2687
      }
2688

2689
      for (lp = row_buf + 1; i < row_bytes; i++)
2690
      {
2691
         *dp++ =
2692
             (png_byte)((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2));
2693 2694 2695 2696
      }
      best_row = png_ptr->avg_row;
   }

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

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

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

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

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2725
             PNG_COST_SHIFT;
2726

A
Andreas Dilger 已提交
2727
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2728
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2729 2730 2731

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2732

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

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

G
Guy Schalnat 已提交
2743 2744
         sum += (v < 128) ? v : 256 - v;
      }
2745

2746
      for (lp = row_buf + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2747
      {
2748
         v = *dp++ =
2749
             (png_byte)(((int)*rp++ - ((int)*pp++ + (int)*lp++) / 2));
G
Guy Schalnat 已提交
2750

G
Guy Schalnat 已提交
2751
         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2752 2753 2754

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

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

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

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

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2778
             PNG_COST_SHIFT;
2779

A
Andreas Dilger 已提交
2780
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2781
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2782 2783 2784

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2785

A
Andreas Dilger 已提交
2786 2787 2788 2789 2790
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

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

A
Andreas Dilger 已提交
2798
   /* Paeth filter */
2799
   if ((filter_to_do == PNG_FILTER_PAETH) != 0)
2800 2801
   {
      png_bytep rp, dp, pp, cp, lp;
2802
      png_size_t i;
2803

2804
      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2805
          pp = prev_row + 1; i < bpp; i++)
2806
      {
2807
         *dp++ = (png_byte)((int)*rp++ - (int)*pp++);
2808 2809
      }

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

2814 2815 2816
         b = *pp++;
         c = *cp++;
         a = *lp++;
2817

2818 2819
         p = b - c;
         pc = a - c;
2820 2821

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

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

2833
         *dp++ = (png_byte)((int)*rp++ - p);
2834 2835 2836 2837
      }
      best_row = png_ptr->paeth_row;
   }

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

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

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

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

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2866
             PNG_COST_SHIFT;
2867

A
Andreas Dilger 已提交
2868
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2869
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2870 2871 2872

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2873

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

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

G
Guy Schalnat 已提交
2884 2885
         sum += (v < 128) ? v : 256 - v;
      }
2886

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

2891 2892 2893
         b = *pp++;
         c = *cp++;
         a = *lp++;
2894 2895

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

G
Guy Schalnat 已提交
2914 2915
         if (pa <= pb && pa <= pc)
            p = a;
2916

G
Guy Schalnat 已提交
2917 2918
         else if (pb <= pc)
            p = b;
2919

G
Guy Schalnat 已提交
2920 2921
         else
            p = c;
2922
#endif /* SLOW_PAETH */
G
Guy Schalnat 已提交
2923

2924
         v = *dp++ = (png_byte)((int)*rp++ - p);
G
Guy Schalnat 已提交
2925

G
Guy Schalnat 已提交
2926
         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2927 2928 2929

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

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

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

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

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2953
             PNG_COST_SHIFT;
2954

A
Andreas Dilger 已提交
2955
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2956
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2957 2958 2959

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2960

A
Andreas Dilger 已提交
2961 2962 2963 2964 2965
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2966 2967 2968 2969
      if (sum < mins)
      {
         best_row = png_ptr->paeth_row;
      }
G
Guy Schalnat 已提交
2970
   }
2971
#endif /* WRITE_FILTER */
2972

2973 2974
   /* 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 已提交
2975

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

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

2988
      png_ptr->prev_filters[j] = best_row[0];
A
Andreas Dilger 已提交
2989 2990
   }
#endif
2991
#endif /* WRITE_FILTER */
G
Guy Schalnat 已提交
2992
}
G
Guy Schalnat 已提交
2993

G
Guy Schalnat 已提交
2994

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

3002
   png_debug1(2, "filter = %d", filtered_row[0]);
3003

3004
   png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
G
Guy Schalnat 已提交
3005

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

      tptr = png_ptr->prev_row;
      png_ptr->prev_row = png_ptr->row_buf;
      png_ptr->row_buf = tptr;
   }
3016
#endif /* WRITE_FILTER */
G
Guy Schalnat 已提交
3017

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

3021
#ifdef PNG_WRITE_FLUSH_SUPPORTED
G
Guy Schalnat 已提交
3022 3023 3024 3025 3026 3027
   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 已提交
3028
   }
3029
#endif /* WRITE_FLUSH */
G
Guy Schalnat 已提交
3030
}
3031
#endif /* WRITE */