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

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

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

16 17
#ifdef PNG_WRITE_SUPPORTED

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
85
/* Write a PNG chunk all at once.  The type is an array of ASCII characters
86 87 88 89 90 91 92 93
 * 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.
 */
94
void PNGAPI
95 96
png_write_chunk(png_structp png_ptr, png_const_bytep chunk_name,
   png_const_bytep data, png_size_t length)
G
Guy Schalnat 已提交
97
{
98 99
   if (png_ptr == NULL)
      return;
100

A
Andreas Dilger 已提交
101
   png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
102
   png_write_chunk_data(png_ptr, data, (png_size_t)length);
A
Andreas Dilger 已提交
103
   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
104 105
}

A
Andreas Dilger 已提交
106
/* Write the start of a PNG chunk.  The type is the chunk type.
107 108 109
 * The total_length is the sum of the lengths of all the data you will be
 * passing in png_write_chunk_data().
 */
110
void PNGAPI
111
png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_name,
112
    png_uint_32 length)
G
Guy Schalnat 已提交
113
{
114 115
   png_byte buf[8];

116 117 118 119 120 121
   png_debug2(0, "Writing %s chunk, length = %lu", chunk_name,
      (unsigned long)length);

   if (png_ptr == NULL)
      return;

122 123 124 125 126 127 128
#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

129
   /* Write the length and the chunk name */
A
Andreas Dilger 已提交
130
   png_save_uint_32(buf, length);
131
   png_memcpy(buf + 4, chunk_name, 4);
132
   png_write_data(png_ptr, buf, (png_size_t)8);
133

134
   /* Put the chunk name into png_ptr->chunk_name */
135
   png_memcpy(png_ptr->chunk_name, chunk_name, 4);
136

137
   /* Reset the crc and run it over the chunk name */
G
Guy Schalnat 已提交
138
   png_reset_crc(png_ptr);
139

140 141 142 143 144 145 146 147
   png_calculate_crc(png_ptr, chunk_name, 4);

#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 已提交
148 149
}

A
Andreas Dilger 已提交
150
/* Write the data of a PNG chunk started with png_write_chunk_start().
151 152 153 154
 * 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
 * given to png_write_chunk_start().
 */
155
void PNGAPI
156 157
png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
    png_size_t length)
G
Guy Schalnat 已提交
158
{
159 160 161
   /* Write the data, and run the CRC over it */
   if (png_ptr == NULL)
      return;
162

A
Andreas Dilger 已提交
163
   if (data != NULL && length > 0)
G
Guy Schalnat 已提交
164
   {
G
Guy Schalnat 已提交
165
      png_write_data(png_ptr, data, length);
166

167
      /* Update the CRC after writing the data,
168 169 170
       * in case that the user I/O routine alters it.
       */
      png_calculate_crc(png_ptr, data, length);
G
Guy Schalnat 已提交
171 172 173
   }
}

A
Andreas Dilger 已提交
174
/* Finish a chunk started with png_write_chunk_start(). */
175
void PNGAPI
G
Guy Schalnat 已提交
176
png_write_chunk_end(png_structp png_ptr)
G
Guy Schalnat 已提交
177
{
A
Andreas Dilger 已提交
178 179
   png_byte buf[4];

180 181
   if (png_ptr == NULL) return;

182 183 184 185 186 187 188
#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

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

192
   png_write_data(png_ptr, buf, (png_size_t)4);
G
Guy Schalnat 已提交
193 194
}

195
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
196
/* This pair of functions encapsulates the operation of (a) compressing a
197 198 199 200 201 202 203
 * text string, and (b) issuing it later as a series of chunk data writes.
 * The compression_state structure is shared context for these functions
 * set up by the caller in order to make the whole mess thread-safe.
 */

typedef struct
{
204
   png_const_bytep input;   /* The uncompressed input data */
205 206 207 208
   png_size_t input_len;    /* Its length */
   int num_output_ptr;      /* Number of output pointers used */
   int max_output_ptr;      /* Size of output_ptr */
   png_bytep *output_ptr;   /* Array of pointers to output */
209 210
} compression_state;

211
/* Compress given text into storage in the png_ptr structure */
212
static int /* PRIVATE */
213
png_text_compress(png_structp png_ptr,
214
    png_const_charp text, png_size_t text_len, int compression,
215
    compression_state *comp)
216 217 218
{
   int ret;

219 220
   comp->num_output_ptr = 0;
   comp->max_output_ptr = 0;
221 222
   comp->output_ptr = NULL;
   comp->input = NULL;
223
   comp->input_len = text_len;
224

225
   /* We may just want to pass the text right through */
226 227
   if (compression == PNG_TEXT_COMPRESSION_NONE)
   {
228
      comp->input = (png_const_bytep)text;
229
      return((int)text_len);
230 231 232 233
   }

   if (compression >= PNG_TEXT_COMPRESSION_LAST)
   {
234 235 236 237 238
      PNG_WARNING_PARAMETERS(p)

      png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
         compression);
      png_formatted_warning(png_ptr, p, "Unknown compression type @1");
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
   }

   /* We can't write the chunk until we find out how much data we have,
    * which means we need to run the compressor first and save the
    * output.  This shouldn't be a problem, as the vast majority of
    * comments should be reasonable, but we will set up an array of
    * malloc'd pointers to be sure.
    *
    * If we knew the application was well behaved, we could simplify this
    * greatly by assuming we can always malloc an output buffer large
    * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
    * and malloc this directly.  The only time this would be a bad idea is
    * if we can't malloc more than 64K and we have 64K of random input
    * data, or if the input string is incredibly large (although this
    * wouldn't cause a failure, just a slowdown due to swapping).
    */

256 257
   if (!(png_ptr->mode & PNG_ZLIB_READY_FOR_ZTXT))
     {
258 259

        /* png_warning(png_ptr, "Initialize compressor for ztxt"); */
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
        /* Free memory from previously opened zstream */
        deflateEnd(&png_ptr->zstream);

        /* Initialize the compressor for zTXt compression. */
        ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_text_level,
            png_ptr->zlib_text_method, png_ptr->zlib_text_window_bits,
            png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);

        if (ret != Z_OK)
        {
           if (ret == Z_VERSION_ERROR)
              png_error(png_ptr,
              "zlib failed to initialize compressor for text-- version error");

           if (ret == Z_STREAM_ERROR)
              png_error(png_ptr,
276 277
             "zlib failed to initialize compressor for text-- stream error");

278 279
           if (ret == Z_MEM_ERROR)
              png_error(png_ptr,
280 281
             "zlib failed to initialize compressor for text-- mem error");

282 283 284
           png_error(png_ptr, "zlib failed to initialize compressor for text");
      }
      png_ptr->mode |= PNG_ZLIB_READY_FOR_ZTXT;
285 286
   }

287
   /* Set up the compression buffers */
288
   /* TODO: the following cast hides a potential overflow problem. */
289
   png_ptr->zstream.avail_in = (uInt)text_len;
290

291
   /* NOTE: assume zlib doesn't overwrite the input */
292
   png_ptr->zstream.next_in = (Bytef *)text;
293 294
   png_ptr->zstream.avail_out = png_ptr->zbuf_size;
   png_ptr->zstream.next_out = png_ptr->zbuf;
295

296
   /* This is the same compression loop as in png_write_row() */
297 298
   do
   {
299
      /* Compress the data */
300
      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
301

302 303
      if (ret != Z_OK)
      {
304
         /* Error */
305 306
         if (png_ptr->zstream.msg != NULL)
            png_error(png_ptr, png_ptr->zstream.msg);
307

308 309 310
         else
            png_error(png_ptr, "zlib error");
      }
311

312
      /* Check to see if we need more room */
313
      if (!(png_ptr->zstream.avail_out))
314
      {
315
         /* Make sure the output array has room */
316 317 318 319 320 321 322 323
         if (comp->num_output_ptr >= comp->max_output_ptr)
         {
            int old_max;

            old_max = comp->max_output_ptr;
            comp->max_output_ptr = comp->num_output_ptr + 4;
            if (comp->output_ptr != NULL)
            {
324
               png_bytepp old_ptr;
325 326

               old_ptr = comp->output_ptr;
327

328
               comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
329 330
                   (png_alloc_size_t)
                   (comp->max_output_ptr * png_sizeof(png_charpp)));
331

332
               png_memcpy(comp->output_ptr, old_ptr, old_max
333
                   * png_sizeof(png_charp));
334

335 336 337
               png_free(png_ptr, old_ptr);
            }
            else
338
               comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
339 340
                   (png_alloc_size_t)
                   (comp->max_output_ptr * png_sizeof(png_charp)));
341 342
         }

343
         /* Save the data */
344
         comp->output_ptr[comp->num_output_ptr] =
345
             (png_bytep)png_malloc(png_ptr,
346
             (png_alloc_size_t)png_ptr->zbuf_size);
347

348
         png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
349
             png_ptr->zbuf_size);
350

351
         comp->num_output_ptr++;
352 353 354 355 356

         /* and reset the buffer */
         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
         png_ptr->zstream.next_out = png_ptr->zbuf;
      }
357
   /* Continue until we don't have any more to compress */
358 359
   } while (png_ptr->zstream.avail_in);

360
   /* Finish the compression */
361 362
   do
   {
363
      /* Tell zlib we are finished */
364 365
      ret = deflate(&png_ptr->zstream, Z_FINISH);

366
      if (ret == Z_OK)
367
      {
368
         /* Check to see if we need more room */
369
         if (!(png_ptr->zstream.avail_out))
370
         {
371
            /* Check to make sure our output array has room */
372
            if (comp->num_output_ptr >= comp->max_output_ptr)
373
            {
374 375 376 377 378 379
               int old_max;

               old_max = comp->max_output_ptr;
               comp->max_output_ptr = comp->num_output_ptr + 4;
               if (comp->output_ptr != NULL)
               {
380
                  png_bytepp old_ptr;
381 382

                  old_ptr = comp->output_ptr;
383

384
                  /* This could be optimized to realloc() */
385
                  comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
386 387
                      (png_alloc_size_t)(comp->max_output_ptr *
                      png_sizeof(png_charp)));
388

389
                  png_memcpy(comp->output_ptr, old_ptr,
390
                      old_max * png_sizeof(png_charp));
391

392 393
                  png_free(png_ptr, old_ptr);
               }
394

395
               else
396
                  comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
397 398
                      (png_alloc_size_t)(comp->max_output_ptr *
                      png_sizeof(png_charp)));
399 400
            }

401
            /* Save the data */
402
            comp->output_ptr[comp->num_output_ptr] =
403
                (png_bytep)png_malloc(png_ptr,
404
                (png_alloc_size_t)png_ptr->zbuf_size);
405

406
            png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
407
                png_ptr->zbuf_size);
408

409
            comp->num_output_ptr++;
410

411 412 413 414 415 416 417
            /* and reset the buffer pointers */
            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
            png_ptr->zstream.next_out = png_ptr->zbuf;
         }
      }
      else if (ret != Z_STREAM_END)
      {
418
         /* We got an error */
419 420
         if (png_ptr->zstream.msg != NULL)
            png_error(png_ptr, png_ptr->zstream.msg);
421

422 423
         else
            png_error(png_ptr, "zlib error");
424 425 426
      }
   } while (ret != Z_STREAM_END);

427
   /* Text length is number of buffers plus last buffer */
428
   text_len = png_ptr->zbuf_size * comp->num_output_ptr;
429

430 431 432
   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
      text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;

433
   return((int)text_len);
434 435
}

