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

A
Andreas Dilger 已提交
2
/* pngwutil.c - utilities to write a PNG file
3
 *
4
 * Copyright (c) 2018 Cosmin Truta
C
Cosmin Truta 已提交
5
 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6 7
 * Copyright (c) 1996-1997 Andreas Dilger
 * 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) & 0xffU);
   buf[1] = (png_byte)((i >> 16) & 0xffU);
   buf[2] = (png_byte)((i >>  8) & 0xffU);
   buf[3] = (png_byte)( i        & 0xffU);
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) & 0xffU);
   buf[1] = (png_byte)( i       & 0xffU);
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
       (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, size_t length)
G
Guy Schalnat 已提交
128
{
129 130 131
   /* Write the data, and run the CRC over it */
   if (png_ptr == NULL)
      return;
132

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

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

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

150 151
   if (png_ptr == NULL) return;

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

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

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

165 166 167 168 169 170 171 172 173 174
/* 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
175
png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
176
    png_const_bytep data, size_t length)
177 178 179 180
{
   if (png_ptr == NULL)
      return;

181
   /* On 64-bit architectures 'length' may not fit in a png_uint_32. */
182
   if (length > PNG_UINT_31_MAX)
183
      png_error(png_ptr, "length exceeds PNG maximum");
184 185 186 187 188 189 190 191

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

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

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

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

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

231 232
         return cb_base;
      }
233

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

238
   else
239
      return 0xffffffffU;
240
}
241

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

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

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

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

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

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

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

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

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

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

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

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

342 343 344
         else
            strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
      }
345

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

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
      /* 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;
384
         }
385
      }
386

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

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

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

409
      /* Now initialize if required, setting the new parameters, otherwise just
410
       * do a simple reset to the previous parameters.
411
       */
412
      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
413 414 415 416 417
         ret = deflateReset(&png_ptr->zstream);

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

         if (ret == Z_OK)
            png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
422
      }
423 424 425 426 427 428 429 430 431 432 433

      /* 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;
434
   }
435
}
436

437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
/* 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);
   }
456 457
}

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

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

486 487 488
/* Compress the data in the compression state input */
static int
png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
489
    compression_state *comp, png_uint_32 prefix_len)
490 491
{
   int ret;
492

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

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

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

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

525
      output_len = png_ptr->zstream.avail_out;
526

527
      do
528
      {
529
         uInt avail_in = ZLIB_IO_MAX;
530

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

534
         input_len -= avail_in;
535

536
         png_ptr->zstream.avail_in = avail_in;
537

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

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

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

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

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

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

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

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

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

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

608 609
      else
         png_zstream_error(png_ptr, ret);
610

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

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

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

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

649
      png_write_chunk_data(png_ptr, output, avail);
650

651
      output_len -= avail;
652

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

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

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

G
Guy Schalnat 已提交
667
/* Write the IHDR chunk, and update the png_struct with the necessary
668 669 670
 * information.  Note that the rest of this code depends upon this
 * information being correct.
 */
671
void /* PRIVATE */
672
png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
673 674
    int bit_depth, int color_type, int compression_type, int filter_type,
    int interlace_type)
G
Guy Schalnat 已提交
675
{
676
   png_byte buf[13]; /* Buffer to store the IHDR info */
677
   int is_invalid_depth;
G
Guy Schalnat 已提交
678

679
   png_debug(1, "in png_write_IHDR");
680

G
Guy Schalnat 已提交
681
   /* Check that we have valid input data from the application info */
G
Guy Schalnat 已提交
682 683
   switch (color_type)
   {
A
Andreas Dilger 已提交
684
      case PNG_COLOR_TYPE_GRAY:
G
Guy Schalnat 已提交
685 686 687 688 689 690
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
            case 8:
691
#ifdef PNG_WRITE_16BIT_SUPPORTED
692
            case 16:
693
#endif
694
               png_ptr->channels = 1; break;
695

696 697 698
            default:
               png_error(png_ptr,
                   "Invalid bit depth for grayscale image");
G
Guy Schalnat 已提交
699
         }
G
Guy Schalnat 已提交
700
         break;
701

A
Andreas Dilger 已提交
702
      case PNG_COLOR_TYPE_RGB:
703
         is_invalid_depth = (bit_depth != 8);
704
#ifdef PNG_WRITE_16BIT_SUPPORTED
705
         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
706
#endif
707
         if (is_invalid_depth)
G
Guy Schalnat 已提交
708
            png_error(png_ptr, "Invalid bit depth for RGB image");
709

G
Guy Schalnat 已提交
710 711
         png_ptr->channels = 3;
         break;
712

A
Andreas Dilger 已提交
713
      case PNG_COLOR_TYPE_PALETTE:
G
Guy Schalnat 已提交
714 715 716 717 718
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
719 720 721
            case 8:
               png_ptr->channels = 1;
               break;
722

723 724
            default:
               png_error(png_ptr, "Invalid bit depth for paletted image");
G
Guy Schalnat 已提交
725 726
         }
         break;
727

A
Andreas Dilger 已提交
728
      case PNG_COLOR_TYPE_GRAY_ALPHA:
729 730 731 732 733
         is_invalid_depth = (bit_depth != 8);
#ifdef PNG_WRITE_16BIT_SUPPORTED
         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
#endif
         if (is_invalid_depth)
G
Guy Schalnat 已提交
734
            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
735

G
Guy Schalnat 已提交
736 737
         png_ptr->channels = 2;
         break;
738

A
Andreas Dilger 已提交
739
      case PNG_COLOR_TYPE_RGB_ALPHA:
740
         is_invalid_depth = (bit_depth != 8);
741
#ifdef PNG_WRITE_16BIT_SUPPORTED
742
         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
743
#endif
744
         if (is_invalid_depth)
G
Guy Schalnat 已提交
745
            png_error(png_ptr, "Invalid bit depth for RGBA image");
746

G
Guy Schalnat 已提交
747 748
         png_ptr->channels = 4;
         break;
749

G
Guy Schalnat 已提交
750 751 752 753
      default:
         png_error(png_ptr, "Invalid image color type specified");
   }

A
Andreas Dilger 已提交
754
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
G
Guy Schalnat 已提交
755 756
   {
      png_warning(png_ptr, "Invalid compression type specified");
A
Andreas Dilger 已提交
757
      compression_type = PNG_COMPRESSION_TYPE_BASE;
G
Guy Schalnat 已提交
758 759
   }

760 761 762 763 764 765 766 767 768
   /* 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
    */
769
   if (
770
#ifdef PNG_MNG_FEATURES_SUPPORTED
771 772
       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
       ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
773 774 775
       (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
776
#endif
777
       filter_type != PNG_FILTER_TYPE_BASE)
G
Guy Schalnat 已提交
778 779
   {
      png_warning(png_ptr, "Invalid filter type specified");
A
Andreas Dilger 已提交
780
      filter_type = PNG_FILTER_TYPE_BASE;
G
Guy Schalnat 已提交
781 782
   }

783
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
A
Andreas Dilger 已提交
784
   if (interlace_type != PNG_INTERLACE_NONE &&
785
       interlace_type != PNG_INTERLACE_ADAM7)
G
Guy Schalnat 已提交
786 787
   {
      png_warning(png_ptr, "Invalid interlace type specified");
A
Andreas Dilger 已提交
788
      interlace_type = PNG_INTERLACE_ADAM7;
G
Guy Schalnat 已提交
789
   }
790 791 792
#else
   interlace_type=PNG_INTERLACE_NONE;
#endif
G
Guy Schalnat 已提交
793

794
   /* Save the relevant information */
795 796 797
   png_ptr->bit_depth = (png_byte)bit_depth;
   png_ptr->color_type = (png_byte)color_type;
   png_ptr->interlaced = (png_byte)interlace_type;
798
#ifdef PNG_MNG_FEATURES_SUPPORTED
799
   png_ptr->filter_type = (png_byte)filter_type;
800
#endif
801
   png_ptr->compression_type = (png_byte)compression_type;
G
Guy Schalnat 已提交
802 803 804
   png_ptr->width = width;
   png_ptr->height = height;

805
   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
806
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
807
   /* Set the usr info, so any transformations can modify it */
G
Guy Schalnat 已提交
808 809
   png_ptr->usr_width = png_ptr->width;
   png_ptr->usr_bit_depth = png_ptr->bit_depth;
G
Guy Schalnat 已提交
810 811
   png_ptr->usr_channels = png_ptr->channels;

812
   /* Pack the header information into the buffer */
G
Guy Schalnat 已提交
813 814
   png_save_uint_32(buf, width);
   png_save_uint_32(buf + 4, height);
815 816 817 818 819
   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 已提交
820

821
   /* Write the chunk */
822
   png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
G
Guy Schalnat 已提交
823

824
   if ((png_ptr->do_filter) == PNG_NO_FILTERS)
G
Guy Schalnat 已提交
825
   {
A
Andreas Dilger 已提交
826
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
827
          png_ptr->bit_depth < 8)
G
Guy Schalnat 已提交
828
         png_ptr->do_filter = PNG_FILTER_NONE;
829

G
Guy Schalnat 已提交
830
      else
G
Guy Schalnat 已提交
831
         png_ptr->do_filter = PNG_ALL_FILTERS;
G
Guy Schalnat 已提交
832
   }