436
/* Ship the compressed text out via chunk writes */
437
static void /* PRIVATE */
438 439 440 441
png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
{
   int i;

442
   /* Handle the no-compression case */
443 444
   if (comp->input)
   {
445
      png_write_chunk_data(png_ptr, comp->input, comp->input_len);
446

447
      return;
448 449
   }

450
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
   if (comp->input_len >= 2 && comp->input_len < 16384)
   {
      unsigned int z_cmf;  /* zlib compression method and flags */

      /* Optimize the CMF field in the zlib stream.  This hack of the zlib
       * stream is compliant to the stream specification.
       */

      if (comp->num_output_ptr)
        z_cmf = comp->output_ptr[0][0];
      else
        z_cmf = png_ptr->zbuf[0];

      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
      {
         unsigned int z_cinfo;
         unsigned int half_z_window_size;
468
         png_size_t uncompressed_text_size = comp->input_len;
469 470 471 472

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

473
         while (uncompressed_text_size <= half_z_window_size &&
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
             half_z_window_size >= 256)
         {
            z_cinfo--;
            half_z_window_size >>= 1;
         }

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

         if (comp->num_output_ptr)
         {

           if (comp->output_ptr[0][0] != z_cmf)
           {
              int tmp;

              comp->output_ptr[0][0] = (png_byte)z_cmf;
              tmp = comp->output_ptr[0][1] & 0xe0;
              tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
              comp->output_ptr[0][1] = (png_byte)tmp;
           }
         }
         else
         {
            int tmp;

            png_ptr->zbuf[0] = (png_byte)z_cmf;
            tmp = png_ptr->zbuf[1] & 0xe0;
            tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
            png_ptr->zbuf[1] = (png_byte)tmp;
         }
      }

      else
         png_error(png_ptr,
             "Invalid zlib compression method or flags in non-IDAT chunk");
   }
510
#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
511

512
   /* Write saved output buffers, if any */
513 514
   for (i = 0; i < comp->num_output_ptr; i++)
   {
515
      png_write_chunk_data(png_ptr, comp->output_ptr[i],
516
          (png_size_t)png_ptr->zbuf_size);
517

518 519
      png_free(png_ptr, comp->output_ptr[i]);
   }
520

521 522
   if (comp->max_output_ptr != 0)
      png_free(png_ptr, comp->output_ptr);
523

524
   /* Write anything left in zbuf */
525 526
   if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
      png_write_chunk_data(png_ptr, png_ptr->zbuf,
527
          (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
528

529
   /* Reset zlib for another zTXt/iTXt or image data */
530 531
   deflateReset(&png_ptr->zstream);
}
532
#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
533

G
Guy Schalnat 已提交
534
/* Write the IHDR chunk, and update the png_struct with the necessary
535 536 537
 * information.  Note that the rest of this code depends upon this
 * information being correct.
 */
538
void /* PRIVATE */
G
Guy Schalnat 已提交
539
png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
540 541
    int bit_depth, int color_type, int compression_type, int filter_type,
    int interlace_type)
G
Guy Schalnat 已提交
542
{
543
   PNG_IHDR;
544 545
   int ret;

546
   png_byte buf[13]; /* Buffer to store the IHDR info */
G
Guy Schalnat 已提交
547

548
   png_debug(1, "in png_write_IHDR");
549

G
Guy Schalnat 已提交
550
   /* Check that we have valid input data from the application info */
G
Guy Schalnat 已提交
551 552
   switch (color_type)
   {
A
Andreas Dilger 已提交
553
      case PNG_COLOR_TYPE_GRAY:
G
Guy Schalnat 已提交
554 555 556 557 558 559
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
            case 8:
560
#ifdef PNG_WRITE_16BIT_SUPPORTED
561
            case 16:
562
#endif
563
               png_ptr->channels = 1; break;
564

565 566 567
            default:
               png_error(png_ptr,
                   "Invalid bit depth for grayscale image");
G
Guy Schalnat 已提交
568
         }
G
Guy Schalnat 已提交
569
         break;
570

A
Andreas Dilger 已提交
571
      case PNG_COLOR_TYPE_RGB:
572
#ifdef PNG_WRITE_16BIT_SUPPORTED
G
Guy Schalnat 已提交
573
         if (bit_depth != 8 && bit_depth != 16)
574 575 576
#else
         if (bit_depth != 8)
#endif
G
Guy Schalnat 已提交
577
            png_error(png_ptr, "Invalid bit depth for RGB image");
578

G
Guy Schalnat 已提交
579 580
         png_ptr->channels = 3;
         break;
581

A
Andreas Dilger 已提交
582
      case PNG_COLOR_TYPE_PALETTE:
G
Guy Schalnat 已提交
583 584 585 586 587
         switch (bit_depth)
         {
            case 1:
            case 2:
            case 4:
588 589 590
            case 8:
               png_ptr->channels = 1;
               break;
591

592 593
            default:
               png_error(png_ptr, "Invalid bit depth for paletted image");
G
Guy Schalnat 已提交
594 595
         }
         break;
596

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

G
Guy Schalnat 已提交
601 602
         png_ptr->channels = 2;
         break;
603

A
Andreas Dilger 已提交
604
      case PNG_COLOR_TYPE_RGB_ALPHA:
605
#ifdef PNG_WRITE_16BIT_SUPPORTED
G
Guy Schalnat 已提交
606
         if (bit_depth != 8 && bit_depth != 16)
607 608 609
#else
         if (bit_depth != 8)
#endif
G
Guy Schalnat 已提交
610
            png_error(png_ptr, "Invalid bit depth for RGBA image");
611

G
Guy Schalnat 已提交
612 613
         png_ptr->channels = 4;
         break;
614

G
Guy Schalnat 已提交
615 616 617 618
      default:
         png_error(png_ptr, "Invalid image color type specified");
   }

A
Andreas Dilger 已提交
619
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
G
Guy Schalnat 已提交
620 621
   {
      png_warning(png_ptr, "Invalid compression type specified");
A
Andreas Dilger 已提交
622
      compression_type = PNG_COMPRESSION_TYPE_BASE;
G
Guy Schalnat 已提交
623 624
   }

625 626 627 628 629 630 631 632 633
   /* 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
    */
634
   if (
635
#ifdef PNG_MNG_FEATURES_SUPPORTED
636 637 638 639 640
       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
       (color_type == PNG_COLOR_TYPE_RGB ||
        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
641
#endif
642
       filter_type != PNG_FILTER_TYPE_BASE)
G
Guy Schalnat 已提交
643 644
   {
      png_warning(png_ptr, "Invalid filter type specified");
A
Andreas Dilger 已提交
645
      filter_type = PNG_FILTER_TYPE_BASE;
G
Guy Schalnat 已提交
646 647
   }

648
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
A
Andreas Dilger 已提交
649
   if (interlace_type != PNG_INTERLACE_NONE &&
650
       interlace_type != PNG_INTERLACE_ADAM7)
G
Guy Schalnat 已提交
651 652
   {
      png_warning(png_ptr, "Invalid interlace type specified");
A
Andreas Dilger 已提交
653
      interlace_type = PNG_INTERLACE_ADAM7;
G
Guy Schalnat 已提交
654
   }
655 656 657
#else
   interlace_type=PNG_INTERLACE_NONE;
#endif
G
Guy Schalnat 已提交
658

659
   /* Save the relevent information */
G
Guy Schalnat 已提交
660 661 662
   png_ptr->bit_depth = (png_byte)bit_depth;
   png_ptr->color_type = (png_byte)color_type;
   png_ptr->interlaced = (png_byte)interlace_type;
663
#ifdef PNG_MNG_FEATURES_SUPPORTED
664
   png_ptr->filter_type = (png_byte)filter_type;
665
#endif
666
   png_ptr->compression_type = (png_byte)compression_type;
G
Guy Schalnat 已提交
667 668 669
   png_ptr->width = width;
   png_ptr->height = height;

G
Guy Schalnat 已提交
670
   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
671
   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
672
   /* Set the usr info, so any transformations can modify it */
G
Guy Schalnat 已提交
673 674
   png_ptr->usr_width = png_ptr->width;
   png_ptr->usr_bit_depth = png_ptr->bit_depth;
G
Guy Schalnat 已提交
675 676
   png_ptr->usr_channels = png_ptr->channels;

677
   /* Pack the header information into the buffer */
G
Guy Schalnat 已提交
678 679 680 681 682 683 684
   png_save_uint_32(buf, width);
   png_save_uint_32(buf + 4, height);
   buf[8] = (png_byte)bit_depth;
   buf[9] = (png_byte)color_type;
   buf[10] = (png_byte)compression_type;
   buf[11] = (png_byte)filter_type;
   buf[12] = (png_byte)interlace_type;
G
Guy Schalnat 已提交
685

686
   /* Write the chunk */
687
   png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
G
Guy Schalnat 已提交
688

689
   /* Initialize zlib with PNG info */
A
Andreas Dilger 已提交
690 691 692
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;
693

G
Guy Schalnat 已提交
694
   if (!(png_ptr->do_filter))
G
Guy Schalnat 已提交
695
   {
A
Andreas Dilger 已提交
696
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
697
          png_ptr->bit_depth < 8)
G
Guy Schalnat 已提交
698
         png_ptr->do_filter = PNG_FILTER_NONE;
699

G
Guy Schalnat 已提交
700
      else
G
Guy Schalnat 已提交
701
         png_ptr->do_filter = PNG_ALL_FILTERS;
G
Guy Schalnat 已提交
702
   }
703

G
Guy Schalnat 已提交
704
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
G
Guy Schalnat 已提交
705
   {
G
Guy Schalnat 已提交
706
      if (png_ptr->do_filter != PNG_FILTER_NONE)
G
Guy Schalnat 已提交
707
         png_ptr->zlib_strategy = Z_FILTERED;
708

G
Guy Schalnat 已提交
709 710 711
      else
         png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
   }
712

G
Guy Schalnat 已提交
713
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
G
Guy Schalnat 已提交
714
      png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
715

G
Guy Schalnat 已提交
716
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
G
Guy Schalnat 已提交
717
      png_ptr->zlib_mem_level = 8;
718

G
Guy Schalnat 已提交
719
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
720
      png_ptr->zlib_window_bits = 15;
721

G
Guy Schalnat 已提交
722
   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
G
Guy Schalnat 已提交
723
      png_ptr->zlib_method = 8;
724

725
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
726 727 728
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION
   if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
      png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
729

730
   if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
731
      png_ptr->zlib_text_level = png_ptr->zlib_level;
732

733
   if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
734
      png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
735

736
   if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
737
      png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
738

739
   if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
740
      png_ptr->zlib_text_method = png_ptr->zlib_method;
741 742
#else
   png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
743 744 745 746
   png_ptr->zlib_text_level = png_ptr->zlib_level;
   png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
   png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
   png_ptr->zlib_text_method = png_ptr->zlib_method;
747
#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
748
#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
749 750 751 752 753

   /* Initialize the zlib compressor */
   ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
       png_ptr->zlib_method, png_ptr->zlib_window_bits,
       png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
G
Guy Schalnat 已提交
754

755
   png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
G
Guy Schalnat 已提交
756 757
}

758
/* Write the palette.  We are careful not to trust png_color to be in the
759
 * correct order for PNG, so people can redefine it to any convenient
760 761
 * structure.
 */
762
void /* PRIVATE */
763 764
png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
    png_uint_32 num_pal)
G
Guy Schalnat 已提交
765
{
766
   PNG_PLTE;
A
Andreas Dilger 已提交
767
   png_uint_32 i;
768
   png_const_colorp pal_ptr;
G
Guy Schalnat 已提交
769 770
   png_byte buf[3];

771
   png_debug(1, "in png_write_PLTE");
772

773
   if ((
774
#ifdef PNG_MNG_FEATURES_SUPPORTED
775
       !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
776
#endif
777
       num_pal == 0) || num_pal > 256)
778
   {
779 780 781 782
      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
      {
         png_error(png_ptr, "Invalid number of colors in palette");
      }
783

784 785 786 787 788
      else
      {
         png_warning(png_ptr, "Invalid number of colors in palette");
         return;
      }
789 790 791 792 793
   }

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

796
      return;
G
Guy Schalnat 已提交
797 798
   }

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

802
   png_write_chunk_start(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
803
#ifdef PNG_POINTER_INDEXING_SUPPORTED
804

A
Andreas Dilger 已提交
805
   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
G
Guy Schalnat 已提交
806 807 808 809
   {
      buf[0] = pal_ptr->red;
      buf[1] = pal_ptr->green;
      buf[2] = pal_ptr->blue;
810
      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
G
Guy Schalnat 已提交
811
   }
812

813
#else
814 815 816
   /* This is a little slower but some buggy compilers need to do this
    * instead
    */
817
   pal_ptr=palette;
818

819 820 821 822 823
   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;
824
      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
825
   }
826

827
#endif
G
Guy Schalnat 已提交
828
   png_write_chunk_end(png_ptr);
G
Guy Schalnat 已提交
829
   png_ptr->mode |= PNG_HAVE_PLTE;
G
Guy Schalnat 已提交
830 831
}