833

834
   png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
G
Guy Schalnat 已提交
835 836
}

837
/* Write the palette.  We are careful not to trust png_color to be in the
838
 * correct order for PNG, so people can redefine it to any convenient
839 840
 * structure.
 */
841
void /* PRIVATE */
842
png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
843
    png_uint_32 num_pal)
G
Guy Schalnat 已提交
844
{
845
   png_uint_32 max_palette_length, i;
846
   png_const_colorp pal_ptr;
G
Guy Schalnat 已提交
847 848
   png_byte buf[3];

849
   png_debug(1, "in png_write_PLTE");
850

851
   max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
852 853
      (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;

854
   if ((
855
#ifdef PNG_MNG_FEATURES_SUPPORTED
856
       (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
857
#endif
858
       num_pal == 0) || num_pal > max_palette_length)
859
   {
860 861 862 863
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_error(png_ptr, "Invalid number of colors in palette");
      }
864

865 866 867 868 869
      else
      {
         png_warning(png_ptr, "Invalid number of colors in palette");
         return;
      }
870 871
   }

872
   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
873 874
   {
      png_warning(png_ptr,
875
          "Ignoring request to write a PLTE chunk in grayscale PNG");
876

877
      return;
G
Guy Schalnat 已提交
878 879
   }

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

883
   png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
884
#ifdef PNG_POINTER_INDEXING_SUPPORTED
885

A
Andreas Dilger 已提交
886
   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
G
Guy Schalnat 已提交
887 888 889 890
   {
      buf[0] = pal_ptr->red;
      buf[1] = pal_ptr->green;
      buf[2] = pal_ptr->blue;
891
      png_write_chunk_data(png_ptr, buf, 3);
G
Guy Schalnat 已提交
892
   }
893

894
#else
895 896 897
   /* This is a little slower but some buggy compilers need to do this
    * instead
    */
898
   pal_ptr=palette;
899

900 901 902 903 904
   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;
905
      png_write_chunk_data(png_ptr, buf, 3);
906
   }
907

908
#endif
G
Guy Schalnat 已提交
909
   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
910
   png_ptr->mode |= PNG_HAVE_PLTE;
G
Guy Schalnat 已提交
911 912
}

913 914 915 916 917 918 919 920 921 922 923 924 925 926
/* 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
927
 * checking and (at the end) clearing png_ptr->zowner; it does some sanity
928 929
 * checks on the 'mode' flags while doing this.
 */
930
void /* PRIVATE */
931
png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
932
    png_alloc_size_t input_len, int flush)
G
Guy Schalnat 已提交
933
{
934 935 936 937 938 939 940 941 942 943
   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,
944
             png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
945 946
         png_ptr->zbuffer_list->next = NULL;
      }
947

948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
      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 (;;)
969
   {
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
      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;

987
      /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
988 989
       * that these two zstream fields are preserved across the calls, therefore
       * there is no need to set these up on entry to the loop.
990
       */
991 992 993 994
      if (png_ptr->zstream.avail_out == 0)
      {
         png_bytep data = png_ptr->zbuffer_list->output;
         uInt size = png_ptr->zbuffer_size;
995

996 997 998
         /* Write an IDAT containing the data then reset the buffer.  The
          * first IDAT may need deflate header optimization.
          */
999 1000 1001
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
            if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
                png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
1002
               optimize_cmf(data, png_image_size(png_ptr));
1003
#endif
1004

1005
         if (size > 0)
1006
            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
         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;
      }

1020
      /* The order of these checks doesn't matter much; it just affects which
1021 1022 1023
       * possible error might be detected if multiple things go wrong at once.
       */
      if (ret == Z_OK) /* most likely return code! */
1024
      {
1025 1026 1027
         /* 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.
1028
          */
1029
         if (input_len == 0)
1030
         {
1031 1032
            if (flush == Z_FINISH)
               png_error(png_ptr, "Z_OK on Z_FINISH with output space");
1033

1034 1035 1036
            return;
         }
      }
1037

1038 1039 1040 1041 1042 1043 1044
      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;
1045

1046 1047 1048 1049 1050
#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
1051

1052
         if (size > 0)
1053
            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
1054 1055 1056
         png_ptr->zstream.avail_out = 0;
         png_ptr->zstream.next_out = NULL;
         png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
1057

1058 1059
         png_ptr->zowner = 0; /* Release the stream */
         return;
1060
      }
1061

1062
      else
1063 1064 1065 1066 1067
      {
         /* This is an error condition. */
         png_zstream_error(png_ptr, ret);
         png_error(png_ptr, png_ptr->zstream.msg);
      }
1068
   }
G
Guy Schalnat 已提交
1069 1070
}

1071
/* Write an IEND chunk */
1072
void /* PRIVATE */
1073
png_write_IEND(png_structrp png_ptr)
G
Guy Schalnat 已提交
1074
{
1075
   png_debug(1, "in png_write_IEND");
1076

1077
   png_write_complete_chunk(png_ptr, png_IEND, NULL, 0);
A
Andreas Dilger 已提交
1078
   png_ptr->mode |= PNG_HAVE_IEND;
G
Guy Schalnat 已提交
1079 1080
}

1081
#ifdef PNG_WRITE_gAMA_SUPPORTED
1082
/* Write a gAMA chunk */
1083
void /* PRIVATE */
1084
png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
1085 1086 1087
{
   png_byte buf[4];

1088
   png_debug(1, "in png_write_gAMA");
1089

1090
   /* file_gamma is saved in 1/100,000ths */
1091
   png_save_uint_32(buf, (png_uint_32)file_gamma);
1092
   png_write_complete_chunk(png_ptr, png_gAMA, buf, 4);
1093 1094
}
#endif
G
Guy Schalnat 已提交
1095

1096
#ifdef PNG_WRITE_sRGB_SUPPORTED
1097
/* Write a sRGB chunk */
1098
void /* PRIVATE */
1099
png_write_sRGB(png_structrp png_ptr, int srgb_intent)
1100 1101 1102
{
   png_byte buf[1];

1103
   png_debug(1, "in png_write_sRGB");
1104

1105
   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1106 1107
      png_warning(png_ptr,
          "Invalid sRGB rendering intent specified");
1108

1109
   buf[0]=(png_byte)srgb_intent;
1110
   png_write_complete_chunk(png_ptr, png_sRGB, buf, 1);
1111 1112 1113
}
#endif

1114
#ifdef PNG_WRITE_iCCP_SUPPORTED
1115
/* Write an iCCP chunk */
1116
void /* PRIVATE */
1117 1118
png_write_iCCP(png_structrp png_ptr, png_const_charp name,
    png_const_bytep profile)
1119
{
1120 1121 1122
   png_uint_32 name_len;
   png_uint_32 profile_len;
   png_byte new_name[81]; /* 1 byte for the compression byte */
1123
   compression_state comp;
1124
   png_uint_32 temp;
1125

1126
   png_debug(1, "in png_write_iCCP");
1127

1128 1129 1130
   /* These are all internal problems: the profile should have been checked
    * before when it was stored.
    */
1131
   if (profile == NULL)
1132
      png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
1133

1134
   profile_len = png_get_uint_32(profile);
1135

1136 1137
   if (profile_len < 132)
      png_error(png_ptr, "ICC profile too short");
1138

1139 1140
   temp = (png_uint_32) (*(profile+8));
   if (temp > 3 && (profile_len & 0x03))
1141
      png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
1142

1143
   {
1144
      png_uint_32 embedded_profile_len = png_get_uint_32(profile);
1145

1146 1147
      if (profile_len != embedded_profile_len)
         png_error(png_ptr, "Profile length does not match profile");
1148
   }
1149

1150
   name_len = png_check_keyword(png_ptr, name, new_name);
1151

1152 1153
   if (name_len == 0)
      png_error(png_ptr, "iCCP: invalid keyword");
1154

1155
   new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
1156

1157
   /* Make sure we include the NULL after the name and the compression type */
1158
   ++name_len;
1159

1160
   png_text_compress_init(&comp, profile, profile_len);
1161

1162 1163 1164
   /* 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);
1165

1166 1167 1168 1169 1170
   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);
1171 1172 1173 1174 1175

   png_write_chunk_end(png_ptr);
}
#endif

1176
#ifdef PNG_WRITE_sPLT_SUPPORTED
1177
/* Write a sPLT chunk */
1178
void /* PRIVATE */
1179
png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
1180
{
1181 1182
   png_uint_32 name_len;
   png_byte new_name[80];
1183
   png_byte entrybuf[10];
1184 1185
   size_t entry_size = (spalette->depth == 8 ? 6 : 10);
   size_t palette_size = entry_size * (size_t)spalette->nentries;
1186
   png_sPLT_entryp ep;
1187
#ifndef PNG_POINTER_INDEXING_SUPPORTED
1188 1189
   int i;
#endif
1190

1191
   png_debug(1, "in png_write_sPLT");
1192

1193 1194 1195 1196
   name_len = png_check_keyword(png_ptr, spalette->name, new_name);

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

1198
   /* Make sure we include the NULL after the name */
1199
   png_write_chunk_header(png_ptr, png_sPLT,
1200
       (png_uint_32)(name_len + 2 + palette_size));
1201

1202
   png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1));
1203

1204
   png_write_chunk_data(png_ptr, &spalette->depth, 1);
1205

1206
   /* Loop through each palette entry, writing appropriately */
1207
#ifdef PNG_POINTER_INDEXING_SUPPORTED
1208
   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1209
   {
1210 1211
      if (spalette->depth == 8)
      {
1212 1213 1214 1215
         entrybuf[0] = (png_byte)ep->red;
         entrybuf[1] = (png_byte)ep->green;
         entrybuf[2] = (png_byte)ep->blue;
         entrybuf[3] = (png_byte)ep->alpha;
1216
         png_save_uint_16(entrybuf + 4, ep->frequency);
1217
      }
1218

1219 1220
      else
      {
1221 1222 1223 1224 1225
         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);
1226
      }
1227

1228
      png_write_chunk_data(png_ptr, entrybuf, entry_size);
1229
   }
1230 1231
#else
   ep=spalette->entries;
1232
   for (i = 0; i>spalette->nentries; i++)
1233
   {
1234 1235
      if (spalette->depth == 8)
      {
1236 1237 1238 1239
         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;
1240
         png_save_uint_16(entrybuf + 4, ep[i].frequency);
1241
      }
1242

1243 1244
      else
      {
1245 1246 1247 1248 1249
         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);
1250
      }
1251

1252
      png_write_chunk_data(png_ptr, entrybuf, entry_size);
1253 1254
   }
#endif
1255 1256 1257 1258 1259

   png_write_chunk_end(png_ptr);
}
#endif

1260
#ifdef PNG_WRITE_sBIT_SUPPORTED
1261
/* Write the sBIT chunk */
1262
void /* PRIVATE */
1263
png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
G
Guy Schalnat 已提交
1264 1265
{
   png_byte buf[4];
1266
   size_t size;
G
Guy Schalnat 已提交
1267

1268
   png_debug(1, "in png_write_sBIT");
1269

1270
   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
1271
   if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
1272
   {
1273
      png_byte maxbits;
G
Guy Schalnat 已提交
1274

1275 1276
      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
          png_ptr->usr_bit_depth);
1277

1278 1279
      if (sbit->red == 0 || sbit->red > maxbits ||
          sbit->green == 0 || sbit->green > maxbits ||
G
Guy Schalnat 已提交
1280 1281 1282 1283 1284
          sbit->blue == 0 || sbit->blue > maxbits)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1285

G
Guy Schalnat 已提交
1286 1287 1288 1289 1290
      buf[0] = sbit->red;
      buf[1] = sbit->green;
      buf[2] = sbit->blue;
      size = 3;
   }
1291

G
Guy Schalnat 已提交
1292 1293
   else
   {
G
Guy Schalnat 已提交
1294 1295 1296 1297 1298
      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1299

G
Guy Schalnat 已提交
1300 1301 1302 1303
      buf[0] = sbit->gray;
      size = 1;
   }

1304
   if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
G
Guy Schalnat 已提交
1305
   {
G
Guy Schalnat 已提交
1306 1307 1308 1309 1310
      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1311

G
Guy Schalnat 已提交
1312 1313 1314
      buf[size++] = sbit->alpha;
   }

1315
   png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
G
Guy Schalnat 已提交
1316
}
G
Guy Schalnat 已提交
1317
#endif
G
Guy Schalnat 已提交
1318

1319
#ifdef PNG_WRITE_cHRM_SUPPORTED
1320
/* Write the cHRM chunk */
1321
void /* PRIVATE */
1322
png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
1323 1324 1325
{
   png_byte buf[32];

1326
   png_debug(1, "in png_write_cHRM");
1327

1328
   /* Each value is saved in 1/100,000ths */
1329 1330
   png_save_int_32(buf,      xy->whitex);
   png_save_int_32(buf +  4, xy->whitey);
1331

1332 1333
   png_save_int_32(buf +  8, xy->redx);
   png_save_int_32(buf + 12, xy->redy);
1334

1335 1336
   png_save_int_32(buf + 16, xy->greenx);
   png_save_int_32(buf + 20, xy->greeny);
1337

1338 1339
   png_save_int_32(buf + 24, xy->bluex);
   png_save_int_32(buf + 28, xy->bluey);
1340

1341
   png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
1342 1343
}
#endif
G
Guy Schalnat 已提交
1344

1345
#ifdef PNG_WRITE_tRNS_SUPPORTED
1346
/* Write the tRNS chunk */
1347
void /* PRIVATE */
1348
png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
1349
    png_const_color_16p tran, int num_trans, int color_type)
G
Guy Schalnat 已提交
1350 1351 1352
{
   png_byte buf[6];

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

G
Guy Schalnat 已提交
1355 1356
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1357
      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1358
      {
1359 1360
         png_app_warning(png_ptr,
             "Invalid number of transparent colors specified");
G
Guy Schalnat 已提交
1361 1362
         return;
      }
1363

1364
      /* Write the chunk out as it is */
1365
      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
1366
          (size_t)num_trans);
G
Guy Schalnat 已提交
1367
   }
1368