832
/* Write an IDAT chunk */
833
void /* PRIVATE */
A
Andreas Dilger 已提交
834
png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
G
Guy Schalnat 已提交
835
{
836
   PNG_IDAT;
837

838
   png_debug(1, "in png_write_IDAT");
839

840 841 842
   if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
       png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
   {
843
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
844
      unsigned int z_cmf;  /* zlib compression method and flags */
845
#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
846

847 848
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
      int ret;
849 850

      /* Reinitialize the compressor if necessary */
851 852 853 854
      if (png_ptr->mode & PNG_ZLIB_READY_FOR_ZTXT)
      {
         /* Free memory from previously opened zstream */
         deflateEnd(&png_ptr->zstream);
855

856 857 858
         ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
             png_ptr->zlib_method, png_ptr->zlib_window_bits,
             png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
859

860 861 862 863 864
         if (ret != Z_OK)
         {
            if (ret == Z_VERSION_ERROR)
               png_error(png_ptr,
                  "zlib failed to initialize compressor -- version error");
865

866 867 868
            if (ret == Z_STREAM_ERROR)
               png_error(png_ptr,
                   "zlib failed to initialize compressor -- stream error");
869

870 871 872
            if (ret == Z_MEM_ERROR)
               png_error(png_ptr,
                   "zlib failed to initialize compressor -- mem error");
873

874 875 876
            png_error(png_ptr, "zlib failed to initialize compressor");
         }
         png_ptr->mode &= ~PNG_ZLIB_READY_FOR_ZTXT; /* Ready for IDAT */
877
      }
878
#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
879 880 881 882 883 884 885 886

      png_ptr->zstream.next_out = png_ptr->zbuf;
      png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
      /* libpng is not interested in zstream.data_type, so set it
       * to a predefined value, to avoid its evaluation inside zlib
       */
      png_ptr->zstream.data_type = Z_BINARY;

887
#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
888 889 890
      /* Optimize the CMF field in the zlib stream.  This hack of the zlib
       * stream is compliant to the stream specification.
       */
891 892
      z_cmf = data[0];

893 894
      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
      {
895 896 897 898 899
         /* Avoid memory underflows and multiplication overflows.
          *
          * The conditions below are practically always satisfied;
          * however, they still must be checked.
          */
900 901 902
         if (length >= 2 &&
             png_ptr->height < 16384 && png_ptr->width < 16384)
         {
903 904 905
            /* Compute the maximum possible length of the datastream */

            /* Number of pixels, plus for each row a filter byte and possible
906 907
             * and possibly a padding byte, so increase the maximum
             * size to account for these.
908
             */
909 910
            unsigned int z_cinfo;
            unsigned int half_z_window_size;
911
            png_uint_32 uncompressed_idat_size = png_ptr->height *
912 913
                ((png_ptr->width *
                png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
914 915 916 917 918 919 920 921 922

            /* If it's interlaced, each block of 8 rows is sent as up to
             * 14 rows, i.e., 6 additional rows, each with a filter byte
             * and possibly a padding byte
             */
            if (png_ptr->interlaced)
               uncompressed_idat_size += ((png_ptr->height + 7)/8) *
                   (png_ptr->bit_depth < 8 ? 12 : 6);

923 924 925
            z_cinfo = z_cmf >> 4;
            half_z_window_size = 1 << (z_cinfo + 7);

926
            while (uncompressed_idat_size <= half_z_window_size &&
927
                half_z_window_size >= 256)
928 929 930 931
            {
               z_cinfo--;
               half_z_window_size >>= 1;
            }
932

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

935
            if (data[0] != z_cmf)
936
            {
937
               int tmp;
938
               data[0] = (png_byte)z_cmf;
939 940 941
               tmp = data[1] & 0xe0;
               tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
               data[1] = (png_byte)tmp;
942 943 944
            }
         }
      }
945

946 947
      else
         png_error(png_ptr,
948
             "Invalid zlib compression method or flags in IDAT");
949
#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
950 951
   }

952
   png_write_chunk(png_ptr, png_IDAT, data, length);
G
Guy Schalnat 已提交
953
   png_ptr->mode |= PNG_HAVE_IDAT;
G
Guy Schalnat 已提交
954 955
}

956
/* Write an IEND chunk */
957
void /* PRIVATE */
G
Guy Schalnat 已提交
958
png_write_IEND(png_structp png_ptr)
G
Guy Schalnat 已提交
959
{
960
   PNG_IEND;
961

962
   png_debug(1, "in png_write_IEND");
963

964
   png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
A
Andreas Dilger 已提交
965
   png_ptr->mode |= PNG_HAVE_IEND;
G
Guy Schalnat 已提交
966 967
}

968
#ifdef PNG_WRITE_gAMA_SUPPORTED
969
/* Write a gAMA chunk */
970
void /* PRIVATE */
971
png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
972 973 974 975
{
   PNG_gAMA;
   png_byte buf[4];

976
   png_debug(1, "in png_write_gAMA");
977

978
   /* file_gamma is saved in 1/100,000ths */
979
   png_save_uint_32(buf, (png_uint_32)file_gamma);
980
   png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
981 982
}
#endif
G
Guy Schalnat 已提交
983

984
#ifdef PNG_WRITE_sRGB_SUPPORTED
985
/* Write a sRGB chunk */
986
void /* PRIVATE */
987
png_write_sRGB(png_structp png_ptr, int srgb_intent)
988
{
989
   PNG_sRGB;
990 991
   png_byte buf[1];

992
   png_debug(1, "in png_write_sRGB");
993

994
   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
995 996
      png_warning(png_ptr,
          "Invalid sRGB rendering intent specified");
997

998
   buf[0]=(png_byte)srgb_intent;
999
   png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
1000 1001 1002
}
#endif

1003
#ifdef PNG_WRITE_iCCP_SUPPORTED
1004
/* Write an iCCP chunk */
1005
void /* PRIVATE */
1006 1007
png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
    png_const_charp profile, int profile_len)
1008 1009 1010 1011 1012
{
   PNG_iCCP;
   png_size_t name_len;
   png_charp new_name;
   compression_state comp;
1013
   int embedded_profile_len = 0;
1014

1015
   png_debug(1, "in png_write_iCCP");
1016 1017 1018 1019 1020 1021 1022

   comp.num_output_ptr = 0;
   comp.max_output_ptr = 0;
   comp.output_ptr = NULL;
   comp.input = NULL;
   comp.input_len = 0;

1023
   if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
1024 1025
      return;

1026
   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
1027
      png_warning(png_ptr, "Unknown compression type in iCCP chunk");
1028

1029
   if (profile == NULL)
1030 1031
      profile_len = 0;

1032
   if (profile_len > 3)
1033
      embedded_profile_len =
1034 1035 1036 1037
          ((*( (png_const_bytep)profile    ))<<24) |
          ((*( (png_const_bytep)profile + 1))<<16) |
          ((*( (png_const_bytep)profile + 2))<< 8) |
          ((*( (png_const_bytep)profile + 3))    );
1038

1039 1040 1041
   if (embedded_profile_len < 0)
   {
      png_warning(png_ptr,
1042
          "Embedded profile length in iCCP chunk is negative");
1043

1044 1045 1046 1047
      png_free(png_ptr, new_name);
      return;
   }

1048
   if (profile_len < embedded_profile_len)
1049 1050
   {
      png_warning(png_ptr,
1051
          "Embedded profile length too large in iCCP chunk");
1052

1053
      png_free(png_ptr, new_name);
1054 1055
      return;
   }
1056 1057

   if (profile_len > embedded_profile_len)
1058 1059
   {
      png_warning(png_ptr,
1060
          "Truncating profile to actual length in iCCP chunk");
1061

1062 1063
      profile_len = embedded_profile_len;
   }
1064

1065
   if (profile_len)
1066
      profile_len = png_text_compress(png_ptr, profile,
1067
          (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
1068

1069
   /* Make sure we include the NULL after the name and the compression type */
1070
   png_write_chunk_start(png_ptr, png_iCCP,
1071
       (png_uint_32)(name_len + profile_len + 2));
1072

1073
   new_name[name_len + 1] = 0x00;
1074

1075
   png_write_chunk_data(png_ptr, (png_bytep)new_name,
1076
       (png_size_t)(name_len + 2));
1077 1078

   if (profile_len)
1079 1080
   {
      comp.input_len = profile_len;
1081
      png_write_compressed_data_out(png_ptr, &comp);
1082
   }
1083 1084 1085 1086 1087 1088

   png_write_chunk_end(png_ptr);
   png_free(png_ptr, new_name);
}
#endif

1089
#ifdef PNG_WRITE_sPLT_SUPPORTED
1090
/* Write a sPLT chunk */
1091
void /* PRIVATE */
1092
png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
1093 1094 1095 1096 1097
{
   PNG_sPLT;
   png_size_t name_len;
   png_charp new_name;
   png_byte entrybuf[10];
1098 1099
   png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
   png_size_t palette_size = entry_size * spalette->nentries;
1100
   png_sPLT_entryp ep;
1101
#ifndef PNG_POINTER_INDEXING_SUPPORTED
1102 1103
   int i;
#endif
1104

1105
   png_debug(1, "in png_write_sPLT");
1106

1107 1108
   if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
      return;
1109

1110
   /* Make sure we include the NULL after the name */
1111
   png_write_chunk_start(png_ptr, png_sPLT,
1112
       (png_uint_32)(name_len + 2 + palette_size));
1113

1114
   png_write_chunk_data(png_ptr, (png_bytep)new_name,
1115
       (png_size_t)(name_len + 1));
1116

1117
   png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
1118

1119
   /* Loop through each palette entry, writing appropriately */
1120
#ifdef PNG_POINTER_INDEXING_SUPPORTED
1121
   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1122
   {
1123 1124
      if (spalette->depth == 8)
      {
1125 1126 1127 1128 1129
         entrybuf[0] = (png_byte)ep->red;
         entrybuf[1] = (png_byte)ep->green;
         entrybuf[2] = (png_byte)ep->blue;
         entrybuf[3] = (png_byte)ep->alpha;
         png_save_uint_16(entrybuf + 4, ep->frequency);
1130
      }
1131

1132 1133
      else
      {
1134 1135 1136 1137 1138
         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);
1139
      }
1140

1141
      png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
1142
   }
1143 1144
#else
   ep=spalette->entries;
1145
   for (i = 0; i>spalette->nentries; i++)
1146
   {
1147 1148
      if (spalette->depth == 8)
      {
1149 1150 1151 1152 1153
         entrybuf[0] = (png_byte)ep[i].red;
         entrybuf[1] = (png_byte)ep[i].green;
         entrybuf[2] = (png_byte)ep[i].blue;
         entrybuf[3] = (png_byte)ep[i].alpha;
         png_save_uint_16(entrybuf + 4, ep[i].frequency);
1154
      }
1155

1156 1157
      else
      {
1158 1159 1160 1161 1162
         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);
1163
      }
1164

1165
      png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
1166 1167
   }
#endif
1168 1169 1170 1171 1172 1173

   png_write_chunk_end(png_ptr);
   png_free(png_ptr, new_name);
}
#endif

1174
#ifdef PNG_WRITE_sBIT_SUPPORTED
1175
/* Write the sBIT chunk */
1176
void /* PRIVATE */
1177
png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
G
Guy Schalnat 已提交
1178
{
1179
   PNG_sBIT;
G
Guy Schalnat 已提交
1180
   png_byte buf[4];
A
Andreas Dilger 已提交
1181
   png_size_t size;
G
Guy Schalnat 已提交
1182

1183
   png_debug(1, "in png_write_sBIT");
1184

1185
   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
G
Guy Schalnat 已提交
1186 1187
   if (color_type & PNG_COLOR_MASK_COLOR)
   {
1188
      png_byte maxbits;
G
Guy Schalnat 已提交
1189

1190
      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
1191
          png_ptr->usr_bit_depth);
1192

1193 1194
      if (sbit->red == 0 || sbit->red > maxbits ||
          sbit->green == 0 || sbit->green > maxbits ||
G
Guy Schalnat 已提交
1195 1196 1197 1198 1199
          sbit->blue == 0 || sbit->blue > maxbits)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1200

G
Guy Schalnat 已提交
1201 1202 1203 1204 1205
      buf[0] = sbit->red;
      buf[1] = sbit->green;
      buf[2] = sbit->blue;
      size = 3;
   }
1206

G
Guy Schalnat 已提交
1207 1208
   else
   {
G
Guy Schalnat 已提交
1209 1210 1211 1212 1213
      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1214

G
Guy Schalnat 已提交
1215 1216 1217 1218 1219 1220
      buf[0] = sbit->gray;
      size = 1;
   }

   if (color_type & PNG_COLOR_MASK_ALPHA)
   {
G
Guy Schalnat 已提交
1221 1222 1223 1224 1225
      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
      {
         png_warning(png_ptr, "Invalid sBIT depth specified");
         return;
      }
1226

G
Guy Schalnat 已提交
1227 1228 1229
      buf[size++] = sbit->alpha;
   }

1230
   png_write_chunk(png_ptr, png_sBIT, buf, size);
G
Guy Schalnat 已提交
1231
}
G
Guy Schalnat 已提交
1232
#endif
G
Guy Schalnat 已提交
1233

1234
#ifdef PNG_WRITE_cHRM_SUPPORTED
1235
/* Write the cHRM chunk */
1236
void /* PRIVATE */
1237
png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
1238 1239 1240
    png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
    png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
    png_fixed_point blue_y)