G
Guy Schalnat 已提交
1369 1370
   else if (color_type == PNG_COLOR_TYPE_GRAY)
   {
1371
      /* One 16-bit value */
1372
      if (tran->gray >= (1 << png_ptr->bit_depth))
1373
      {
1374
         png_app_warning(png_ptr,
1375
             "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1376

1377 1378
         return;
      }
1379

G
Guy Schalnat 已提交
1380
      png_save_uint_16(buf, tran->gray);
1381
      png_write_complete_chunk(png_ptr, png_tRNS, buf, 2);
G
Guy Schalnat 已提交
1382
   }
1383

G
Guy Schalnat 已提交
1384 1385
   else if (color_type == PNG_COLOR_TYPE_RGB)
   {
1386
      /* Three 16-bit values */
G
Guy Schalnat 已提交
1387 1388 1389
      png_save_uint_16(buf, tran->red);
      png_save_uint_16(buf + 2, tran->green);
      png_save_uint_16(buf + 4, tran->blue);
1390
#ifdef PNG_WRITE_16BIT_SUPPORTED
1391
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1392
#else
1393
      if ((buf[0] | buf[2] | buf[4]) != 0)
1394
#endif
1395
      {
1396
         png_app_warning(png_ptr,
1397
             "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1398 1399
         return;
      }
1400

1401
      png_write_complete_chunk(png_ptr, png_tRNS, buf, 6);
G
Guy Schalnat 已提交
1402
   }
1403

G
Guy Schalnat 已提交
1404 1405
   else
   {
1406
      png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
G
Guy Schalnat 已提交
1407
   }
G
Guy Schalnat 已提交
1408
}
G
Guy Schalnat 已提交
1409
#endif
G
Guy Schalnat 已提交
1410

1411
#ifdef PNG_WRITE_bKGD_SUPPORTED
1412
/* Write the background chunk */
1413
void /* PRIVATE */
1414
png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
G
Guy Schalnat 已提交
1415 1416 1417
{
   png_byte buf[6];

1418
   png_debug(1, "in png_write_bKGD");
1419

G
Guy Schalnat 已提交
1420 1421
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1422
      if (
1423
#ifdef PNG_MNG_FEATURES_SUPPORTED
1424 1425
          (png_ptr->num_palette != 0 ||
          (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
1426
#endif
1427
         back->index >= png_ptr->num_palette)
G
Guy Schalnat 已提交
1428 1429 1430 1431
      {
         png_warning(png_ptr, "Invalid background palette index");
         return;
      }
1432

G
Guy Schalnat 已提交
1433
      buf[0] = back->index;
1434
      png_write_complete_chunk(png_ptr, png_bKGD, buf, 1);
G
Guy Schalnat 已提交
1435
   }
1436

1437
   else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
G
Guy Schalnat 已提交
1438 1439 1440 1441
   {
      png_save_uint_16(buf, back->red);
      png_save_uint_16(buf + 2, back->green);
      png_save_uint_16(buf + 4, back->blue);
1442
#ifdef PNG_WRITE_16BIT_SUPPORTED
1443
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1444
#else
1445
      if ((buf[0] | buf[2] | buf[4]) != 0)
1446
#endif
1447 1448
      {
         png_warning(png_ptr,
1449 1450
             "Ignoring attempt to write 16-bit bKGD chunk "
             "when bit_depth is 8");
1451

1452 1453
         return;
      }
1454

1455
      png_write_complete_chunk(png_ptr, png_bKGD, buf, 6);
G
Guy Schalnat 已提交
1456
   }
1457

G
Guy Schalnat 已提交
1458
   else
G
Guy Schalnat 已提交
1459
   {
1460
      if (back->gray >= (1 << png_ptr->bit_depth))
1461 1462
      {
         png_warning(png_ptr,
1463
             "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1464

1465 1466
         return;
      }
1467

G
Guy Schalnat 已提交
1468
      png_save_uint_16(buf, back->gray);
1469
      png_write_complete_chunk(png_ptr, png_bKGD, buf, 2);
G
Guy Schalnat 已提交
1470 1471
   }
}
G
Guy Schalnat 已提交
1472
#endif
G
Guy Schalnat 已提交
1473

1474 1475 1476 1477 1478 1479
#ifdef PNG_WRITE_eXIf_SUPPORTED
/* Write the Exif data */
void /* PRIVATE */
png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif)
{
   int i;
1480
   png_byte buf[1];
1481 1482 1483 1484 1485 1486 1487

   png_debug(1, "in png_write_eXIf");

   png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif));

   for (i = 0; i < num_exif; i++)
   {
1488
      buf[0] = exif[i];
1489
      png_write_chunk_data(png_ptr, buf, 1);
1490 1491 1492 1493 1494 1495
   }

   png_write_chunk_end(png_ptr);
}
#endif

1496
#ifdef PNG_WRITE_hIST_SUPPORTED
1497
/* Write the histogram */
1498
void /* PRIVATE */
1499
png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
G
Guy Schalnat 已提交
1500
{
1501
   int i;
G
Guy Schalnat 已提交
1502 1503
   png_byte buf[3];

1504
   png_debug(1, "in png_write_hIST");
1505

1506
   if (num_hist > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1507
   {
1508
      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1509
          png_ptr->num_palette);
1510

G
Guy Schalnat 已提交
1511 1512 1513 1514
      png_warning(png_ptr, "Invalid number of histogram entries specified");
      return;
   }

1515
   png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1516

A
Andreas Dilger 已提交
1517
   for (i = 0; i < num_hist; i++)
G
Guy Schalnat 已提交
1518
   {
G
Guy Schalnat 已提交
1519
      png_save_uint_16(buf, hist[i]);
1520
      png_write_chunk_data(png_ptr, buf, 2);
G
Guy Schalnat 已提交
1521
   }
1522

G
Guy Schalnat 已提交
1523 1524
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1525
#endif
G
Guy Schalnat 已提交
1526

1527
#ifdef PNG_WRITE_tEXt_SUPPORTED
1528
/* Write a tEXt chunk */
1529
void /* PRIVATE */
1530
png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1531
    size_t text_len)
G
Guy Schalnat 已提交
1532
{
1533 1534
   png_uint_32 key_len;
   png_byte new_key[80];
A
Andreas Dilger 已提交
1535

1536
   png_debug(1, "in png_write_tEXt");
1537

1538 1539 1540 1541
   key_len = png_check_keyword(png_ptr, key, new_key);

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

A
Andreas Dilger 已提交
1543
   if (text == NULL || *text == '\0')
A
Andreas Dilger 已提交
1544
      text_len = 0;
1545

1546
   else
1547 1548 1549 1550
      text_len = strlen(text);

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

1552
   /* Make sure we include the 0 after the key */
1553
   png_write_chunk_header(png_ptr, png_tEXt,
1554
       (png_uint_32)/*checked above*/(key_len + text_len + 1));
1555 1556 1557 1558
   /*
    * 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.
1559
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1560
    */
1561
   png_write_chunk_data(png_ptr, new_key, key_len + 1);
1562

1563
   if (text_len != 0)
1564
      png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
A
Andreas Dilger 已提交
1565

G
Guy Schalnat 已提交
1566 1567
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1568
#endif
G
Guy Schalnat 已提交
1569

1570
#ifdef PNG_WRITE_zTXt_SUPPORTED
1571
/* Write a compressed text chunk */
1572
void /* PRIVATE */
1573
png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
1574
    int compression)
G
Guy Schalnat 已提交
1575
{
1576 1577
   png_uint_32 key_len;
   png_byte new_key[81];
1578
   compression_state comp;
G
Guy Schalnat 已提交
1579

1580
   png_debug(1, "in png_write_zTXt");
A
Andreas Dilger 已提交
1581

1582
   if (compression == PNG_TEXT_COMPRESSION_NONE)
A
Andreas Dilger 已提交
1583
   {
1584
      png_write_tEXt(png_ptr, key, text, 0);
G
Guy Schalnat 已提交
1585
      return;
A
Andreas Dilger 已提交
1586
   }
A
Andreas Dilger 已提交
1587

1588 1589
   if (compression != PNG_TEXT_COMPRESSION_zTXt)
      png_error(png_ptr, "zTXt: invalid compression type");
G
Guy Schalnat 已提交
1590

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

1593 1594
   if (key_len == 0)
      png_error(png_ptr, "zTXt: invalid keyword");
1595

1596 1597 1598
   /* Add the compression method and 1 for the keyword separator. */
   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
   ++key_len;
1599

1600 1601
   /* Compute the compressed data; do it now for the length */
   png_text_compress_init(&comp, (png_const_bytep)text,
1602
       text == NULL ? 0 : strlen(text));
1603

1604 1605
   if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
      png_error(png_ptr, png_ptr->zstream.msg);
1606

1607 1608
   /* Write start of chunk */
   png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
1609

1610 1611
   /* Write key */
   png_write_chunk_data(png_ptr, new_key, key_len);
1612

1613
   /* Write the compressed data */
1614
   png_write_compressed_data_out(png_ptr, &comp);
G
Guy Schalnat 已提交
1615

1616
   /* Close the chunk */
1617 1618 1619
   png_write_chunk_end(png_ptr);
}
#endif
G
Guy Schalnat 已提交
1620

1621
#ifdef PNG_WRITE_iTXt_SUPPORTED
1622
/* Write an iTXt chunk */
1623
void /* PRIVATE */
1624
png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
1625
    png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1626
{
1627
   png_uint_32 key_len, prefix_len;
1628
   size_t lang_len, lang_key_len;
1629
   png_byte new_key[82];
1630
   compression_state comp;
G
Guy Schalnat 已提交
1631

1632
   png_debug(1, "in png_write_iTXt");
G
Guy Schalnat 已提交
1633

1634
   key_len = png_check_keyword(png_ptr, key, new_key);
1635

1636 1637
   if (key_len == 0)
      png_error(png_ptr, "iTXt: invalid keyword");
1638

1639 1640
   /* Set the compression flag */
   switch (compression)
1641
   {
1642 1643 1644 1645
      case PNG_ITXT_COMPRESSION_NONE:
      case PNG_TEXT_COMPRESSION_NONE:
         compression = new_key[++key_len] = 0; /* no compression */
         break;
1646

1647 1648 1649 1650
      case PNG_TEXT_COMPRESSION_zTXt:
      case PNG_ITXT_COMPRESSION_zTXt:
         compression = new_key[++key_len] = 1; /* compressed */
         break;
1651

1652 1653 1654
      default:
         png_error(png_ptr, "iTXt: invalid compression");
   }
1655

1656 1657
   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
   ++key_len; /* for the keywod separator */
1658

1659 1660
   /* 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
1661 1662 1663 1664
    * 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.
    *
1665
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1666 1667
    *
    * TODO: validate the language tag correctly (see the spec.)
1668
    */
1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679
   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);
1680