1241 1242 1243 1244
{
   PNG_cHRM;
   png_byte buf[32];

1245
   png_debug(1, "in png_write_cHRM");
1246

1247
   /* Each value is saved in 1/100,000ths */
1248
#ifdef PNG_CHECK_cHRM_SUPPORTED
1249
   if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
1250
       green_x, green_y, blue_x, blue_y))
1251
#endif
1252
   {
1253 1254
      png_save_uint_32(buf, (png_uint_32)white_x);
      png_save_uint_32(buf + 4, (png_uint_32)white_y);
1255

1256 1257
      png_save_uint_32(buf + 8, (png_uint_32)red_x);
      png_save_uint_32(buf + 12, (png_uint_32)red_y);
1258

1259 1260
      png_save_uint_32(buf + 16, (png_uint_32)green_x);
      png_save_uint_32(buf + 20, (png_uint_32)green_y);
1261

1262 1263
      png_save_uint_32(buf + 24, (png_uint_32)blue_x);
      png_save_uint_32(buf + 28, (png_uint_32)blue_y);
1264

1265
      png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
1266
   }
1267 1268
}
#endif
G
Guy Schalnat 已提交
1269

1270
#ifdef PNG_WRITE_tRNS_SUPPORTED
1271
/* Write the tRNS chunk */
1272
void /* PRIVATE */
1273 1274
png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
    png_const_color_16p tran, int num_trans, int color_type)
G
Guy Schalnat 已提交
1275
{
1276
   PNG_tRNS;
G
Guy Schalnat 已提交
1277 1278
   png_byte buf[6];

1279
   png_debug(1, "in png_write_tRNS");
1280

G
Guy Schalnat 已提交
1281 1282
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1283
      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1284
      {
1285
         png_warning(png_ptr, "Invalid number of transparent colors specified");
G
Guy Schalnat 已提交
1286 1287
         return;
      }
1288

1289
      /* Write the chunk out as it is */
1290
      png_write_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
G
Guy Schalnat 已提交
1291
   }
1292

G
Guy Schalnat 已提交
1293 1294
   else if (color_type == PNG_COLOR_TYPE_GRAY)
   {
1295
      /* One 16 bit value */
1296
      if (tran->gray >= (1 << png_ptr->bit_depth))
1297 1298
      {
         png_warning(png_ptr,
1299
             "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1300

1301 1302
         return;
      }
1303

G
Guy Schalnat 已提交
1304
      png_save_uint_16(buf, tran->gray);
1305
      png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1306
   }
1307

G
Guy Schalnat 已提交
1308 1309
   else if (color_type == PNG_COLOR_TYPE_RGB)
   {
1310
      /* Three 16 bit values */
G
Guy Schalnat 已提交
1311 1312 1313
      png_save_uint_16(buf, tran->red);
      png_save_uint_16(buf + 2, tran->green);
      png_save_uint_16(buf + 4, tran->blue);
1314
#ifdef PNG_WRITE_16BIT_SUPPORTED
1315
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1316 1317 1318
#else
      if (buf[0] | buf[2] | buf[4])
#endif
1319 1320
      {
         png_warning(png_ptr,
1321
           "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1322 1323
         return;
      }
1324

1325
      png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
G
Guy Schalnat 已提交
1326
   }
1327

G
Guy Schalnat 已提交
1328 1329
   else
   {
1330
      png_warning(png_ptr, "Can't write tRNS with an alpha channel");
G
Guy Schalnat 已提交
1331
   }
G
Guy Schalnat 已提交
1332
}
G
Guy Schalnat 已提交
1333
#endif
G
Guy Schalnat 已提交
1334

1335
#ifdef PNG_WRITE_bKGD_SUPPORTED
1336
/* Write the background chunk */
1337
void /* PRIVATE */
1338
png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
G
Guy Schalnat 已提交
1339
{
1340
   PNG_bKGD;
G
Guy Schalnat 已提交
1341 1342
   png_byte buf[6];

1343
   png_debug(1, "in png_write_bKGD");
1344

G
Guy Schalnat 已提交
1345 1346
   if (color_type == PNG_COLOR_TYPE_PALETTE)
   {
1347
      if (
1348
#ifdef PNG_MNG_FEATURES_SUPPORTED
1349 1350
          (png_ptr->num_palette ||
          (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
1351
#endif
1352
         back->index >= png_ptr->num_palette)
G
Guy Schalnat 已提交
1353 1354 1355 1356
      {
         png_warning(png_ptr, "Invalid background palette index");
         return;
      }
1357

G
Guy Schalnat 已提交
1358
      buf[0] = back->index;
1359
      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
G
Guy Schalnat 已提交
1360
   }
1361

G
Guy Schalnat 已提交
1362 1363 1364 1365 1366
   else if (color_type & PNG_COLOR_MASK_COLOR)
   {
      png_save_uint_16(buf, back->red);
      png_save_uint_16(buf + 2, back->green);
      png_save_uint_16(buf + 4, back->blue);
1367
#ifdef PNG_WRITE_16BIT_SUPPORTED
1368
      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1369 1370 1371
#else
      if (buf[0] | buf[2] | buf[4])
#endif
1372 1373
      {
         png_warning(png_ptr,
1374
             "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
1375

1376 1377
         return;
      }
1378

1379
      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
G
Guy Schalnat 已提交
1380
   }
1381

G
Guy Schalnat 已提交
1382
   else
G
Guy Schalnat 已提交
1383
   {
1384
      if (back->gray >= (1 << png_ptr->bit_depth))
1385 1386
      {
         png_warning(png_ptr,
1387
             "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1388

1389 1390
         return;
      }
1391

G
Guy Schalnat 已提交
1392
      png_save_uint_16(buf, back->gray);
1393
      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1394 1395
   }
}
G
Guy Schalnat 已提交
1396
#endif
G
Guy Schalnat 已提交
1397

1398
#ifdef PNG_WRITE_hIST_SUPPORTED
1399
/* Write the histogram */
1400
void /* PRIVATE */
1401
png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
G
Guy Schalnat 已提交
1402
{
1403
   PNG_hIST;
1404
   int i;
G
Guy Schalnat 已提交
1405 1406
   png_byte buf[3];

1407
   png_debug(1, "in png_write_hIST");
1408

1409
   if (num_hist > (int)png_ptr->num_palette)
G
Guy Schalnat 已提交
1410
   {
1411
      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1412
          png_ptr->num_palette);
1413

G
Guy Schalnat 已提交
1414 1415 1416 1417
      png_warning(png_ptr, "Invalid number of histogram entries specified");
      return;
   }

1418
   png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1419

A
Andreas Dilger 已提交
1420
   for (i = 0; i < num_hist; i++)
G
Guy Schalnat 已提交
1421
   {
G
Guy Schalnat 已提交
1422
      png_save_uint_16(buf, hist[i]);
1423
      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
G
Guy Schalnat 已提交
1424
   }
1425

G
Guy Schalnat 已提交
1426 1427
   png_write_chunk_end(png_ptr);
}
G
Guy Schalnat 已提交
1428
#endif
G
Guy Schalnat 已提交
1429

1430 1431
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
A
Andreas Dilger 已提交
1432 1433 1434 1435 1436
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
 * and if invalid, correct the keyword rather than discarding the entire
 * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
 * length, forbids leading or trailing whitespace, multiple internal spaces,
 * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
A
Andreas Dilger 已提交
1437 1438 1439 1440
 *
 * The new_key is allocated to hold the corrected keyword and must be freed
 * by the calling routine.  This avoids problems with trying to write to
 * static keywords without having to have duplicate copies of the strings.
A
Andreas Dilger 已提交
1441
 */
1442
png_size_t /* PRIVATE */
1443
png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
A
Andreas Dilger 已提交
1444
{
A
Andreas Dilger 已提交
1445
   png_size_t key_len;
1446
   png_const_charp ikp;
1447
   png_charp kp, dp;
A
Andreas Dilger 已提交
1448
   int kflag;
1449
   int kwarn=0;
A
Andreas Dilger 已提交
1450

1451
   png_debug(1, "in png_check_keyword");
1452

A
Andreas Dilger 已提交
1453 1454 1455
   *new_key = NULL;

   if (key == NULL || (key_len = png_strlen(key)) == 0)
A
Andreas Dilger 已提交
1456
   {
1457
      png_warning(png_ptr, "zero length keyword");
1458
      return ((png_size_t)0);
A
Andreas Dilger 已提交
1459
   }
A
Andreas Dilger 已提交
1460

1461
   png_debug1(2, "Keyword to be checked is '%s'", key);
A
Andreas Dilger 已提交
1462

1463
   *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
1464

1465 1466 1467
   if (*new_key == NULL)
   {
      png_warning(png_ptr, "Out of memory while procesing keyword");
1468
      return ((png_size_t)0);
1469
   }
1470

A
Andreas Dilger 已提交
1471
   /* Replace non-printing characters with a blank and print a warning */
1472
   for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
A
Andreas Dilger 已提交
1473
   {
1474 1475
      if ((png_byte)*ikp < 0x20 ||
         ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
A
Andreas Dilger 已提交
1476
      {
1477
         PNG_WARNING_PARAMETERS(p)
A
Andreas Dilger 已提交
1478

1479 1480 1481
         png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
            *ikp);
         png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
A
Andreas Dilger 已提交
1482 1483
         *dp = ' ';
      }
1484

A
Andreas Dilger 已提交
1485 1486
      else
      {
1487
         *dp = *ikp;
A
Andreas Dilger 已提交
1488
      }
A
Andreas Dilger 已提交
1489
   }
A
Andreas Dilger 已提交
1490
   *dp = '\0';
A
Andreas Dilger 已提交
1491

A
Andreas Dilger 已提交
1492 1493 1494
   /* Remove any trailing white space. */
   kp = *new_key + key_len - 1;
   if (*kp == ' ')
A
Andreas Dilger 已提交
1495
   {
1496
      png_warning(png_ptr, "trailing spaces removed from keyword");
A
Andreas Dilger 已提交
1497 1498 1499

      while (*kp == ' ')
      {
1500 1501
         *(kp--) = '\0';
         key_len--;
A
Andreas Dilger 已提交
1502
      }
A
Andreas Dilger 已提交
1503 1504 1505
   }

   /* Remove any leading white space. */
A
Andreas Dilger 已提交
1506 1507
   kp = *new_key;
   if (*kp == ' ')
A
Andreas Dilger 已提交
1508
   {
1509
      png_warning(png_ptr, "leading spaces removed from keyword");
A
Andreas Dilger 已提交
1510 1511 1512

      while (*kp == ' ')
      {
1513 1514
         kp++;
         key_len--;
A
Andreas Dilger 已提交
1515
      }
A
Andreas Dilger 已提交
1516 1517
   }

1518
   png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
A
Andreas Dilger 已提交
1519 1520 1521

   /* Remove multiple internal spaces. */
   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
A
Andreas Dilger 已提交
1522
   {
A
Andreas Dilger 已提交
1523
      if (*kp == ' ' && kflag == 0)
A
Andreas Dilger 已提交
1524
      {
A
Andreas Dilger 已提交
1525 1526
         *(dp++) = *kp;
         kflag = 1;
A
Andreas Dilger 已提交
1527
      }
1528

A
Andreas Dilger 已提交
1529
      else if (*kp == ' ')
A
Andreas Dilger 已提交
1530 1531
      {
         key_len--;
1532
         kwarn = 1;
A
Andreas Dilger 已提交
1533
      }
1534

A
Andreas Dilger 已提交
1535 1536
      else
      {
A
Andreas Dilger 已提交
1537 1538
         *(dp++) = *kp;
         kflag = 0;
A
Andreas Dilger 已提交
1539 1540
      }
   }
A
Andreas Dilger 已提交
1541
   *dp = '\0';
1542
   if (kwarn)
1543
      png_warning(png_ptr, "extra interior spaces removed from keyword");
A
Andreas Dilger 已提交
1544 1545

   if (key_len == 0)
A
Andreas Dilger 已提交
1546
   {
1547
      png_free(png_ptr, *new_key);
1548
      png_warning(png_ptr, "Zero length keyword");
A
Andreas Dilger 已提交
1549 1550 1551 1552
   }

   if (key_len > 79)
   {
1553
      png_warning(png_ptr, "keyword length must be 1 - 79 characters");
1554
      (*new_key)[79] = '\0';
A
Andreas Dilger 已提交
1555 1556
      key_len = 79;
   }
A
Andreas Dilger 已提交
1557

1558
   return (key_len);
A
Andreas Dilger 已提交
1559 1560 1561
}
#endif

1562
#ifdef PNG_WRITE_tEXt_SUPPORTED
1563
/* Write a tEXt chunk */
1564
void /* PRIVATE */
1565
png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
1566
    png_size_t text_len)
G
Guy Schalnat 已提交
1567
{
1568
   PNG_tEXt;
A
Andreas Dilger 已提交
1569
   png_size_t key_len;
1570
   png_charp new_key;
A
Andreas Dilger 已提交
1571

1572
   png_debug(1, "in png_write_tEXt");
1573

1574
   if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
G
Guy Schalnat 已提交
1575 1576
      return;

A
Andreas Dilger 已提交
1577
   if (text == NULL || *text == '\0')
A
Andreas Dilger 已提交
1578
      text_len = 0;
1579

1580 1581
   else
      text_len = png_strlen(text);
A
Andreas Dilger 已提交
1582

1583
   /* Make sure we include the 0 after the key */
1584
   png_write_chunk_start(png_ptr, png_tEXt,
1585
       (png_uint_32)(key_len + text_len + 1));
1586 1587 1588 1589
   /*
    * 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.
1590
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1591
    */
1592
   png_write_chunk_data(png_ptr, (png_bytep)new_key,
1593
       (png_size_t)(key_len + 1));
1594

A
Andreas Dilger 已提交
1595
   if (text_len)
1596
      png_write_chunk_data(png_ptr, (png_const_bytep)text,
1597
          (png_size_t)text_len);
A
Andreas Dilger 已提交
1598

G
Guy Schalnat 已提交
1599
   png_write_chunk_end(png_ptr);
A
Andreas Dilger 已提交
1600
   png_free(png_ptr, new_key);
G
Guy Schalnat 已提交
1601
}
G
Guy Schalnat 已提交
1602
#endif
G
Guy Schalnat 已提交
1603

1604
#ifdef PNG_WRITE_zTXt_SUPPORTED
1605
/* Write a compressed text chunk */
1606
void /* PRIVATE */
1607
png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
1608
    png_size_t text_len, int compression)
G
Guy Schalnat 已提交
1609
{
1610
   PNG_zTXt;
A
Andreas Dilger 已提交
1611
   png_size_t key_len;
1612
   png_byte buf;
1613
   png_charp new_key;
1614
   compression_state comp;
G
Guy Schalnat 已提交
1615

1616
   png_debug(1, "in png_write_zTXt");
A
Andreas Dilger 已提交
1617

1618 1619 1620 1621 1622 1623
   comp.num_output_ptr = 0;
   comp.max_output_ptr = 0;
   comp.output_ptr = NULL;
   comp.input = NULL;
   comp.input_len = 0;

1624
   if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
A
Andreas Dilger 已提交
1625
   {
1626
      png_free(png_ptr, new_key);
G
Guy Schalnat 已提交
1627
      return;
A
Andreas Dilger 已提交
1628
   }
A
Andreas Dilger 已提交
1629

A
Andreas Dilger 已提交
1630 1631
   if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
   {
1632
      png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
A
Andreas Dilger 已提交
1633 1634 1635 1636
      png_free(png_ptr, new_key);
      return;
   }

1637 1638
   text_len = png_strlen(text);

1639
   /* Compute the compressed data; do it now for the length */
1640 1641
   text_len = png_text_compress(png_ptr, text, text_len, compression,
       &comp);
G
Guy Schalnat 已提交
1642

1643
   /* Write start of chunk */
1644
   png_write_chunk_start(png_ptr, png_zTXt,
1645
       (png_uint_32)(key_len+text_len + 2));
1646

1647
   /* Write key */
1648
   png_write_chunk_data(png_ptr, (png_bytep)new_key,
1649
       (png_size_t)(key_len + 1));
1650

1651 1652
   png_free(png_ptr, new_key);

1653
   buf = (png_byte)compression;
1654

1655
   /* Write compression */
1656
   png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
1657

1658
   /* Write the compressed data */
1659
   comp.input_len = text_len;
1660
   png_write_compressed_data_out(png_ptr, &comp);
G
Guy Schalnat 已提交
1661

1662
   /* Close the chunk */
1663 1664 1665
   png_write_chunk_end(png_ptr);
}
#endif
G
Guy Schalnat 已提交
1666

1667
#ifdef PNG_WRITE_iTXt_SUPPORTED
1668
/* Write an iTXt chunk */
1669
void /* PRIVATE */
1670 1671
png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
    png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1672 1673
{
   PNG_iTXt;
1674
   png_size_t lang_len, key_len, lang_key_len, text_len;
1675 1676
   png_charp new_lang;
   png_charp new_key = NULL;
1677 1678
   png_byte cbuf[2];
   compression_state comp;
G
Guy Schalnat 已提交
1679

1680
   png_debug(1, "in png_write_iTXt");
G
Guy Schalnat 已提交
1681

1682 1683 1684 1685 1686
   comp.num_output_ptr = 0;
   comp.max_output_ptr = 0;
   comp.output_ptr = NULL;
   comp.input = NULL;

1687
   if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
1688
      return;
1689

1690
   if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
1691
   {
1692
      png_warning(png_ptr, "Empty language field in iTXt chunk");
1693
      new_lang = NULL;
1694
      lang_len = 0;
1695
   }
G
Guy Schalnat 已提交
1696

1697
   if (lang_key == NULL)
1698
      lang_key_len = 0;
1699

1700
   else
1701
      lang_key_len = png_strlen(lang_key);
1702 1703

   if (text == NULL)
1704
      text_len = 0;
1705

1706
   else
1707
      text_len = png_strlen(text);
G
Guy Schalnat 已提交
1708

1709
   /* Compute the compressed data; do it now for the length */
1710
   text_len = png_text_compress(png_ptr, text, text_len, compression - 2,
1711
       &comp);
G
Guy Schalnat 已提交
1712

1713

1714
   /* Make sure we include the compression flag, the compression byte,
1715 1716
    * and the NULs after the key, lang, and lang_key parts
    */
G
Guy Schalnat 已提交
1717

1718
   png_write_chunk_start(png_ptr, png_iTXt, (png_uint_32)(
1719 1720 1721 1722 1723
        5 /* comp byte, comp flag, terminators for key, lang and lang_key */
        + key_len
        + lang_len
        + lang_key_len
        + text_len));
G
Guy Schalnat 已提交
1724

1725
   /* We leave it to the application to meet PNG-1.0 requirements on the
1726 1727 1728 1729
    * 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.
    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
    */
1730
   png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
1731

1732
   /* Set the compression flag */
1733
   if (compression == PNG_ITXT_COMPRESSION_NONE ||
1734
       compression == PNG_TEXT_COMPRESSION_NONE)
1735
      cbuf[0] = 0;
1736

1737
   else /* compression == PNG_ITXT_COMPRESSION_zTXt */
1738
      cbuf[0] = 1;
1739

1740
   /* Set the compression method */
1741
   cbuf[1] = 0;
1742

1743
   png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
1744

1745
   cbuf[0] = 0;
1746
   png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
1747
       (png_size_t)(lang_len + 1));
1748

1749
   png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
1750
       (png_size_t)(lang_key_len + 1));
1751

1752
   png_write_compressed_data_out(png_ptr, &comp);
G
Guy Schalnat 已提交
1753 1754

   png_write_chunk_end(png_ptr);
1755

1756
   png_free(png_ptr, new_key);
1757
   png_free(png_ptr, new_lang);
G
Guy Schalnat 已提交
1758
}
G
Guy Schalnat 已提交
1759
#endif
G
Guy Schalnat 已提交
1760

1761
#ifdef PNG_WRITE_oFFs_SUPPORTED
1762
/* Write the oFFs chunk */
1763
void /* PRIVATE */
1764
png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1765
    int unit_type)
G
Guy Schalnat 已提交
1766
{
1767
   PNG_oFFs;
G
Guy Schalnat 已提交
1768 1769
   png_byte buf[9];

1770
   png_debug(1, "in png_write_oFFs");
1771

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

1775 1776
   png_save_int_32(buf, x_offset);
   png_save_int_32(buf + 4, y_offset);
G
Guy Schalnat 已提交
1777
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1778

1779
   png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
G
Guy Schalnat 已提交
1780
}
G
Guy Schalnat 已提交
1781
#endif
1782
#ifdef PNG_WRITE_pCAL_SUPPORTED
1783
/* Write the pCAL chunk (described in the PNG extensions document) */
1784
void /* PRIVATE */
A
Andreas Dilger 已提交
1785
png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
1786 1787
    png_int_32 X1, int type, int nparams, png_const_charp units,
    png_charpp params)
A
Andreas Dilger 已提交
1788
{
1789
   PNG_pCAL;
1790
   png_size_t purpose_len, units_len, total_len;
A
Andreas Dilger 已提交
1791 1792
   png_uint_32p params_len;
   png_byte buf[10];
1793
   png_charp new_purpose;
A
Andreas Dilger 已提交
1794 1795
   int i;

1796
   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1797

A
Andreas Dilger 已提交
1798 1799 1800 1801
   if (type >= PNG_EQUATION_LAST)
      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");

   purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
1802
   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
A
Andreas Dilger 已提交
1803
   units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
1804
   png_debug1(3, "pCAL units length = %d", (int)units_len);
A
Andreas Dilger 已提交
1805 1806
   total_len = purpose_len + units_len + 10;

1807
   params_len = (png_uint_32p)png_malloc(png_ptr,
1808
       (png_alloc_size_t)(nparams * png_sizeof(png_uint_32)));
A
Andreas Dilger 已提交
1809 1810

   /* Find the length of each parameter, making sure we don't count the
1811 1812
    * null terminator for the last parameter.
    */
A
Andreas Dilger 已提交
1813 1814 1815
   for (i = 0; i < nparams; i++)
   {
      params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1816
      png_debug2(3, "pCAL parameter %d length = %lu", i,
1817
          (unsigned long)params_len[i]);
A
Andreas Dilger 已提交
1818 1819 1820
      total_len += (png_size_t)params_len[i];
   }

1821
   png_debug1(3, "pCAL total length = %d", (int)total_len);
1822 1823
   png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len);
   png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose,
1824
       (png_size_t)purpose_len);
A
Andreas Dilger 已提交
1825 1826 1827 1828
   png_save_int_32(buf, X0);
   png_save_int_32(buf + 4, X1);
   buf[8] = (png_byte)type;
   buf[9] = (png_byte)nparams;
1829
   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
1830
   png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
A
Andreas Dilger 已提交
1831 1832 1833 1834 1835

   png_free(png_ptr, new_purpose);

   for (i = 0; i < nparams; i++)
   {
1836
      png_write_chunk_data(png_ptr, (png_const_bytep)params[i],
1837
          (png_size_t)params_len[i]);
A
Andreas Dilger 已提交
1838 1839
   }

1840
   png_free(png_ptr, params_len);
A
Andreas Dilger 已提交
1841 1842 1843 1844
   png_write_chunk_end(png_ptr);
}
#endif

1845
#ifdef PNG_WRITE_sCAL_SUPPORTED
1846
/* Write the sCAL chunk */
1847
void /* PRIVATE */
1848 1849
png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
    png_const_charp height)
1850 1851
{
   PNG_sCAL;
1852 1853
   png_byte buf[64];
   png_size_t wlen, hlen, total_len;
1854

1855
   png_debug(1, "in png_write_sCAL_s");
1856

1857 1858 1859
   wlen = png_strlen(width);
   hlen = png_strlen(height);
   total_len = wlen + hlen + 2;
1860

1861 1862 1863 1864 1865
   if (total_len > 64)
   {
      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
      return;
   }
1866

1867
   buf[0] = (png_byte)unit;
1868 1869
   png_memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
   png_memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
1870

1871
   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1872
   png_write_chunk(png_ptr, png_sCAL, buf, total_len);
1873 1874 1875
}
#endif

1876
#ifdef PNG_WRITE_pHYs_SUPPORTED
1877
/* Write the pHYs chunk */
1878
void /* PRIVATE */
A
Andreas Dilger 已提交
1879
png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1880 1881
    png_uint_32 y_pixels_per_unit,
    int unit_type)
G
Guy Schalnat 已提交
1882
{
1883
   PNG_pHYs;
G
Guy Schalnat 已提交
1884 1885
   png_byte buf[9];

1886
   png_debug(1, "in png_write_pHYs");
1887

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

A
Andreas Dilger 已提交
1891 1892
   png_save_uint_32(buf, x_pixels_per_unit);
   png_save_uint_32(buf + 4, y_pixels_per_unit);
G
Guy Schalnat 已提交
1893
   buf[8] = (png_byte)unit_type;
G
Guy Schalnat 已提交
1894

1895
   png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
G
Guy Schalnat 已提交
1896
}
G
Guy Schalnat 已提交
1897
#endif
G
Guy Schalnat 已提交
1898