1681 1682 1683 1684
   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 已提交
1685

1686
   png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
1687

1688
   if (compression != 0)
1689 1690 1691 1692
   {
      if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
         png_error(png_ptr, png_ptr->zstream.msg);
   }
1693

1694 1695 1696 1697
   else
   {
      if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
         png_error(png_ptr, "iTXt: uncompressed text too long");
1698 1699 1700

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

1703 1704
   png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);

1705
   png_write_chunk_data(png_ptr, new_key, key_len);
1706

1707
   png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
1708

1709
   png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
1710

1711
   if (compression != 0)
1712 1713 1714
      png_write_compressed_data_out(png_ptr, &comp);

   else
1715
      png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
1716 1717

   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
1718
}
G
Guy Schalnat 已提交
1719
#endif
G
Guy Schalnat 已提交
1720

1721
#ifdef PNG_WRITE_oFFs_SUPPORTED
1722
/* Write the oFFs chunk */
1723
void /* PRIVATE */
1724
png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1725
    int unit_type)
G
Guy Schalnat 已提交
1726 1727 1728
{
   png_byte buf[9];

1729
   png_debug(1, "in png_write_oFFs");
1730

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

1734 1735
   png_save_int_32(buf, x_offset);
   png_save_int_32(buf + 4, y_offset);
1736
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1737

1738
   png_write_complete_chunk(png_ptr, png_oFFs, buf, 9);
G
Guy Schalnat 已提交
1739
}
G
Guy Schalnat 已提交
1740
#endif
1741
#ifdef PNG_WRITE_pCAL_SUPPORTED
1742
/* Write the pCAL chunk (described in the PNG extensions document) */
1743
void /* PRIVATE */
1744
png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
1745 1746
    png_int_32 X1, int type, int nparams, png_const_charp units,
    png_charpp params)
A
Andreas Dilger 已提交
1747
{
1748
   png_uint_32 purpose_len;
1749
   size_t units_len, total_len;
1750
   png_size_tp params_len;
A
Andreas Dilger 已提交
1751
   png_byte buf[10];
1752
   png_byte new_purpose[80];
A
Andreas Dilger 已提交
1753 1754
   int i;

1755
   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1756

A
Andreas Dilger 已提交
1757
   if (type >= PNG_EQUATION_LAST)
1758 1759 1760 1761 1762 1763 1764 1765
      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 已提交
1766

1767
   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
1768
   units_len = strlen(units) + (nparams == 0 ? 0 : 1);
1769
   png_debug1(3, "pCAL units length = %d", (int)units_len);
A
Andreas Dilger 已提交
1770 1771
   total_len = purpose_len + units_len + 10;

1772
   params_len = (png_size_tp)png_malloc(png_ptr,
1773
       (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t))));
A
Andreas Dilger 已提交
1774 1775

   /* Find the length of each parameter, making sure we don't count the
1776 1777
    * null terminator for the last parameter.
    */
A
Andreas Dilger 已提交
1778 1779
   for (i = 0; i < nparams; i++)
   {
1780
      params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1781
      png_debug2(3, "pCAL parameter %d length = %lu", i,
1782
          (unsigned long)params_len[i]);
1783
      total_len += params_len[i];
A
Andreas Dilger 已提交
1784 1785
   }

1786
   png_debug1(3, "pCAL total length = %d", (int)total_len);
1787
   png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
1788
   png_write_chunk_data(png_ptr, new_purpose, purpose_len);
A
Andreas Dilger 已提交
1789 1790
   png_save_int_32(buf, X0);
   png_save_int_32(buf + 4, X1);
1791 1792
   buf[8] = (png_byte)type;
   buf[9] = (png_byte)nparams;
1793 1794
   png_write_chunk_data(png_ptr, buf, 10);
   png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len);
A
Andreas Dilger 已提交
1795 1796 1797

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

1801
   png_free(png_ptr, params_len);
A
Andreas Dilger 已提交
1802 1803 1804 1805
   png_write_chunk_end(png_ptr);
}
#endif

1806
#ifdef PNG_WRITE_sCAL_SUPPORTED
1807
/* Write the sCAL chunk */
1808
void /* PRIVATE */
1809
png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
1810
    png_const_charp height)
1811
{
1812
   png_byte buf[64];
1813
   size_t wlen, hlen, total_len;
1814

1815
   png_debug(1, "in png_write_sCAL_s");
1816

1817 1818
   wlen = strlen(width);
   hlen = strlen(height);
1819
   total_len = wlen + hlen + 2;
1820

1821 1822 1823 1824 1825
   if (total_len > 64)
   {
      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
      return;
   }
1826

1827
   buf[0] = (png_byte)unit;
1828 1829
   memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
   memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
1830

1831
   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1832
   png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1833 1834 1835
}
#endif

1836
#ifdef PNG_WRITE_pHYs_SUPPORTED
1837
/* Write the pHYs chunk */
1838
void /* PRIVATE */
1839
png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
1840 1841
    png_uint_32 y_pixels_per_unit,
    int unit_type)
G
Guy Schalnat 已提交
1842 1843 1844
{
   png_byte buf[9];

1845
   png_debug(1, "in png_write_pHYs");
1846

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

A
Andreas Dilger 已提交
1850 1851
   png_save_uint_32(buf, x_pixels_per_unit);
   png_save_uint_32(buf + 4, y_pixels_per_unit);
1852
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1853

1854
   png_write_complete_chunk(png_ptr, png_pHYs, buf, 9);
G
Guy Schalnat 已提交
1855
}
G
Guy Schalnat 已提交
1856
#endif
G
Guy Schalnat 已提交
1857

1858
#ifdef PNG_WRITE_tIME_SUPPORTED
1859 1860 1861
/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
 * or png_convert_from_time_t(), or fill in the structure yourself.
 */
1862
void /* PRIVATE */
1863
png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
G
Guy Schalnat 已提交
1864 1865 1866
{
   png_byte buf[7];

1867
   png_debug(1, "in png_write_tIME");
1868

G
Guy Schalnat 已提交
1869 1870 1871 1872 1873 1874 1875 1876
   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 已提交
1877 1878 1879 1880 1881 1882 1883
   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;

1884
   png_write_complete_chunk(png_ptr, png_tIME, buf, 7);
G
Guy Schalnat 已提交
1885
}
G
Guy Schalnat 已提交
1886
#endif
G
Guy Schalnat 已提交
1887

1888
/* Initializes the row writing capability of libpng */
1889
void /* PRIVATE */
1890
png_write_start_row(png_structrp png_ptr)
G
Guy Schalnat 已提交
1891
{
1892
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1893
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1894

1895
   /* Start of interlace block */
1896
   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1897

1898
   /* Offset to next interlace block */
1899
   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1900

1901
   /* Start of interlace block in the y direction */
1902
   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1903

1904
   /* Offset to next interlace block in the y direction */
1905
   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1906
#endif
1907

1908 1909
   png_alloc_size_t buf_size;
   int usr_pixel_depth;
A
Andreas Dilger 已提交
1910

1911
#ifdef PNG_WRITE_FILTER_SUPPORTED
1912
   png_byte filters;
1913 1914
#endif

1915
   png_debug(1, "in png_write_start_row");
1916

1917 1918 1919 1920 1921
   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;
1922
   png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
A
Andreas Dilger 已提交
1923

1924
   /* Set up row buffer */
1925
   png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
1926

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

1929
#ifdef PNG_WRITE_FILTER_SUPPORTED
1930
   filters = png_ptr->do_filter;
1931

1932
   if (png_ptr->height == 1)
1933
      filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
G
Guy Schalnat 已提交
1934

1935
   if (png_ptr->width == 1)
1936
      filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
1937 1938 1939 1940 1941 1942 1943 1944

   if (filters == 0)
      filters = PNG_FILTER_NONE;

   png_ptr->do_filter = filters;

   if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG |
       PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL)
G
Guy Schalnat 已提交
1945
   {
1946
      int num_filters = 0;
G
Guy Schalnat 已提交
1947

1948
      png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
1949

1950 1951
      if (filters & PNG_FILTER_SUB)
         num_filters++;
G
Guy Schalnat 已提交
1952

1953 1954
      if (filters & PNG_FILTER_UP)
         num_filters++;
1955

1956 1957
      if (filters & PNG_FILTER_AVG)
         num_filters++;
G
Guy Schalnat 已提交
1958

1959 1960
      if (filters & PNG_FILTER_PAETH)
         num_filters++;
1961

1962 1963 1964
      if (num_filters > 1)
         png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr,
             buf_size));
G
Guy Schalnat 已提交
1965
   }