1899
#ifdef PNG_WRITE_tIME_SUPPORTED
1900 1901 1902
/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
 * or png_convert_from_time_t(), or fill in the structure yourself.
 */
1903
void /* PRIVATE */
1904
png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
G
Guy Schalnat 已提交
1905
{
1906
   PNG_tIME;
G
Guy Schalnat 已提交
1907 1908
   png_byte buf[7];

1909
   png_debug(1, "in png_write_tIME");
1910

G
Guy Schalnat 已提交
1911 1912 1913 1914 1915 1916 1917 1918
   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 已提交
1919 1920 1921 1922 1923 1924 1925
   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;

1926
   png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
G
Guy Schalnat 已提交
1927
}
G
Guy Schalnat 已提交
1928
#endif
G
Guy Schalnat 已提交
1929

1930
/* Initializes the row writing capability of libpng */
1931
void /* PRIVATE */
G
Guy Schalnat 已提交
1932
png_write_start_row(png_structp png_ptr)
G
Guy Schalnat 已提交
1933
{
1934
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1935
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1936

1937
   /* Start of interlace block */
1938
   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1939

1940
   /* Offset to next interlace block */
1941
   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1942

1943
   /* Start of interlace block in the y direction */
1944
   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1945

1946
   /* Offset to next interlace block in the y direction */
1947
   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1948
#endif
1949

A
Andreas Dilger 已提交
1950 1951
   png_size_t buf_size;

1952
   png_debug(1, "in png_write_start_row");
1953

1954
   buf_size = (png_size_t)(PNG_ROWBYTES(
1955
       png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
A
Andreas Dilger 已提交
1956

1957
   /* Set up row buffer */
1958
   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
1959
       (png_alloc_size_t)buf_size);
1960

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

1963
#ifdef PNG_WRITE_FILTER_SUPPORTED
1964
   /* Set up filtering buffer, if using this filter */
G
Guy Schalnat 已提交
1965
   if (png_ptr->do_filter & PNG_FILTER_SUB)
G
Guy Schalnat 已提交
1966
   {
1967
      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
1968

A
Andreas Dilger 已提交
1969
      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
G
Guy Schalnat 已提交
1970 1971
   }

A
Andreas Dilger 已提交
1972
   /* We only need to keep the previous row if we are using one of these. */
G
Guy Schalnat 已提交
1973 1974
   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
   {
1975 1976
      /* Set up previous row buffer */
      png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
1977
          (png_alloc_size_t)buf_size);
G
Guy Schalnat 已提交
1978 1979 1980

      if (png_ptr->do_filter & PNG_FILTER_UP)
      {
1981
         png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
1982
            png_ptr->rowbytes + 1);
1983

A
Andreas Dilger 已提交
1984
         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
G
Guy Schalnat 已提交
1985 1986 1987 1988
      }

      if (png_ptr->do_filter & PNG_FILTER_AVG)
      {
1989
         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
1990
             png_ptr->rowbytes + 1);
1991

A
Andreas Dilger 已提交
1992
         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
G
Guy Schalnat 已提交
1993 1994 1995 1996
      }

      if (png_ptr->do_filter & PNG_FILTER_PAETH)
      {
1997
         png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
1998
             png_ptr->rowbytes + 1);
1999

A
Andreas Dilger 已提交
2000
         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
G
Guy Schalnat 已提交
2001
      }
G
Guy Schalnat 已提交
2002
   }
2003
#endif /* PNG_WRITE_FILTER_SUPPORTED */
G
Guy Schalnat 已提交
2004

2005
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2006
   /* If interlaced, we need to set up width and height of pass */
G
Guy Schalnat 已提交
2007
   if (png_ptr->interlaced)
G
Guy Schalnat 已提交
2008 2009 2010 2011
   {
      if (!(png_ptr->transformations & PNG_INTERLACE))
      {
         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2012
             png_pass_ystart[0]) / png_pass_yinc[0];
2013

A
Andreas Dilger 已提交
2014
         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2015
             png_pass_start[0]) / png_pass_inc[0];
G
Guy Schalnat 已提交
2016
      }
2017

G
Guy Schalnat 已提交
2018 2019 2020 2021 2022 2023
      else
      {
         png_ptr->num_rows = png_ptr->height;
         png_ptr->usr_width = png_ptr->width;
      }
   }
2024

G
Guy Schalnat 已提交
2025
   else
2026
#endif
G
Guy Schalnat 已提交
2027
   {
G
Guy Schalnat 已提交
2028 2029 2030
      png_ptr->num_rows = png_ptr->height;
      png_ptr->usr_width = png_ptr->width;
   }
2031

A
Andreas Dilger 已提交
2032 2033
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
   png_ptr->zstream.next_out = png_ptr->zbuf;
G
Guy Schalnat 已提交
2034 2035
}

A
Andreas Dilger 已提交
2036
/* Internal use only.  Called when finished processing a row of data. */
2037
void /* PRIVATE */
G
Guy Schalnat 已提交
2038
png_write_finish_row(png_structp png_ptr)
G
Guy Schalnat 已提交
2039
{
2040
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2041
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2042

2043
   /* Start of interlace block */
2044
   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2045

2046
   /* Offset to next interlace block */
2047
   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2048

2049
   /* Start of interlace block in the y direction */
2050
   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2051

2052
   /* Offset to next interlace block in the y direction */
2053
   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2054
#endif
2055

G
Guy Schalnat 已提交
2056 2057
   int ret;

2058
   png_debug(1, "in png_write_finish_row");
2059

2060
   /* Next row */
G
Guy Schalnat 已提交
2061
   png_ptr->row_number++;
G
Guy Schalnat 已提交
2062

2063
   /* See if we are done */
G
Guy Schalnat 已提交
2064
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
2065
      return;
G
Guy Schalnat 已提交
2066

2067
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2068
   /* If interlaced, go to next pass */
G
Guy Schalnat 已提交
2069 2070 2071 2072 2073 2074 2075
   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
      if (png_ptr->transformations & PNG_INTERLACE)
      {
         png_ptr->pass++;
      }
2076

G
Guy Schalnat 已提交
2077 2078
      else
      {
2079
         /* Loop until we find a non-zero width or height pass */
G
Guy Schalnat 已提交
2080 2081 2082
         do
         {
            png_ptr->pass++;
2083

G
Guy Schalnat 已提交
2084 2085
            if (png_ptr->pass >= 7)
               break;
2086

G
Guy Schalnat 已提交
2087
            png_ptr->usr_width = (png_ptr->width +
2088 2089 2090
                png_pass_inc[png_ptr->pass] - 1 -
                png_pass_start[png_ptr->pass]) /
                png_pass_inc[png_ptr->pass];
2091

G
Guy Schalnat 已提交
2092
            png_ptr->num_rows = (png_ptr->height +
2093 2094 2095
                png_pass_yinc[png_ptr->pass] - 1 -
                png_pass_ystart[png_ptr->pass]) /
                png_pass_yinc[png_ptr->pass];
2096

G
Guy Schalnat 已提交
2097 2098
            if (png_ptr->transformations & PNG_INTERLACE)
               break;
2099

G
Guy Schalnat 已提交
2100 2101 2102 2103
         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);

      }

2104
      /* Reset the row above the image for the next pass */
G
Guy Schalnat 已提交
2105
      if (png_ptr->pass < 7)
G
Guy Schalnat 已提交
2106
      {
A
Andreas Dilger 已提交
2107
         if (png_ptr->prev_row != NULL)
2108
            png_memset(png_ptr->prev_row, 0,
2109 2110
                (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
                png_ptr->usr_bit_depth, png_ptr->width)) + 1);
2111

G
Guy Schalnat 已提交
2112
         return;
G
Guy Schalnat 已提交
2113
      }
G
Guy Schalnat 已提交
2114
   }
2115
#endif
G
Guy Schalnat 已提交
2116

2117
   /* If we get here, we've just written the last row, so we need
G
Guy Schalnat 已提交
2118 2119 2120
      to flush the compressor */
   do
   {
2121
      /* Tell the compressor we are done */
A
Andreas Dilger 已提交
2122
      ret = deflate(&png_ptr->zstream, Z_FINISH);
2123

2124
      /* Check for an error */
2125 2126
      if (ret == Z_OK)
      {
2127
         /* Check to see if we need more room */
2128 2129 2130 2131 2132 2133 2134
         if (!(png_ptr->zstream.avail_out))
         {
            png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
            png_ptr->zstream.next_out = png_ptr->zbuf;
            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
         }
      }
2135

2136
      else if (ret != Z_STREAM_END)
G
Guy Schalnat 已提交
2137
      {
A
Andreas Dilger 已提交
2138
         if (png_ptr->zstream.msg != NULL)
A
Andreas Dilger 已提交
2139
            png_error(png_ptr, png_ptr->zstream.msg);
2140

G
Guy Schalnat 已提交
2141
         else
G
Guy Schalnat 已提交
2142
            png_error(png_ptr, "zlib error");
G
Guy Schalnat 已提交
2143 2144 2145
      }
   } while (ret != Z_STREAM_END);

2146
   /* Write any extra space */
A
Andreas Dilger 已提交
2147
   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
G
Guy Schalnat 已提交
2148 2149
   {
      png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
2150
          png_ptr->zstream.avail_out);
G
Guy Schalnat 已提交
2151 2152
   }

A
Andreas Dilger 已提交
2153
   deflateReset(&png_ptr->zstream);
2154
   png_ptr->zstream.data_type = Z_BINARY;
G
Guy Schalnat 已提交
2155 2156
}

2157
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2158 2159 2160 2161 2162 2163 2164
/* 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.
 */
2165
void /* PRIVATE */
G
Guy Schalnat 已提交
2166
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
G
Guy Schalnat 已提交
2167
{
2168
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2169

2170
   /* Start of interlace block */
2171
   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2172

2173
   /* Offset to next interlace block */
2174
   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2175

2176
   png_debug(1, "in png_do_write_interlace");
2177

2178
   /* We don't have to do anything on the last pass (6) */
A
Andreas Dilger 已提交
2179
   if (pass < 6)
G
Guy Schalnat 已提交
2180
   {
2181
      /* Each pixel depth is handled separately */
G
Guy Schalnat 已提交
2182
      switch (row_info->pixel_depth)
G
Guy Schalnat 已提交
2183
      {
G
Guy Schalnat 已提交
2184 2185
         case 1:
         {
G
Guy Schalnat 已提交
2186 2187
            png_bytep sp;
            png_bytep dp;
G
Guy Schalnat 已提交
2188 2189 2190
            int shift;
            int d;
            int value;
2191 2192
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2193 2194 2195 2196

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

2198
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2199 2200 2201
               i += png_pass_inc[pass])
            {
               sp = row + (png_size_t)(i >> 3);
2202
               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
G
Guy Schalnat 已提交
2203 2204 2205 2206 2207
               d |= (value << shift);

               if (shift == 0)
               {
                  shift = 7;
G
Guy Schalnat 已提交
2208
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2209 2210
                  d = 0;
               }
2211

G
Guy Schalnat 已提交
2212 2213 2214 2215 2216
               else
                  shift--;

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

G
Guy Schalnat 已提交
2219 2220
            break;
         }
2221

G
Guy Schalnat 已提交
2222
         case 2:
G
Guy Schalnat 已提交
2223
         {
G
Guy Schalnat 已提交
2224 2225
            png_bytep sp;
            png_bytep dp;
G
Guy Schalnat 已提交
2226 2227 2228
            int shift;
            int d;
            int value;
2229 2230
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2231 2232 2233 2234

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

2236
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2237 2238 2239
               i += png_pass_inc[pass])
            {
               sp = row + (png_size_t)(i >> 2);
2240
               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
G
Guy Schalnat 已提交
2241 2242 2243 2244 2245
               d |= (value << shift);

               if (shift == 0)
               {
                  shift = 6;
G
Guy Schalnat 已提交
2246
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2247 2248
                  d = 0;
               }
2249

G
Guy Schalnat 已提交
2250 2251 2252 2253
               else
                  shift -= 2;
            }
            if (shift != 6)
2254 2255
               *dp = (png_byte)d;

G
Guy Schalnat 已提交
2256 2257
            break;
         }
2258

G
Guy Schalnat 已提交
2259 2260
         case 4:
         {
G
Guy Schalnat 已提交
2261 2262
            png_bytep sp;
            png_bytep dp;
G
Guy Schalnat 已提交
2263
            int shift;
G
Guy Schalnat 已提交
2264 2265
            int d;
            int value;
2266 2267
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
G
Guy Schalnat 已提交
2268 2269 2270 2271

            dp = row;
            shift = 4;
            d = 0;
2272
            for (i = png_pass_start[pass]; i < row_width;
2273
                i += png_pass_inc[pass])
G
Guy Schalnat 已提交
2274 2275
            {
               sp = row + (png_size_t)(i >> 1);
2276
               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
G
Guy Schalnat 已提交
2277 2278 2279 2280
               d |= (value << shift);

               if (shift == 0)
               {
G
Guy Schalnat 已提交
2281 2282
                  shift = 4;
                  *dp++ = (png_byte)d;
G
Guy Schalnat 已提交
2283 2284
                  d = 0;
               }
2285

G
Guy Schalnat 已提交
2286 2287 2288 2289
               else
                  shift -= 4;
            }
            if (shift != 4)
G
Guy Schalnat 已提交
2290
               *dp = (png_byte)d;
2291

G
Guy Schalnat 已提交
2292 2293
            break;
         }
2294

G
Guy Schalnat 已提交
2295 2296
         default:
         {
G
Guy Schalnat 已提交
2297 2298
            png_bytep sp;
            png_bytep dp;
2299 2300
            png_uint_32 i;
            png_uint_32 row_width = row_info->width;
A
Andreas Dilger 已提交
2301
            png_size_t pixel_bytes;
G
Guy Schalnat 已提交
2302

2303
            /* Start at the beginning */
G
Guy Schalnat 已提交
2304
            dp = row;
2305

2306
            /* Find out how many bytes each pixel takes up */
G
Guy Schalnat 已提交
2307
            pixel_bytes = (row_info->pixel_depth >> 3);
2308 2309

            /* Loop through the row, only looking at the pixels that matter */
2310
            for (i = png_pass_start[pass]; i < row_width;
G
Guy Schalnat 已提交
2311 2312
               i += png_pass_inc[pass])
            {
2313
               /* Find out where the original pixel is */
2314
               sp = row + (png_size_t)i * pixel_bytes;
2315

2316
               /* Move the pixel */
G
Guy Schalnat 已提交
2317
               if (dp != sp)
G
Guy Schalnat 已提交
2318
                  png_memcpy(dp, sp, pixel_bytes);
2319

2320
               /* Next pixel */
G
Guy Schalnat 已提交
2321 2322
               dp += pixel_bytes;
            }
G
Guy Schalnat 已提交
2323
            break;
G
Guy Schalnat 已提交
2324 2325
         }
      }
2326
      /* Set new row width */
G
Guy Schalnat 已提交
2327
      row_info->width = (row_info->width +
2328 2329 2330
          png_pass_inc[pass] - 1 -
          png_pass_start[pass]) /
          png_pass_inc[pass];
2331

2332 2333
      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
          row_info->width);
G
Guy Schalnat 已提交
2334 2335
   }
}
G
Guy Schalnat 已提交
2336
#endif
G
Guy Schalnat 已提交
2337

A
Andreas Dilger 已提交
2338 2339
/* 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
2340 2341
 * chosen filter.
 */
2342
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
A
Andreas Dilger 已提交
2343
#define PNG_HISHIFT 10
2344 2345
#define PNG_LOMASK ((png_uint_32)0xffffL)
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
2346
void /* PRIVATE */
G
Guy Schalnat 已提交
2347
png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
G
Guy Schalnat 已提交
2348
{
2349
   png_bytep best_row;
2350
#ifdef PNG_WRITE_FILTER_SUPPORTED
2351
   png_bytep prev_row, row_buf;
A
Andreas Dilger 已提交
2352
   png_uint_32 mins, bpp;
2353
   png_byte filter_to_do = png_ptr->do_filter;
2354
   png_size_t row_bytes = row_info->rowbytes;
2355
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2356
   int num_p_filters = (int)png_ptr->num_prev_filters;
2357
#endif
2358 2359 2360 2361

   png_debug(1, "in png_write_find_filter");

#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2362
  if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
2363
  {
2364 2365
     /* These will never be selected so we need not test them. */
     filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
2366
  }
2367
#endif
G
Guy Schalnat 已提交
2368

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

   prev_row = png_ptr->prev_row;
2373 2374
#endif
   best_row = png_ptr->row_buf;
2375
#ifdef PNG_WRITE_FILTER_SUPPORTED
2376
   row_buf = best_row;
A
Andreas Dilger 已提交
2377 2378 2379 2380
   mins = PNG_MAXSUM;

   /* The prediction method we use is to find which method provides the
    * smallest value when summing the absolute values of the distances
2381
    * from zero, using anything >= 128 as negative numbers.  This is known
A
Andreas Dilger 已提交
2382
    * as the "minimum sum of absolute differences" heuristic.  Other
2383
    * heuristics are the "weighted minimum sum of absolute differences"
A
Andreas Dilger 已提交
2384
    * (experimental and can in theory improve compression), and the "zlib
2385 2386 2387
    * 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 已提交
2388
    * computationally expensive).
2389 2390
    *
    * GRR 980525:  consider also
2391
    *
2392 2393 2394
    *   (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?]
2395
    *
2396 2397
    *  (1b) minimum sum of absolute differences from sliding average, probably
    *       with window size <= deflate window (usually 32K)
2398
    *
2399 2400
    *   (2) minimum sum of squared differences from zero or running average
    *       (i.e., ~ root-mean-square approach)
A
Andreas Dilger 已提交
2401
    */
G
Guy Schalnat 已提交
2402

2403

G
Guy Schalnat 已提交
2404
   /* We don't need to test the 'no filter' case if this is the only filter
A
Andreas Dilger 已提交
2405 2406
    * that has been chosen, as it doesn't actually do anything to the data.
    */
2407
   if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
G
Guy Schalnat 已提交
2408
   {
G
Guy Schalnat 已提交
2409 2410
      png_bytep rp;
      png_uint_32 sum = 0;
2411
      png_size_t i;
A
Andreas Dilger 已提交
2412
      int v;
G
Guy Schalnat 已提交
2413

2414
      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
G
Guy Schalnat 已提交
2415 2416 2417 2418
      {
         v = *rp;
         sum += (v < 128) ? v : 256 - v;
      }
A
Andreas Dilger 已提交
2419

2420
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2421 2422 2423
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
         png_uint_32 sumhi, sumlo;
2424
         int j;
A
Andreas Dilger 已提交
2425 2426 2427 2428
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */

         /* Reduce the sum if we match any of the previous rows */
2429
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2430
         {
2431
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
A
Andreas Dilger 已提交
2432
            {
2433
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2434
                   PNG_WEIGHT_SHIFT;
2435

2436
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2437
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2438 2439 2440 2441 2442 2443 2444 2445
            }
         }

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

A
Andreas Dilger 已提交
2448
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2449
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2450 2451 2452

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2453

A
Andreas Dilger 已提交
2454 2455 2456 2457
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif
G
Guy Schalnat 已提交
2458 2459
      mins = sum;
   }
G
Guy Schalnat 已提交
2460

2461
   /* Sub filter */
2462
   if (filter_to_do == PNG_FILTER_SUB)
2463
   /* It's the only filter so no testing is needed */
2464 2465
   {
      png_bytep rp, lp, dp;
2466
      png_size_t i;
2467

2468 2469 2470 2471 2472
      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
           i++, rp++, dp++)
      {
         *dp = *rp;
      }
2473

2474
      for (lp = row_buf + 1; i < row_bytes;
2475 2476 2477 2478
         i++, rp++, lp++, dp++)
      {
         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
      }
2479

2480 2481 2482 2483
      best_row = png_ptr->sub_row;
   }

   else if (filter_to_do & PNG_FILTER_SUB)
G
Guy Schalnat 已提交
2484 2485
   {
      png_bytep rp, dp, lp;
A
Andreas Dilger 已提交
2486
      png_uint_32 sum = 0, lmins = mins;
2487
      png_size_t i;
A
Andreas Dilger 已提交
2488 2489
      int v;

2490
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2491
      /* We temporarily increase the "minimum sum" by the factor we
A
Andreas Dilger 已提交
2492 2493 2494 2495 2496
       * would reduce the sum of this filter, so that we can do the
       * early exit comparison without scaling the sum each time.
       */
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2497
         int j;
A
Andreas Dilger 已提交
2498 2499 2500 2501
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2502
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2503
         {
2504
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
A
Andreas Dilger 已提交
2505
            {
2506
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2507
                   PNG_WEIGHT_SHIFT;
2508

2509
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2510
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2511 2512 2513 2514
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2515
             PNG_COST_SHIFT;
2516

A
Andreas Dilger 已提交
2517
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2518
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2519 2520 2521

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2522

A
Andreas Dilger 已提交
2523 2524 2525 2526
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2527

G
Guy Schalnat 已提交
2528 2529 2530 2531
      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
           i++, rp++, dp++)
      {
         v = *dp = *rp;
G
Guy Schalnat 已提交
2532

G
Guy Schalnat 已提交
2533 2534
         sum += (v < 128) ? v : 256 - v;
      }
2535

2536
      for (lp = row_buf + 1; i < row_bytes;
2537
         i++, rp++, lp++, dp++)
G
Guy Schalnat 已提交
2538 2539 2540 2541
      {
         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);

         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2542 2543 2544 2545 2546

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

2547
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2548 2549
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2550
         int j;
A
Andreas Dilger 已提交
2551 2552 2553 2554
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2555
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2556
         {
2557
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
A
Andreas Dilger 已提交
2558
            {
2559
               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
2560
                   PNG_WEIGHT_SHIFT;
2561

2562
               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
2563
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2564 2565 2566 2567
            }
         }

         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2568
             PNG_COST_SHIFT;
2569

A
Andreas Dilger 已提交
2570
         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2571
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2572 2573 2574

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2575

A
Andreas Dilger 已提交
2576 2577
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
G
Guy Schalnat 已提交
2578
      }
A
Andreas Dilger 已提交
2579 2580
#endif

G
Guy Schalnat 已提交
2581 2582 2583 2584 2585
      if (sum < mins)
      {
         mins = sum;
         best_row = png_ptr->sub_row;
      }
G
Guy Schalnat 已提交
2586 2587
   }

2588
   /* Up filter */
2589 2590 2591
   if (filter_to_do == PNG_FILTER_UP)
   {
      png_bytep rp, dp, pp;
2592
      png_size_t i;
2593 2594

      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2595 2596
          pp = prev_row + 1; i < row_bytes;
          i++, rp++, pp++, dp++)
2597 2598 2599
      {
         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
      }
2600

2601 2602 2603 2604
      best_row = png_ptr->up_row;
   }

   else if (filter_to_do & PNG_FILTER_UP)