1966 1967 1968 1969 1970

   /* We only need to keep the previous row if we are using one of the following
    * filters.
    */
   if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
J
John Bowler 已提交
1971
      png_ptr->prev_row = png_voidcast(png_bytep,
1972
          png_calloc(png_ptr, buf_size));
1973
#endif /* WRITE_FILTER */
G
Guy Schalnat 已提交
1974

1975
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1976
   /* If interlaced, we need to set up width and height of pass */
1977
   if (png_ptr->interlaced != 0)
G
Guy Schalnat 已提交
1978
   {
1979
      if ((png_ptr->transformations & PNG_INTERLACE) == 0)
G
Guy Schalnat 已提交
1980 1981
      {
         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
1982
             png_pass_ystart[0]) / png_pass_yinc[0];
1983

A
Andreas Dilger 已提交
1984
         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
1985
             png_pass_start[0]) / png_pass_inc[0];
G
Guy Schalnat 已提交
1986
      }
1987

G
Guy Schalnat 已提交
1988 1989 1990 1991 1992 1993
      else
      {
         png_ptr->num_rows = png_ptr->height;
         png_ptr->usr_width = png_ptr->width;
      }
   }
1994

G
Guy Schalnat 已提交
1995
   else
1996
#endif
G
Guy Schalnat 已提交
1997
   {
G
Guy Schalnat 已提交
1998 1999 2000 2001 2002
      png_ptr->num_rows = png_ptr->height;
      png_ptr->usr_width = png_ptr->width;
   }
}

A
Andreas Dilger 已提交
2003
/* Internal use only.  Called when finished processing a row of data. */
2004
void /* PRIVATE */
2005
png_write_finish_row(png_structrp png_ptr)
G
Guy Schalnat 已提交
2006
{
2007
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2008
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2009

2010
   /* Start of interlace block */
2011
   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2012

2013
   /* Offset to next interlace block */
2014
   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2015

2016
   /* Start of interlace block in the y direction */
2017
   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2018

2019
   /* Offset to next interlace block in the y direction */
2020
   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2021
#endif
2022

2023
   png_debug(1, "in png_write_finish_row");
2024

2025
   /* Next row */
G
Guy Schalnat 已提交
2026
   png_ptr->row_number++;
G
Guy Schalnat 已提交
2027

2028
   /* See if we are done */
G
Guy Schalnat 已提交
2029
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
2030
      return;
G
Guy Schalnat 已提交
2031

2032
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2033
   /* If interlaced, go to next pass */
2034
   if (png_ptr->interlaced != 0)
G
Guy Schalnat 已提交
2035 2036
   {
      png_ptr->row_number = 0;
2037
      if ((png_ptr->transformations & PNG_INTERLACE) != 0)
G
Guy Schalnat 已提交
2038 2039 2040
      {
         png_ptr->pass++;
      }
2041

G
Guy Schalnat 已提交
2042 2043
      else
      {
2044
         /* Loop until we find a non-zero width or height pass */
G
Guy Schalnat 已提交
2045 2046 2047
         do
         {
            png_ptr->pass++;
2048

G
Guy Schalnat 已提交
2049 2050
            if (png_ptr->pass >= 7)
               break;
2051

G
Guy Schalnat 已提交
2052
            png_ptr->usr_width = (png_ptr->width +
2053 2054 2055
                png_pass_inc[png_ptr->pass] - 1 -
                png_pass_start[png_ptr->pass]) /
                png_pass_inc[png_ptr->pass];
2056

G
Guy Schalnat 已提交
2057
            png_ptr->num_rows = (png_ptr->height +
2058 2059 2060
                png_pass_yinc[png_ptr->pass] - 1 -
                png_pass_ystart[png_ptr->pass]) /
                png_pass_yinc[png_ptr->pass];
2061

2062
            if ((png_ptr->transformations & PNG_INTERLACE) != 0)
G
Guy Schalnat 已提交
2063
               break;
2064

G
Guy Schalnat 已提交
2065 2066 2067 2068
         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);

      }

2069
      /* Reset the row above the image for the next pass */
G
Guy Schalnat 已提交
2070
      if (png_ptr->pass < 7)
G
Guy Schalnat 已提交
2071
      {
A
Andreas Dilger 已提交
2072
         if (png_ptr->prev_row != NULL)
2073
            memset(png_ptr->prev_row, 0,
2074 2075
                PNG_ROWBYTES(png_ptr->usr_channels *
                png_ptr->usr_bit_depth, png_ptr->width) + 1);
2076

G
Guy Schalnat 已提交
2077
         return;
G
Guy Schalnat 已提交
2078
      }
G
Guy Schalnat 已提交
2079
   }
2080
#endif
G
Guy Schalnat 已提交
2081

2082
   /* If we get here, we've just written the last row, so we need
G
Guy Schalnat 已提交
2083
      to flush the compressor */
2084
   png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
G
Guy Schalnat 已提交
2085 2086
}

2087
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2088 2089 2090 2091 2092 2093 2094
/* 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.
 */
2095
void /* PRIVATE */
G
Guy Schalnat 已提交
2096
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
G
Guy Schalnat 已提交
2097
{
2098
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2099

2100
   /* Start of interlace block */
2101
   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2102

2103
   /* Offset to next interlace block */
2104
   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2105

2106
   png_debug(1, "in png_do_write_interlace");
2107

2108
   /* We don't have to do anything on the last pass (6) */
A
Andreas Dilger 已提交
2109
   if (pass < 6)
G
Guy Schalnat 已提交
2110
   {
2111
      /* Each pixel depth is handled separately */
G
Guy Schalnat 已提交
2112
      switch (row_info->pixel_depth)
G
Guy Schalnat 已提交
2113
      {
G
Guy Schalnat 已提交
2114 2115
         case 1:
         {
G
Guy Schalnat 已提交
2116 2117
            png_bytep sp;
            png_bytep dp;
2118
            unsigned int shift;
G
Guy Schalnat 已提交
2119 2120
            int d;
            int value;
2121 2122
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2123 2124 2125 2126

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

2128
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2129 2130
               i += png_pass_inc[pass])
            {
2131
               sp = row + (size_t)(i >> 3);
2132
               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
G
Guy Schalnat 已提交
2133 2134 2135 2136 2137
               d |= (value << shift);

               if (shift == 0)
               {
                  shift = 7;
2138
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2139 2140
                  d = 0;
               }
2141

G
Guy Schalnat 已提交
2142 2143 2144 2145 2146
               else
                  shift--;

            }
            if (shift != 7)
2147
               *dp = (png_byte)d;
2148

G
Guy Schalnat 已提交
2149 2150
            break;
         }
2151

G
Guy Schalnat 已提交
2152
         case 2:
G
Guy Schalnat 已提交
2153
         {
G
Guy Schalnat 已提交
2154 2155
            png_bytep sp;
            png_bytep dp;
2156
            unsigned int shift;
G
Guy Schalnat 已提交
2157 2158
            int d;
            int value;
2159 2160
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2161 2162 2163 2164

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

2166
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2167 2168
               i += png_pass_inc[pass])
            {
2169
               sp = row + (size_t)(i >> 2);
2170
               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
G
Guy Schalnat 已提交
2171 2172 2173 2174 2175
               d |= (value << shift);

               if (shift == 0)
               {
                  shift = 6;
2176
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2177 2178
                  d = 0;
               }
2179

G
Guy Schalnat 已提交
2180 2181 2182 2183
               else
                  shift -= 2;
            }
            if (shift != 6)
2184
               *dp = (png_byte)d;
2185

G
Guy Schalnat 已提交
2186 2187
            break;
         }
2188

G
Guy Schalnat 已提交
2189 2190
         case 4:
         {
G
Guy Schalnat 已提交
2191 2192
            png_bytep sp;
            png_bytep dp;
2193
            unsigned int shift;
G
Guy Schalnat 已提交
2194 2195
            int d;
            int value;
2196 2197
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2198 2199 2200 2201

            dp = row;
            shift = 4;
            d = 0;
2202
            for (i = png_pass_start[pass]; i < row_width;
2203
                i += png_pass_inc[pass])
G
Guy Schalnat 已提交
2204
            {
2205
               sp = row + (size_t)(i >> 1);
2206
               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
G
Guy Schalnat 已提交
2207 2208 2209 2210
               d |= (value << shift);

               if (shift == 0)
               {
G
Guy Schalnat 已提交
2211
                  shift = 4;
2212
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2213 2214
                  d = 0;
               }
2215

G
Guy Schalnat 已提交
2216 2217 2218 2219
               else
                  shift -= 4;
            }
            if (shift != 4)
2220
               *dp = (png_byte)d;
2221

G
Guy Schalnat 已提交
2222 2223
            break;
         }
2224

G
Guy Schalnat 已提交
2225 2226
         default:
         {
G
Guy Schalnat 已提交
2227 2228
            png_bytep sp;
            png_bytep dp;
2229 2230
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
2231
            size_t pixel_bytes;
G
Guy Schalnat 已提交
2232

2233
            /* Start at the beginning */
G
Guy Schalnat 已提交
2234
            dp = row;
2235

2236
            /* Find out how many bytes each pixel takes up */
G
Guy Schalnat 已提交
2237
            pixel_bytes = (row_info->pixel_depth >> 3);
2238 2239

            /* Loop through the row, only looking at the pixels that matter */
2240
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2241 2242
               i += png_pass_inc[pass])
            {
2243
               /* Find out where the original pixel is */
2244
               sp = row + (size_t)i * pixel_bytes;
2245

2246
               /* Move the pixel */
G
Guy Schalnat 已提交
2247
               if (dp != sp)
2248
                  memcpy(dp, sp, pixel_bytes);
2249

2250
               /* Next pixel */
G
Guy Schalnat 已提交
2251 2252
               dp += pixel_bytes;
            }
G
Guy Schalnat 已提交
2253
            break;
G
Guy Schalnat 已提交
2254 2255
         }
      }
2256
      /* Set new row width */
G
Guy Schalnat 已提交
2257
      row_info->width = (row_info->width +
2258 2259 2260
          png_pass_inc[pass] - 1 -
          png_pass_start[pass]) /
          png_pass_inc[pass];
2261

2262 2263
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
          row_info->width);
G
Guy Schalnat 已提交
2264 2265
   }
}
G
Guy Schalnat 已提交
2266
#endif
G
Guy Schalnat 已提交
2267

2268

A
Andreas Dilger 已提交
2269 2270
/* 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
2271 2272
 * chosen filter.
 */
2273
static void /* PRIVATE */
2274
png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2275
    size_t row_bytes);
2276

2277
#ifdef PNG_WRITE_FILTER_SUPPORTED
2278
static size_t /* PRIVATE */
2279
png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
2280
    size_t row_bytes, size_t lmins)
2281 2282
{
   png_bytep rp, dp, lp;
2283 2284
   size_t i;
   size_t sum = 0;
2285
   unsigned int v;
2286 2287 2288 2289 2290 2291 2292

   png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
        i++, rp++, dp++)
   {
      v = *dp = *rp;
2293
#ifdef PNG_USE_ABS
2294
      sum += 128 - abs((int)v - 128);
2295
#else
2296
      sum += (v < 128) ? v : 256 - v;
2297
#endif
2298 2299 2300 2301 2302 2303
   }

   for (lp = png_ptr->row_buf + 1; i < row_bytes;
      i++, rp++, lp++, dp++)
   {
      v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2304
#ifdef PNG_USE_ABS
2305
      sum += 128 - abs((int)v - 128);
2306
#else
2307
      sum += (v < 128) ? v : 256 - v;
2308
#endif
2309 2310 2311 2312 2313 2314 2315 2316

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

   return (sum);
}

2317
static void /* PRIVATE */
2318
png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
2319
    size_t row_bytes)
2320 2321
{
   png_bytep rp, dp, lp;
2322
   size_t i;
2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338

   png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
        i++, rp++, dp++)
   {
      *dp = *rp;
   }

   for (lp = png_ptr->row_buf + 1; i < row_bytes;
      i++, rp++, lp++, dp++)
   {
      *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
   }
}

2339 2340
static size_t /* PRIVATE */
png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins)
2341 2342
{
   png_bytep rp, dp, pp;
2343 2344
   size_t i;
   size_t sum = 0;
2345
   unsigned int v;
2346 2347 2348 2349 2350 2351 2352 2353

   png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
       pp = png_ptr->prev_row + 1; i < row_bytes;
       i++, rp++, pp++, dp++)
   {
      v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2354
#ifdef PNG_USE_ABS
2355
      sum += 128 - abs((int)v - 128);
2356
#else
2357
      sum += (v < 128) ? v : 256 - v;
2358
#endif
2359 2360 2361 2362 2363 2364 2365

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

   return (sum);
}
2366
static void /* PRIVATE */
2367
png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes)
2368 2369
{
   png_bytep rp, dp, pp;
2370
   size_t i;
2371 2372 2373 2374 2375 2376 2377 2378 2379 2380

   png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
       pp = png_ptr->prev_row + 1; i < row_bytes;
       i++, rp++, pp++, dp++)
   {
      *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
   }
}
2381

2382
static size_t /* PRIVATE */
2383
png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
2384
    size_t row_bytes, size_t lmins)
2385 2386 2387
{
   png_bytep rp, dp, pp, lp;
   png_uint_32 i;
2388
   size_t sum = 0;
2389
   unsigned int v;
2390 2391 2392 2393

   png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2394
       pp = png_ptr->prev_row + 1; i < bpp; i++)
2395 2396 2397
   {
      v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);

2398
#ifdef PNG_USE_ABS
2399
      sum += 128 - abs((int)v - 128);
2400
#else
2401
      sum += (v < 128) ? v : 256 - v;
2402
#endif
2403 2404 2405 2406 2407 2408 2409
   }

   for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
   {
      v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
          & 0xff);

2410
#ifdef PNG_USE_ABS
2411
      sum += 128 - abs((int)v - 128);
2412
#else
2413
      sum += (v < 128) ? v : 256 - v;
2414
#endif
2415 2416 2417 2418 2419 2420 2421

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

   return (sum);
}
2422
static void /* PRIVATE */
2423
png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
2424
    size_t row_bytes)
2425 2426 2427 2428 2429 2430 2431
{
   png_bytep rp, dp, pp, lp;
   png_uint_32 i;

   png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2432
       pp = png_ptr->prev_row + 1; i < bpp; i++)
2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
   {
      *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
   }

   for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
   {
      *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
          & 0xff);
   }
}
2443

2444
static size_t /* PRIVATE */
2445
png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
2446
    size_t row_bytes, size_t lmins)
2447 2448
{
   png_bytep rp, dp, pp, cp, lp;
2449 2450
   size_t i;
   size_t sum = 0;
2451
   unsigned int v;
2452 2453 2454 2455 2456 2457 2458 2459

   png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
       pp = png_ptr->prev_row + 1; i < bpp; i++)
   {
      v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);

2460
#ifdef PNG_USE_ABS
2461
      sum += 128 - abs((int)v - 128);
2462
#else
2463
      sum += (v < 128) ? v : 256 - v;
2464
#endif
2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492
   }

   for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
        i++)
   {
      int a, b, c, pa, pb, pc, p;

      b = *pp++;
      c = *cp++;
      a = *lp++;

      p = b - c;
      pc = a - c;

#ifdef PNG_USE_ABS
      pa = abs(p);
      pb = abs(pc);
      pc = abs(p + pc);
#else
      pa = p < 0 ? -p : p;
      pb = pc < 0 ? -pc : pc;
      pc = (p + pc) < 0 ? -(p + pc) : p + pc;
#endif

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

      v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);

2493
#ifdef PNG_USE_ABS
2494
      sum += 128 - abs((int)v - 128);
2495
#else
2496
      sum += (v < 128) ? v : 256 - v;
2497
#endif
2498 2499 2500 2501 2502 2503 2504

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

   return (sum);
}
2505
static void /* PRIVATE */
2506
png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
2507
    size_t row_bytes)
2508 2509
{
   png_bytep rp, dp, pp, cp, lp;
2510
   size_t i;
2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546

   png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;

   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
       pp = png_ptr->prev_row + 1; i < bpp; i++)
   {
      *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
   }

   for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
        i++)
   {
      int a, b, c, pa, pb, pc, p;

      b = *pp++;
      c = *cp++;
      a = *lp++;

      p = b - c;
      pc = a - c;

#ifdef PNG_USE_ABS
      pa = abs(p);
      pb = abs(pc);
      pc = abs(p + pc);
#else
      pa = p < 0 ? -p : p;
      pb = pc < 0 ? -pc : pc;
      pc = (p + pc) < 0 ? -(p + pc) : p + pc;
#endif

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

      *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
   }
}
2547 2548
#endif /* WRITE_FILTER */