G
Guy Schalnat 已提交
2605 2606
   {
      png_bytep rp, dp, pp;
A
Andreas Dilger 已提交
2607
      png_uint_32 sum = 0, lmins = mins;
2608
      png_size_t i;
A
Andreas Dilger 已提交
2609 2610
      int v;

2611

2612
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2613 2614
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2615
         int j;
A
Andreas Dilger 已提交
2616 2617 2618 2619
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2620
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2621
         {
2622
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
A
Andreas Dilger 已提交
2623
            {
2624
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2625
                   PNG_WEIGHT_SHIFT;
2626

2627
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2628
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2629 2630 2631 2632
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2633
             PNG_COST_SHIFT;
2634

A
Andreas Dilger 已提交
2635
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2636
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2637 2638 2639

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2640

A
Andreas Dilger 已提交
2641 2642 2643 2644
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2645

G
Guy Schalnat 已提交
2646
      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2647
          pp = prev_row + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2648
      {
2649
         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
G
Guy Schalnat 已提交
2650 2651

         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2652 2653 2654

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

2657
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2658 2659
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2660
         int j;
A
Andreas Dilger 已提交
2661 2662 2663 2664
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2665
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2666
         {
2667
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
A
Andreas Dilger 已提交
2668
            {
2669
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2670
                   PNG_WEIGHT_SHIFT;
2671

2672
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2673
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2674 2675 2676 2677
            }
         }

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2678
             PNG_COST_SHIFT;
2679

A
Andreas Dilger 已提交
2680
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2681
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2682 2683 2684

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2685

A
Andreas Dilger 已提交
2686 2687 2688 2689 2690
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2691 2692 2693 2694 2695 2696 2697
      if (sum < mins)
      {
         mins = sum;
         best_row = png_ptr->up_row;
      }
   }

2698
   /* Avg filter */
2699 2700 2701
   if (filter_to_do == PNG_FILTER_AVG)
   {
      png_bytep rp, dp, pp, lp;
2702
      png_uint_32 i;
2703

2704
      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2705
           pp = prev_row + 1; i < bpp; i++)
2706
      {
2707
         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2708
      }
2709

2710
      for (lp = row_buf + 1; i < row_bytes; i++)
2711
      {
2712 2713
         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
                 & 0xff);
2714 2715 2716 2717 2718
      }
      best_row = png_ptr->avg_row;
   }

   else if (filter_to_do & PNG_FILTER_AVG)
G
Guy Schalnat 已提交
2719
   {
G
Guy Schalnat 已提交
2720
      png_bytep rp, dp, pp, lp;
A
Andreas Dilger 已提交
2721
      png_uint_32 sum = 0, lmins = mins;
2722
      png_size_t i;
A
Andreas Dilger 已提交
2723 2724
      int v;

2725
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2726 2727
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2728
         int j;
A
Andreas Dilger 已提交
2729 2730 2731 2732
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2733
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2734
         {
2735
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
A
Andreas Dilger 已提交
2736
            {
2737
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2738
                   PNG_WEIGHT_SHIFT;
2739

2740
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2741
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2742 2743 2744 2745
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2746
             PNG_COST_SHIFT;
2747

A
Andreas Dilger 已提交
2748
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2749
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2750 2751 2752

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2753

A
Andreas Dilger 已提交
2754 2755 2756 2757
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2758

G
Guy Schalnat 已提交
2759
      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2760
           pp = prev_row + 1; i < bpp; i++)
G
Guy Schalnat 已提交
2761
      {
2762
         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
G
Guy Schalnat 已提交
2763

G
Guy Schalnat 已提交
2764 2765
         sum += (v < 128) ? v : 256 - v;
      }
2766

2767
      for (lp = row_buf + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2768
      {
2769
         v = *dp++ =
2770
             (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
G
Guy Schalnat 已提交
2771

G
Guy Schalnat 已提交
2772
         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2773 2774 2775

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

2778
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2779 2780
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2781
         int j;
A
Andreas Dilger 已提交
2782 2783 2784 2785
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2786
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2787
         {
2788
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
A
Andreas Dilger 已提交
2789
            {
2790
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2791
                   PNG_WEIGHT_SHIFT;
2792

2793
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2794
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2795 2796 2797 2798
            }
         }

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2799
             PNG_COST_SHIFT;
2800

A
Andreas Dilger 已提交
2801
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2802
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2803 2804 2805

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2806

A
Andreas Dilger 已提交
2807 2808 2809 2810 2811
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2812 2813 2814 2815 2816 2817
      if (sum < mins)
      {
         mins = sum;
         best_row = png_ptr->avg_row;
      }
   }
G
Guy Schalnat 已提交
2818

A
Andreas Dilger 已提交
2819
   /* Paeth filter */
2820 2821 2822
   if (filter_to_do == PNG_FILTER_PAETH)
   {
      png_bytep rp, dp, pp, cp, lp;
2823
      png_size_t i;
2824

2825
      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2826
          pp = prev_row + 1; i < bpp; i++)
2827
      {
2828
         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2829 2830
      }

2831
      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2832 2833 2834
      {
         int a, b, c, pa, pb, pc, p;

2835 2836 2837
         b = *pp++;
         c = *cp++;
         a = *lp++;
2838

2839 2840
         p = b - c;
         pc = a - c;
2841 2842

#ifdef PNG_USE_ABS
2843 2844 2845
         pa = abs(p);
         pb = abs(pc);
         pc = abs(p + pc);
2846
#else
2847 2848 2849
         pa = p < 0 ? -p : p;
         pb = pc < 0 ? -pc : pc;
         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2850 2851 2852 2853
#endif

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

2854
         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2855 2856 2857 2858 2859
      }
      best_row = png_ptr->paeth_row;
   }

   else if (filter_to_do & PNG_FILTER_PAETH)
G
Guy Schalnat 已提交
2860 2861
   {
      png_bytep rp, dp, pp, cp, lp;
A
Andreas Dilger 已提交
2862
      png_uint_32 sum = 0, lmins = mins;
2863
      png_size_t i;
A
Andreas Dilger 已提交
2864 2865
      int v;

2866
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2867 2868
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2869
         int j;
A
Andreas Dilger 已提交
2870 2871 2872 2873
         png_uint_32 lmhi, lmlo;
         lmlo = lmins & PNG_LOMASK;
         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;

2874
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2875
         {
2876
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
A
Andreas Dilger 已提交
2877
            {
2878
               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2879
                   PNG_WEIGHT_SHIFT;
2880

2881
               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2882
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2883 2884 2885 2886
            }
         }

         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2887
             PNG_COST_SHIFT;
2888

A
Andreas Dilger 已提交
2889
         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2890
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2891 2892 2893

         if (lmhi > PNG_HIMASK)
            lmins = PNG_MAXSUM;
2894

A
Andreas Dilger 已提交
2895 2896 2897 2898
         else
            lmins = (lmhi << PNG_HISHIFT) + lmlo;
      }
#endif
G
Guy Schalnat 已提交
2899

G
Guy Schalnat 已提交
2900
      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2901
          pp = prev_row + 1; i < bpp; i++)
G
Guy Schalnat 已提交
2902
      {
2903
         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
G
Guy Schalnat 已提交
2904

G
Guy Schalnat 已提交
2905 2906
         sum += (v < 128) ? v : 256 - v;
      }
2907

2908
      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
G
Guy Schalnat 已提交
2909 2910
      {
         int a, b, c, pa, pb, pc, p;
G
Guy Schalnat 已提交
2911

2912 2913 2914
         b = *pp++;
         c = *cp++;
         a = *lp++;
2915 2916

#ifndef PNG_SLOW_PAETH
2917 2918
         p = b - c;
         pc = a - c;
2919
#ifdef PNG_USE_ABS
2920 2921 2922
         pa = abs(p);
         pb = abs(pc);
         pc = abs(p + pc);
2923
#else
2924 2925 2926
         pa = p < 0 ? -p : p;
         pb = pc < 0 ? -pc : pc;
         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2927 2928 2929
#endif
         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
#else /* PNG_SLOW_PAETH */
2930
         p = a + b - c;
2931 2932 2933
         pa = abs(p - a);
         pb = abs(p - b);
         pc = abs(p - c);
2934

G
Guy Schalnat 已提交
2935 2936
         if (pa <= pb && pa <= pc)
            p = a;
2937

G
Guy Schalnat 已提交
2938 2939
         else if (pb <= pc)
            p = b;
2940

G
Guy Schalnat 已提交
2941 2942
         else
            p = c;
2943
#endif /* PNG_SLOW_PAETH */
G
Guy Schalnat 已提交
2944

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

G
Guy Schalnat 已提交
2947
         sum += (v < 128) ? v : 256 - v;
A
Andreas Dilger 已提交
2948 2949 2950

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

2953
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2954 2955
      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
      {
2956
         int j;
A
Andreas Dilger 已提交
2957 2958 2959 2960
         png_uint_32 sumhi, sumlo;
         sumlo = sum & PNG_LOMASK;
         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;

2961
         for (j = 0; j < num_p_filters; j++)
A
Andreas Dilger 已提交
2962
         {
2963
            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
A
Andreas Dilger 已提交
2964
            {
2965
               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2966
                   PNG_WEIGHT_SHIFT;
2967

2968
               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2969
                   PNG_WEIGHT_SHIFT;
A
Andreas Dilger 已提交
2970 2971 2972 2973
            }
         }

         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2974
             PNG_COST_SHIFT;
2975

A
Andreas Dilger 已提交
2976
         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2977
             PNG_COST_SHIFT;
A
Andreas Dilger 已提交
2978 2979 2980

         if (sumhi > PNG_HIMASK)
            sum = PNG_MAXSUM;
2981

A
Andreas Dilger 已提交
2982 2983 2984 2985 2986
         else
            sum = (sumhi << PNG_HISHIFT) + sumlo;
      }
#endif

G
Guy Schalnat 已提交
2987 2988 2989 2990
      if (sum < mins)
      {
         best_row = png_ptr->paeth_row;
      }
G
Guy Schalnat 已提交
2991
   }
2992
#endif /* PNG_WRITE_FILTER_SUPPORTED */
A
Andreas Dilger 已提交
2993
   /* Do the actual writing of the filtered row data from the chosen filter. */
2994

G
Guy Schalnat 已提交
2995
   png_write_filtered_row(png_ptr, best_row);
A
Andreas Dilger 已提交
2996

2997
#ifdef PNG_WRITE_FILTER_SUPPORTED
2998
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
A
Andreas Dilger 已提交
2999 3000 3001
   /* Save the type of filter we picked this time for future calculations */
   if (png_ptr->num_prev_filters > 0)
   {
3002
      int j;
3003

3004
      for (j = 1; j < num_p_filters; j++)
A
Andreas Dilger 已提交
3005
      {
3006
         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
A
Andreas Dilger 已提交
3007
      }
3008

3009
      png_ptr->prev_filters[j] = best_row[0];
A
Andreas Dilger 已提交
3010 3011
   }
#endif
3012
#endif /* PNG_WRITE_FILTER_SUPPORTED */
G
Guy Schalnat 已提交
3013
}
G
Guy Schalnat 已提交
3014

G
Guy Schalnat 已提交
3015

A
Andreas Dilger 已提交
3016
/* Do the actual writing of a previously filtered row. */
3017
void /* PRIVATE */
G
Guy Schalnat 已提交
3018 3019
png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
{
3020 3021
   png_size_t avail;

3022
   png_debug(1, "in png_write_filtered_row");
3023

3024
   png_debug1(2, "filter = %d", filtered_row[0]);
3025
   /* Set up the zlib input buffer */
3026

A
Andreas Dilger 已提交
3027
   png_ptr->zstream.next_in = filtered_row;
3028 3029
   png_ptr->zstream.avail_in = 0;
   avail = png_ptr->row_info.rowbytes + 1;
3030
   /* Repeat until we have compressed all the data */
G
Guy Schalnat 已提交
3031
   do
G
Guy Schalnat 已提交
3032
   {
3033
      int ret; /* Return of zlib */
G
Guy Schalnat 已提交
3034

3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058
      /* Record the number of bytes available - zlib supports at least 65535
       * bytes at one step, depending on the size of the zlib type 'uInt', the
       * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
       * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
       * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
       * uInt.  ZLIB_IO_MAX can be safely reduced to cause zlib to be called
       * with smaller chunks of data.
       */
      if (png_ptr->zstream.avail_in == 0)
      {
         if (avail > ZLIB_IO_MAX)
         {
            png_ptr->zstream.avail_in  = ZLIB_IO_MAX;
            avail -= ZLIB_IO_MAX;
         }

         else
         {
            /* So this will fit in the available uInt space: */
            png_ptr->zstream.avail_in = (uInt)avail;
            avail = 0;
         }
      }

3059
      /* Compress the data */
A
Andreas Dilger 已提交
3060
      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
3061

3062
      /* Check for compression errors */
G
Guy Schalnat 已提交
3063 3064
      if (ret != Z_OK)
      {
A
Andreas Dilger 已提交
3065
         if (png_ptr->zstream.msg != NULL)
A
Andreas Dilger 已提交
3066
            png_error(png_ptr, png_ptr->zstream.msg);
3067

G
Guy Schalnat 已提交
3068 3069 3070
         else
            png_error(png_ptr, "zlib error");
      }
G
Guy Schalnat 已提交
3071

3072
      /* See if it is time to write another IDAT */
A
Andreas Dilger 已提交
3073
      if (!(png_ptr->zstream.avail_out))
G
Guy Schalnat 已提交
3074
      {
3075
         /* Write the IDAT and reset the zlib output buffer */
G
Guy Schalnat 已提交
3076
         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
A
Andreas Dilger 已提交
3077 3078
         png_ptr->zstream.next_out = png_ptr->zbuf;
         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
3079
      }
3080
   /* Repeat until all data has been compressed */
3081
   } while (avail > 0 || png_ptr->zstream.avail_in > 0);
G
Guy Schalnat 已提交
3082

3083
   /* Swap the current and previous rows */
A
Andreas Dilger 已提交
3084
   if (png_ptr->prev_row != NULL)
G
Guy Schalnat 已提交
3085 3086 3087 3088 3089 3090 3091 3092
   {
      png_bytep tptr;

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

3093
   /* Finish row - updates counters and flushes zlib if last row */
G
Guy Schalnat 已提交
3094
   png_write_finish_row(png_ptr);
G
Guy Schalnat 已提交
3095

3096
#ifdef PNG_WRITE_FLUSH_SUPPORTED
G
Guy Schalnat 已提交
3097 3098 3099 3100 3101 3102
   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 已提交
3103
   }
3104
#endif
G
Guy Schalnat 已提交
3105
}
3106
#endif /* PNG_WRITE_SUPPORTED */