2549
void /* PRIVATE */
2550
png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
G
Guy Schalnat 已提交
2551
{
2552 2553 2554
#ifndef PNG_WRITE_FILTER_SUPPORTED
   png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
#else
2555
   unsigned int filter_to_do = png_ptr->do_filter;
2556 2557 2558
   png_bytep row_buf;
   png_bytep best_row;
   png_uint_32 bpp;
2559 2560
   size_t mins;
   size_t row_bytes = row_info->rowbytes;
2561 2562 2563

   png_debug(1, "in png_write_find_filter");

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

2567 2568 2569
   row_buf = png_ptr->row_buf;
   mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the
                               running sum */;
A
Andreas Dilger 已提交
2570 2571 2572

   /* The prediction method we use is to find which method provides the
    * smallest value when summing the absolute values of the distances
2573
    * from zero, using anything >= 128 as negative numbers.  This is known
A
Andreas Dilger 已提交
2574
    * as the "minimum sum of absolute differences" heuristic.  Other
2575
    * heuristics are the "weighted minimum sum of absolute differences"
A
Andreas Dilger 已提交
2576
    * (experimental and can in theory improve compression), and the "zlib
2577 2578 2579
    * 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 已提交
2580
    * computationally expensive).
2581 2582
    *
    * GRR 980525:  consider also
2583
    *
2584 2585 2586
    *   (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?]
2587
    *
2588 2589
    *  (1b) minimum sum of absolute differences from sliding average, probably
    *       with window size <= deflate window (usually 32K)
2590
    *
2591 2592
    *   (2) minimum sum of squared differences from zero or running average
    *       (i.e., ~ root-mean-square approach)
A
Andreas Dilger 已提交
2593
    */
G
Guy Schalnat 已提交
2594

2595

G
Guy Schalnat 已提交
2596
   /* We don't need to test the 'no filter' case if this is the only filter
A
Andreas Dilger 已提交
2597 2598
    * that has been chosen, as it doesn't actually do anything to the data.
    */
2599 2600
   best_row = png_ptr->row_buf;

2601 2602 2603 2604 2605
   if (PNG_SIZE_MAX/128 <= row_bytes)
   {
      /* Overflow can occur in the calculation, just select the lowest set
       * filter.
       */
2606
      filter_to_do &= 0U-filter_to_do;
2607 2608 2609
   }
   else if ((filter_to_do & PNG_FILTER_NONE) != 0 &&
         filter_to_do != PNG_FILTER_NONE)
G
Guy Schalnat 已提交
2610
   {
2611 2612 2613
      /* Overflow not possible and multiple filters in the list, including the
       * 'none' filter.
       */
G
Guy Schalnat 已提交
2614
      png_bytep rp;
2615 2616
      size_t sum = 0;
      size_t i;
2617
      unsigned int v;
G
Guy Schalnat 已提交
2618

2619 2620 2621 2622
      {
         for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
         {
            v = *rp;
2623
#ifdef PNG_USE_ABS
2624
            sum += 128 - abs((int)v - 128);
2625
#else
2626
            sum += (v < 128) ? v : 256 - v;
2627
#endif
2628 2629 2630
         }
      }

G
Guy Schalnat 已提交
2631 2632
      mins = sum;
   }
G
Guy Schalnat 已提交
2633

2634
   /* Sub filter */
2635
   if (filter_to_do == PNG_FILTER_SUB)
2636
   /* It's the only filter so no testing is needed */
2637
   {
2638
      png_setup_sub_row_only(png_ptr, bpp, row_bytes);
2639
      best_row = png_ptr->try_row;
2640 2641
   }

2642
   else if ((filter_to_do & PNG_FILTER_SUB) != 0)
G
Guy Schalnat 已提交
2643
   {
2644 2645
      size_t sum;
      size_t lmins = mins;
G
Guy Schalnat 已提交
2646

2647
      sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
A
Andreas Dilger 已提交
2648

G
Guy Schalnat 已提交
2649 2650 2651
      if (sum < mins)
      {
         mins = sum;
2652 2653 2654 2655 2656 2657
         best_row = png_ptr->try_row;
         if (png_ptr->tst_row != NULL)
         {
            png_ptr->try_row = png_ptr->tst_row;
            png_ptr->tst_row = best_row;
         }
G
Guy Schalnat 已提交
2658
      }
G
Guy Schalnat 已提交
2659 2660
   }

2661
   /* Up filter */
2662 2663
   if (filter_to_do == PNG_FILTER_UP)
   {
2664
      png_setup_up_row_only(png_ptr, row_bytes);
2665
      best_row = png_ptr->try_row;
2666 2667
   }

2668
   else if ((filter_to_do & PNG_FILTER_UP) != 0)
G
Guy Schalnat 已提交
2669
   {
2670 2671
      size_t sum;
      size_t lmins = mins;
G
Guy Schalnat 已提交
2672

2673
      sum = png_setup_up_row(png_ptr, row_bytes, lmins);
A
Andreas Dilger 已提交
2674

G
Guy Schalnat 已提交
2675 2676 2677
      if (sum < mins)
      {
         mins = sum;
2678 2679 2680 2681 2682 2683
         best_row = png_ptr->try_row;
         if (png_ptr->tst_row != NULL)
         {
            png_ptr->try_row = png_ptr->tst_row;
            png_ptr->tst_row = best_row;
         }
G
Guy Schalnat 已提交
2684 2685 2686
      }
   }

2687
   /* Avg filter */
2688 2689
   if (filter_to_do == PNG_FILTER_AVG)
   {
2690
      png_setup_avg_row_only(png_ptr, bpp, row_bytes);
2691
      best_row = png_ptr->try_row;
2692 2693
   }

2694
   else if ((filter_to_do & PNG_FILTER_AVG) != 0)
G
Guy Schalnat 已提交
2695
   {
2696 2697
      size_t sum;
      size_t lmins = mins;
G
Guy Schalnat 已提交
2698

2699
      sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
A
Andreas Dilger 已提交
2700

G
Guy Schalnat 已提交
2701 2702 2703
      if (sum < mins)
      {
         mins = sum;
2704 2705 2706 2707 2708 2709
         best_row = png_ptr->try_row;
         if (png_ptr->tst_row != NULL)
         {
            png_ptr->try_row = png_ptr->tst_row;
            png_ptr->tst_row = best_row;
         }
G
Guy Schalnat 已提交
2710 2711
      }
   }
G
Guy Schalnat 已提交
2712

A
Andreas Dilger 已提交
2713
   /* Paeth filter */
2714
   if (filter_to_do == PNG_FILTER_PAETH)
2715
   {
2716
      png_setup_paeth_row_only(png_ptr, bpp, row_bytes);
2717
      best_row = png_ptr->try_row;
2718 2719
   }

2720
   else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
G
Guy Schalnat 已提交
2721
   {
2722 2723
      size_t sum;
      size_t lmins = mins;
G
Guy Schalnat 已提交
2724

2725
      sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
A
Andreas Dilger 已提交
2726

G
Guy Schalnat 已提交
2727 2728
      if (sum < mins)
      {
2729 2730 2731 2732 2733 2734
         best_row = png_ptr->try_row;
         if (png_ptr->tst_row != NULL)
         {
            png_ptr->try_row = png_ptr->tst_row;
            png_ptr->tst_row = best_row;
         }
G
Guy Schalnat 已提交
2735
      }
G
Guy Schalnat 已提交
2736
   }
2737

2738 2739
   /* 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 已提交
2740

2741
#endif /* WRITE_FILTER */
G
Guy Schalnat 已提交
2742
}
G
Guy Schalnat 已提交
2743

G
Guy Schalnat 已提交
2744

A
Andreas Dilger 已提交
2745
/* Do the actual writing of a previously filtered row. */
2746
static void
2747
png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2748
    size_t full_row_length/*includes filter byte*/)
G
Guy Schalnat 已提交
2749
{
2750
   png_debug(1, "in png_write_filtered_row");
2751

2752
   png_debug1(2, "filter = %d", filtered_row[0]);
2753

2754
   png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
G
Guy Schalnat 已提交
2755

2756
#ifdef PNG_WRITE_FILTER_SUPPORTED
2757
   /* Swap the current and previous rows */
A
Andreas Dilger 已提交
2758
   if (png_ptr->prev_row != NULL)
G
Guy Schalnat 已提交
2759 2760 2761 2762 2763 2764 2765
   {
      png_bytep tptr;

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

2768
   /* Finish row - updates counters and flushes zlib if last row */
G
Guy Schalnat 已提交
2769
   png_write_finish_row(png_ptr);
G
Guy Schalnat 已提交
2770

2771
#ifdef PNG_WRITE_FLUSH_SUPPORTED
G
Guy Schalnat 已提交
2772 2773 2774 2775 2776 2777
   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 已提交
2778
   }
2779
#endif /* WRITE_FLUSH */
G
Guy Schalnat 已提交
2780
}
2781
#endif /* WRITE */