ReactOS 0.4.16-dev-2613-g9533ad7
pngwutil.c
Go to the documentation of this file.
1/* pngwutil.c - utilities to write a PNG file
2 *
3 * Copyright (c) 2018-2025 Cosmin Truta
4 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
5 * Copyright (c) 1996-1997 Andreas Dilger
6 * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
7 *
8 * This code is released under the libpng license.
9 * For conditions of distribution and use, see the disclaimer
10 * and license in png.h
11 *
12 * This file contains routines that are only called from within
13 * libpng itself during the course of writing an image.
14 */
15
16#include "pngpriv.h"
17
18#ifdef PNG_WRITE_SUPPORTED
19
20#ifdef PNG_WRITE_INTERLACING_SUPPORTED
21/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
22
23/* Start of interlace block */
24static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
25/* Offset to next interlace block */
26static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
27/* Start of interlace block in the y direction */
28static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
29/* Offset to next interlace block in the y direction */
30static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
31
32/* TODO: Move these arrays to a common utility module to avoid duplication. */
33#endif
34
35#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
36/* Place a 32-bit number into a buffer in PNG byte order. We work
37 * with unsigned numbers for convenience, although one supported
38 * ancillary chunk uses signed (two's complement) numbers.
39 */
40void PNGAPI
41png_save_uint_32(png_bytep buf, png_uint_32 i)
42{
43 buf[0] = (png_byte)((i >> 24) & 0xffU);
44 buf[1] = (png_byte)((i >> 16) & 0xffU);
45 buf[2] = (png_byte)((i >> 8) & 0xffU);
46 buf[3] = (png_byte)( i & 0xffU);
47}
48
49/* Place a 16-bit number into a buffer in PNG byte order.
50 * The parameter is declared unsigned int, not png_uint_16,
51 * just to avoid potential problems on pre-ANSI C compilers.
52 */
53void PNGAPI
54png_save_uint_16(png_bytep buf, unsigned int i)
55{
56 buf[0] = (png_byte)((i >> 8) & 0xffU);
57 buf[1] = (png_byte)( i & 0xffU);
58}
59#endif
60
61/* Simple function to write the signature. If we have already written
62 * the magic bytes of the signature, or more likely, the PNG stream is
63 * being embedded into another stream and doesn't need its own signature,
64 * we should call png_set_sig_bytes() to tell libpng how many of the
65 * bytes have already been written.
66 */
67void PNGAPI
68png_write_sig(png_structrp png_ptr)
69{
70 png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
71
72#ifdef PNG_IO_STATE_SUPPORTED
73 /* Inform the I/O callback that the signature is being written */
75#endif
76
77 /* Write the rest of the 8 byte signature */
78 png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
79 (size_t)(8 - png_ptr->sig_bytes));
80
81 if (png_ptr->sig_bytes < 3)
83}
84
85/* Write the start of a PNG chunk. The type is the chunk type.
86 * The total_length is the sum of the lengths of all the data you will be
87 * passing in png_write_chunk_data().
88 */
89static void
90png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
92{
93 png_byte buf[8];
94
95#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
96 PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
97 png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
98#endif
99
100 if (png_ptr == NULL)
101 return;
102
103#ifdef PNG_IO_STATE_SUPPORTED
104 /* Inform the I/O callback that the chunk header is being written.
105 * PNG_IO_CHUNK_HDR requires a single I/O call.
106 */
108#endif
109
110 /* Write the length and the chunk name */
111 png_save_uint_32(buf, length);
112 png_save_uint_32(buf + 4, chunk_name);
113 png_write_data(png_ptr, buf, 8);
114
115 /* Put the chunk name into png_ptr->chunk_name */
116 png_ptr->chunk_name = chunk_name;
117
118 /* Reset the crc and run it over the chunk name */
119 png_reset_crc(png_ptr);
120
121 png_calculate_crc(png_ptr, buf + 4, 4);
122
123#ifdef PNG_IO_STATE_SUPPORTED
124 /* Inform the I/O callback that chunk data will (possibly) be written.
125 * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
126 */
128#endif
129}
130
131void PNGAPI
132png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
134{
135 png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
136}
137
138/* Write the data of a PNG chunk started with png_write_chunk_header().
139 * Note that multiple calls to this function are allowed, and that the
140 * sum of the lengths from these calls *must* add up to the total_length
141 * given to png_write_chunk_header().
142 */
143void PNGAPI
144png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, size_t length)
145{
146 /* Write the data, and run the CRC over it */
147 if (png_ptr == NULL)
148 return;
149
150 if (data != NULL && length > 0)
151 {
152 png_write_data(png_ptr, data, length);
153
154 /* Update the CRC after writing the data,
155 * in case the user I/O routine alters it.
156 */
157 png_calculate_crc(png_ptr, data, length);
158 }
159}
160
161/* Finish a chunk started with png_write_chunk_header(). */
162void PNGAPI
163png_write_chunk_end(png_structrp png_ptr)
164{
165 png_byte buf[4];
166
167 if (png_ptr == NULL) return;
168
169#ifdef PNG_IO_STATE_SUPPORTED
170 /* Inform the I/O callback that the chunk CRC is being written.
171 * PNG_IO_CHUNK_CRC requires a single I/O function call.
172 */
174#endif
175
176 /* Write the crc in a single operation */
177 png_save_uint_32(buf, png_ptr->crc);
178
179 png_write_data(png_ptr, buf, 4);
180}
181
182/* Write a PNG chunk all at once. The type is an array of ASCII characters
183 * representing the chunk name. The array must be at least 4 bytes in
184 * length, and does not need to be null terminated. To be safe, pass the
185 * pre-defined chunk names here, and if you need a new one, define it
186 * where the others are defined. The length is the length of the data.
187 * All the data must be present. If that is not possible, use the
188 * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
189 * functions instead.
190 */
191static void
192png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
194{
195 if (png_ptr == NULL)
196 return;
197
198 /* On 64-bit architectures 'length' may not fit in a png_uint_32. */
200 png_error(png_ptr, "length exceeds PNG maximum");
201
202 png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
203 png_write_chunk_data(png_ptr, data, length);
204 png_write_chunk_end(png_ptr);
205}
206
207/* This is the API that calls the internal function above. */
208void PNGAPI
209png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
211{
212 png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
213 length);
214}
215
216/* This is used below to find the size of an image to pass to png_deflate_claim,
217 * so it only needs to be accurate if the size is less than 16384 bytes (the
218 * point at which a lower LZ window size can be used.)
219 */
220static png_alloc_size_t
221png_image_size(png_structrp png_ptr)
222{
223 /* Only return sizes up to the maximum of a png_uint_32; do this by limiting
224 * the width and height used to 15 bits.
225 */
226 png_uint_32 h = png_ptr->height;
227
228 if (png_ptr->rowbytes < 32768 && h < 32768)
229 {
230 if (png_ptr->interlaced != 0)
231 {
232 /* Interlacing makes the image larger because of the replication of
233 * both the filter byte and the padding to a byte boundary.
234 */
235 png_uint_32 w = png_ptr->width;
236 unsigned int pd = png_ptr->pixel_depth;
237 png_alloc_size_t cb_base;
238 int pass;
239
240 for (cb_base=0, pass=0; pass<=6; ++pass)
241 {
243
244 if (pw > 0)
245 cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
246 }
247
248 return cb_base;
249 }
250
251 else
252 return (png_ptr->rowbytes+1) * h;
253 }
254
255 else
256 return 0xffffffffU;
257}
258
259#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
260 /* This is the code to hack the first two bytes of the deflate stream (the
261 * deflate header) to correct the windowBits value to match the actual data
262 * size. Note that the second argument is the *uncompressed* size but the
263 * first argument is the *compressed* data (and it must be deflate
264 * compressed.)
265 */
266static void
267optimize_cmf(png_bytep data, png_alloc_size_t data_size)
268{
269 /* Optimize the CMF field in the zlib stream. The resultant zlib stream is
270 * still compliant to the stream specification.
271 */
272 if (data_size <= 16384) /* else windowBits must be 15 */
273 {
274 unsigned int z_cmf = data[0]; /* zlib compression method and flags */
275
276 if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
277 {
278 unsigned int z_cinfo;
279 unsigned int half_z_window_size;
280
281 z_cinfo = z_cmf >> 4;
282 half_z_window_size = 1U << (z_cinfo + 7);
283
284 if (data_size <= half_z_window_size) /* else no change */
285 {
286 unsigned int tmp;
287
288 do
289 {
290 half_z_window_size >>= 1;
291 --z_cinfo;
292 }
293 while (z_cinfo > 0 && data_size <= half_z_window_size);
294
295 z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
296
297 data[0] = (png_byte)z_cmf;
298 tmp = data[1] & 0xe0;
299 tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
300 data[1] = (png_byte)tmp;
301 }
302 }
303 }
304}
305#endif /* WRITE_OPTIMIZE_CMF */
306
307/* Initialize the compressor for the appropriate type of compression. */
308static int
309png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
310 png_alloc_size_t data_size)
311{
312 if (png_ptr->zowner != 0)
313 {
314#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
315 char msg[64];
316
318 msg[4] = ':';
319 msg[5] = ' ';
321 /* So the message that results is "<chunk> using zstream"; this is an
322 * internal error, but is very useful for debugging. i18n requirements
323 * are minimal.
324 */
325 (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
326#endif
327#if PNG_RELEASE_BUILD
328 png_warning(png_ptr, msg);
329
330 /* Attempt sane error recovery */
331 if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
332 {
333 png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
334 return Z_STREAM_ERROR;
335 }
336
337 png_ptr->zowner = 0;
338#else
339 png_error(png_ptr, msg);
340#endif
341 }
342
343 {
344 int level = png_ptr->zlib_level;
345 int method = png_ptr->zlib_method;
346 int windowBits = png_ptr->zlib_window_bits;
347 int memLevel = png_ptr->zlib_mem_level;
348 int strategy; /* set below */
349 int ret; /* zlib return code */
350
351 if (owner == png_IDAT)
352 {
353 if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
354 strategy = png_ptr->zlib_strategy;
355
356 else if (png_ptr->do_filter != PNG_FILTER_NONE)
357 strategy = PNG_Z_DEFAULT_STRATEGY;
358
359 else
361 }
362
363 else
364 {
365#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
366 level = png_ptr->zlib_text_level;
367 method = png_ptr->zlib_text_method;
368 windowBits = png_ptr->zlib_text_window_bits;
369 memLevel = png_ptr->zlib_text_mem_level;
370 strategy = png_ptr->zlib_text_strategy;
371#else
372 /* If customization is not supported the values all come from the
373 * IDAT values except for the strategy, which is fixed to the
374 * default. (This is the pre-1.6.0 behavior too, although it was
375 * implemented in a very different way.)
376 */
377 strategy = Z_DEFAULT_STRATEGY;
378#endif
379 }
380
381 /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
382 * happening just pass 32768 as the data_size parameter. Notice that zlib
383 * requires an extra 262 bytes in the window in addition to the data to be
384 * able to see the whole of the data, so if data_size+262 takes us to the
385 * next windowBits size we need to fix up the value later. (Because even
386 * though deflate needs the extra window, inflate does not!)
387 */
388 if (data_size <= 16384)
389 {
390 /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
391 * work round a Microsoft Visual C misbehavior which, contrary to C-90,
392 * widens the result of the following shift to 64-bits if (and,
393 * apparently, only if) it is used in a test.
394 */
395 unsigned int half_window_size = 1U << (windowBits-1);
396
397 while (data_size + 262 <= half_window_size)
398 {
399 half_window_size >>= 1;
400 --windowBits;
401 }
402 }
403
404 /* Check against the previous initialized values, if any. */
405 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
406 (png_ptr->zlib_set_level != level ||
407 png_ptr->zlib_set_method != method ||
408 png_ptr->zlib_set_window_bits != windowBits ||
409 png_ptr->zlib_set_mem_level != memLevel ||
410 png_ptr->zlib_set_strategy != strategy))
411 {
412 if (deflateEnd(&png_ptr->zstream) != Z_OK)
413 png_warning(png_ptr, "deflateEnd failed (ignored)");
414
415 png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
416 }
417
418 /* For safety clear out the input and output pointers (currently zlib
419 * doesn't use them on Init, but it might in the future).
420 */
421 png_ptr->zstream.next_in = NULL;
422 png_ptr->zstream.avail_in = 0;
423 png_ptr->zstream.next_out = NULL;
424 png_ptr->zstream.avail_out = 0;
425
426 /* Now initialize if required, setting the new parameters, otherwise just
427 * do a simple reset to the previous parameters.
428 */
429 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
430 ret = deflateReset(&png_ptr->zstream);
431
432 else
433 {
435 memLevel, strategy);
436
437 if (ret == Z_OK)
439 }
440
441 /* The return code is from either deflateReset or deflateInit2; they have
442 * pretty much the same set of error codes.
443 */
444 if (ret == Z_OK)
445 png_ptr->zowner = owner;
446
447 else
448 png_zstream_error(png_ptr, ret);
449
450 return ret;
451 }
452}
453
454/* Clean up (or trim) a linked list of compression buffers. */
455void /* PRIVATE */
456png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
457{
458 png_compression_bufferp list = *listp;
459
460 if (list != NULL)
461 {
462 *listp = NULL;
463
464 do
465 {
466 png_compression_bufferp next = list->next;
467
468 png_free(png_ptr, list);
469 list = next;
470 }
471 while (list != NULL);
472 }
473}
474
475#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
476/* This pair of functions encapsulates the operation of (a) compressing a
477 * text string, and (b) issuing it later as a series of chunk data writes.
478 * The compression_state structure is shared context for these functions
479 * set up by the caller to allow access to the relevant local variables.
480 *
481 * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
482 * temporary buffers. From 1.6.0 it is retained in png_struct so that it will
483 * be correctly freed in the event of a write error (previous implementations
484 * just leaked memory.)
485 */
486typedef struct
487{
488 png_const_bytep input; /* The uncompressed input data */
489 png_alloc_size_t input_len; /* Its length */
490 png_uint_32 output_len; /* Final compressed length */
491 png_byte output[1024]; /* First block of output */
492} compression_state;
493
494static void
495png_text_compress_init(compression_state *comp, png_const_bytep input,
496 png_alloc_size_t input_len)
497{
498 comp->input = input;
499 comp->input_len = input_len;
500 comp->output_len = 0;
501}
502
503/* Compress the data in the compression state input */
504static int
505png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
506 compression_state *comp, png_uint_32 prefix_len)
507{
508 int ret;
509
510 /* To find the length of the output it is necessary to first compress the
511 * input. The result is buffered rather than using the two-pass algorithm
512 * that is used on the inflate side; deflate is assumed to be slower and a
513 * PNG writer is assumed to have more memory available than a PNG reader.
514 *
515 * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
516 * upper limit on the output size, but it is always bigger than the input
517 * size so it is likely to be more efficient to use this linked-list
518 * approach.
519 */
520 ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
521
522 if (ret != Z_OK)
523 return ret;
524
525 /* Set up the compression buffers, we need a loop here to avoid overflowing a
526 * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited
527 * by the output buffer size, so there is no need to check that. Since this
528 * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
529 * in size.
530 */
531 {
532 png_compression_bufferp *end = &png_ptr->zbuffer_list;
533 png_alloc_size_t input_len = comp->input_len; /* may be zero! */
534 png_uint_32 output_len;
535
536 /* zlib updates these for us: */
537 png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
538 png_ptr->zstream.avail_in = 0; /* Set below */
539 png_ptr->zstream.next_out = comp->output;
540 png_ptr->zstream.avail_out = (sizeof comp->output);
541
542 output_len = png_ptr->zstream.avail_out;
543
544 do
545 {
546 uInt avail_in = ZLIB_IO_MAX;
547
548 if (avail_in > input_len)
549 avail_in = (uInt)input_len;
550
551 input_len -= avail_in;
552
553 png_ptr->zstream.avail_in = avail_in;
554
555 if (png_ptr->zstream.avail_out == 0)
556 {
557 png_compression_buffer *next;
558
559 /* Chunk data is limited to 2^31 bytes in length, so the prefix
560 * length must be counted here.
561 */
562 if (output_len + prefix_len > PNG_UINT_31_MAX)
563 {
565 break;
566 }
567
568 /* Need a new (malloc'ed) buffer, but there may be one present
569 * already.
570 */
571 next = *end;
572 if (next == NULL)
573 {
574 next = png_voidcast(png_compression_bufferp, png_malloc_base
575 (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
576
577 if (next == NULL)
578 {
580 break;
581 }
582
583 /* Link in this buffer (so that it will be freed later) */
584 next->next = NULL;
585 *end = next;
586 }
587
588 png_ptr->zstream.next_out = next->output;
589 png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
590 output_len += png_ptr->zstream.avail_out;
591
592 /* Move 'end' to the next buffer pointer. */
593 end = &next->next;
594 }
595
596 /* Compress the data */
597 ret = deflate(&png_ptr->zstream,
598 input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
599
600 /* Claw back input data that was not consumed (because avail_in is
601 * reset above every time round the loop).
602 */
603 input_len += png_ptr->zstream.avail_in;
604 png_ptr->zstream.avail_in = 0; /* safety */
605 }
606 while (ret == Z_OK);
607
608 /* There may be some space left in the last output buffer. This needs to
609 * be subtracted from output_len.
610 */
611 output_len -= png_ptr->zstream.avail_out;
612 png_ptr->zstream.avail_out = 0; /* safety */
613 comp->output_len = output_len;
614
615 /* Now double check the output length, put in a custom message if it is
616 * too long. Otherwise ensure the z_stream::msg pointer is set to
617 * something.
618 */
619 if (output_len + prefix_len >= PNG_UINT_31_MAX)
620 {
621 png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
623 }
624
625 else
626 png_zstream_error(png_ptr, ret);
627
628 /* Reset zlib for another zTXt/iTXt or image data */
629 png_ptr->zowner = 0;
630
631 /* The only success case is Z_STREAM_END, input_len must be 0; if not this
632 * is an internal error.
633 */
634 if (ret == Z_STREAM_END && input_len == 0)
635 {
636#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
637 /* Fix up the deflate header, if required */
638 optimize_cmf(comp->output, comp->input_len);
639#endif
640 /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
641 * function above to return Z_STREAM_END on an error (though it never
642 * does in the current versions of zlib.)
643 */
644 return Z_OK;
645 }
646
647 else
648 return ret;
649 }
650}
651
652/* Ship the compressed text out via chunk writes */
653static void
654png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
655{
656 png_uint_32 output_len = comp->output_len;
657 png_const_bytep output = comp->output;
658 png_uint_32 avail = (sizeof comp->output);
659 png_compression_buffer *next = png_ptr->zbuffer_list;
660
661 for (;;)
662 {
663 if (avail > output_len)
664 avail = output_len;
665
666 png_write_chunk_data(png_ptr, output, avail);
667
668 output_len -= avail;
669
670 if (output_len == 0 || next == NULL)
671 break;
672
673 avail = png_ptr->zbuffer_size;
674 output = next->output;
675 next = next->next;
676 }
677
678 /* This is an internal error; 'next' must have been NULL! */
679 if (output_len > 0)
680 png_error(png_ptr, "error writing ancillary chunked compressed data");
681}
682#endif /* WRITE_COMPRESSED_TEXT */
683
684/* Write the IHDR chunk, and update the png_struct with the necessary
685 * information. Note that the rest of this code depends upon this
686 * information being correct.
687 */
688void /* PRIVATE */
690 int bit_depth, int color_type, int compression_type, int filter_type,
691 int interlace_type)
692{
693 png_byte buf[13]; /* Buffer to store the IHDR info */
694 int is_invalid_depth;
695
696 png_debug(1, "in png_write_IHDR");
697
698 /* Check that we have valid input data from the application info */
699 switch (color_type)
700 {
702 switch (bit_depth)
703 {
704 case 1:
705 case 2:
706 case 4:
707 case 8:
708#ifdef PNG_WRITE_16BIT_SUPPORTED
709 case 16:
710#endif
711 png_ptr->channels = 1; break;
712
713 default:
714 png_error(png_ptr,
715 "Invalid bit depth for grayscale image");
716 }
717 break;
718
720 is_invalid_depth = (bit_depth != 8);
721#ifdef PNG_WRITE_16BIT_SUPPORTED
722 is_invalid_depth = (is_invalid_depth && bit_depth != 16);
723#endif
724 if (is_invalid_depth)
725 png_error(png_ptr, "Invalid bit depth for RGB image");
726
727 png_ptr->channels = 3;
728 break;
729
731 switch (bit_depth)
732 {
733 case 1:
734 case 2:
735 case 4:
736 case 8:
737 png_ptr->channels = 1;
738 break;
739
740 default:
741 png_error(png_ptr, "Invalid bit depth for paletted image");
742 }
743 break;
744
746 is_invalid_depth = (bit_depth != 8);
747#ifdef PNG_WRITE_16BIT_SUPPORTED
748 is_invalid_depth = (is_invalid_depth && bit_depth != 16);
749#endif
750 if (is_invalid_depth)
751 png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
752
753 png_ptr->channels = 2;
754 break;
755
757 is_invalid_depth = (bit_depth != 8);
758#ifdef PNG_WRITE_16BIT_SUPPORTED
759 is_invalid_depth = (is_invalid_depth && bit_depth != 16);
760#endif
761 if (is_invalid_depth)
762 png_error(png_ptr, "Invalid bit depth for RGBA image");
763
764 png_ptr->channels = 4;
765 break;
766
767 default:
768 png_error(png_ptr, "Invalid image color type specified");
769 }
770
771 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
772 {
773 png_warning(png_ptr, "Invalid compression type specified");
774 compression_type = PNG_COMPRESSION_TYPE_BASE;
775 }
776
777 /* Write filter_method 64 (intrapixel differencing) only if
778 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
779 * 2. Libpng did not write a PNG signature (this filter_method is only
780 * used in PNG datastreams that are embedded in MNG datastreams) and
781 * 3. The application called png_permit_mng_features with a mask that
782 * included PNG_FLAG_MNG_FILTER_64 and
783 * 4. The filter_method is 64 and
784 * 5. The color_type is RGB or RGBA
785 */
786 if (
788 !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
789 ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
790 (color_type == PNG_COLOR_TYPE_RGB ||
791 color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
792 (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
793#endif
794 filter_type != PNG_FILTER_TYPE_BASE)
795 {
796 png_warning(png_ptr, "Invalid filter type specified");
797 filter_type = PNG_FILTER_TYPE_BASE;
798 }
799
800#ifdef PNG_WRITE_INTERLACING_SUPPORTED
801 if (interlace_type != PNG_INTERLACE_NONE &&
802 interlace_type != PNG_INTERLACE_ADAM7)
803 {
804 png_warning(png_ptr, "Invalid interlace type specified");
805 interlace_type = PNG_INTERLACE_ADAM7;
806 }
807#else
808 interlace_type=PNG_INTERLACE_NONE;
809#endif
810
811 /* Save the relevant information */
812 png_ptr->bit_depth = (png_byte)bit_depth;
813 png_ptr->color_type = (png_byte)color_type;
814 png_ptr->interlaced = (png_byte)interlace_type;
815#ifdef PNG_MNG_FEATURES_SUPPORTED
816 png_ptr->filter_type = (png_byte)filter_type;
817#endif
818 png_ptr->compression_type = (png_byte)compression_type;
819 png_ptr->width = width;
820 png_ptr->height = height;
821
822 png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
823 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
824 /* Set the usr info, so any transformations can modify it */
825 png_ptr->usr_width = png_ptr->width;
826 png_ptr->usr_bit_depth = png_ptr->bit_depth;
827 png_ptr->usr_channels = png_ptr->channels;
828
829 /* Pack the header information into the buffer */
830 png_save_uint_32(buf, width);
831 png_save_uint_32(buf + 4, height);
832 buf[8] = (png_byte)bit_depth;
833 buf[9] = (png_byte)color_type;
834 buf[10] = (png_byte)compression_type;
835 buf[11] = (png_byte)filter_type;
836 buf[12] = (png_byte)interlace_type;
837
838 /* Write the chunk */
839 png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
840
841 if ((png_ptr->do_filter) == PNG_NO_FILTERS)
842 {
843 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
844 png_ptr->bit_depth < 8)
845 png_ptr->do_filter = PNG_FILTER_NONE;
846
847 else
848 png_ptr->do_filter = PNG_ALL_FILTERS;
849 }
850
851 png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
852}
853
854/* Write the palette. We are careful not to trust png_color to be in the
855 * correct order for PNG, so people can redefine it to any convenient
856 * structure.
857 */
858void /* PRIVATE */
860 png_uint_32 num_pal)
861{
862 png_uint_32 max_palette_length, i;
863 png_const_colorp pal_ptr;
864 png_byte buf[3];
865
866 png_debug(1, "in png_write_PLTE");
867
868 max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
869 (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
870
871 if ((
873 (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
874#endif
875 num_pal == 0) || num_pal > max_palette_length)
876 {
877 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
878 {
879 png_error(png_ptr, "Invalid number of colors in palette");
880 }
881
882 else
883 {
884 png_warning(png_ptr, "Invalid number of colors in palette");
885 return;
886 }
887 }
888
889 if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
890 {
891 png_warning(png_ptr,
892 "Ignoring request to write a PLTE chunk in grayscale PNG");
893
894 return;
895 }
896
897 png_ptr->num_palette = (png_uint_16)num_pal;
898 png_debug1(3, "num_palette = %d", png_ptr->num_palette);
899
900 png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
901#ifdef PNG_POINTER_INDEXING_SUPPORTED
902
903 for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
904 {
905 buf[0] = pal_ptr->red;
906 buf[1] = pal_ptr->green;
907 buf[2] = pal_ptr->blue;
908 png_write_chunk_data(png_ptr, buf, 3);
909 }
910
911#else
912 /* This is a little slower but some buggy compilers need to do this
913 * instead
914 */
915 pal_ptr=palette;
916
917 for (i = 0; i < num_pal; i++)
918 {
919 buf[0] = pal_ptr[i].red;
920 buf[1] = pal_ptr[i].green;
921 buf[2] = pal_ptr[i].blue;
922 png_write_chunk_data(png_ptr, buf, 3);
923 }
924
925#endif
926 png_write_chunk_end(png_ptr);
927 png_ptr->mode |= PNG_HAVE_PLTE;
928}
929
930/* This is similar to png_text_compress, above, except that it does not require
931 * all of the data at once and, instead of buffering the compressed result,
932 * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out
933 * because it calls the write interface. As a result it does its own error
934 * reporting and does not return an error code. In the event of error it will
935 * just call png_error. The input data length may exceed 32-bits. The 'flush'
936 * parameter is exactly the same as that to deflate, with the following
937 * meanings:
938 *
939 * Z_NO_FLUSH: normal incremental output of compressed data
940 * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
941 * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
942 *
943 * The routine manages the acquire and release of the png_ptr->zstream by
944 * checking and (at the end) clearing png_ptr->zowner; it does some sanity
945 * checks on the 'mode' flags while doing this.
946 */
947void /* PRIVATE */
948png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
949 png_alloc_size_t input_len, int flush)
950{
951 if (png_ptr->zowner != png_IDAT)
952 {
953 /* First time. Ensure we have a temporary buffer for compression and
954 * trim the buffer list if it has more than one entry to free memory.
955 * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
956 * created at this point, but the check here is quick and safe.
957 */
958 if (png_ptr->zbuffer_list == NULL)
959 {
960 png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
961 png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
962 png_ptr->zbuffer_list->next = NULL;
963 }
964
965 else
966 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
967
968 /* It is a terminal error if we can't claim the zstream. */
969 if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
970 png_error(png_ptr, png_ptr->zstream.msg);
971
972 /* The output state is maintained in png_ptr->zstream, so it must be
973 * initialized here after the claim.
974 */
975 png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
976 png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
977 }
978
979 /* Now loop reading and writing until all the input is consumed or an error
980 * terminates the operation. The _out values are maintained across calls to
981 * this function, but the input must be reset each time.
982 */
983 png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
984 png_ptr->zstream.avail_in = 0; /* set below */
985 for (;;)
986 {
987 int ret;
988
989 /* INPUT: from the row data */
991
992 if (avail > input_len)
993 avail = (uInt)input_len; /* safe because of the check */
994
995 png_ptr->zstream.avail_in = avail;
996 input_len -= avail;
997
998 ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
999
1000 /* Include as-yet unconsumed input */
1001 input_len += png_ptr->zstream.avail_in;
1002 png_ptr->zstream.avail_in = 0;
1003
1004 /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
1005 * that these two zstream fields are preserved across the calls, therefore
1006 * there is no need to set these up on entry to the loop.
1007 */
1008 if (png_ptr->zstream.avail_out == 0)
1009 {
1010 png_bytep data = png_ptr->zbuffer_list->output;
1011 uInt size = png_ptr->zbuffer_size;
1012
1013 /* Write an IDAT containing the data then reset the buffer. The
1014 * first IDAT may need deflate header optimization.
1015 */
1016#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
1017 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
1018 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
1019 optimize_cmf(data, png_image_size(png_ptr));
1020#endif
1021
1022 if (size > 0)
1023 png_write_complete_chunk(png_ptr, png_IDAT, data, size);
1024 png_ptr->mode |= PNG_HAVE_IDAT;
1025
1026 png_ptr->zstream.next_out = data;
1027 png_ptr->zstream.avail_out = size;
1028
1029 /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
1030 * the same flush parameter until it has finished output, for NO_FLUSH
1031 * it doesn't matter.
1032 */
1033 if (ret == Z_OK && flush != Z_NO_FLUSH)
1034 continue;
1035 }
1036
1037 /* The order of these checks doesn't matter much; it just affects which
1038 * possible error might be detected if multiple things go wrong at once.
1039 */
1040 if (ret == Z_OK) /* most likely return code! */
1041 {
1042 /* If all the input has been consumed then just return. If Z_FINISH
1043 * was used as the flush parameter something has gone wrong if we get
1044 * here.
1045 */
1046 if (input_len == 0)
1047 {
1048 if (flush == Z_FINISH)
1049 png_error(png_ptr, "Z_OK on Z_FINISH with output space");
1050
1051 return;
1052 }
1053 }
1054
1055 else if (ret == Z_STREAM_END && flush == Z_FINISH)
1056 {
1057 /* This is the end of the IDAT data; any pending output must be
1058 * flushed. For small PNG files we may still be at the beginning.
1059 */
1060 png_bytep data = png_ptr->zbuffer_list->output;
1061 uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
1062
1063#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
1064 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
1065 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
1066 optimize_cmf(data, png_image_size(png_ptr));
1067#endif
1068
1069 if (size > 0)
1070 png_write_complete_chunk(png_ptr, png_IDAT, data, size);
1071 png_ptr->zstream.avail_out = 0;
1072 png_ptr->zstream.next_out = NULL;
1074
1075 png_ptr->zowner = 0; /* Release the stream */
1076 return;
1077 }
1078
1079 else
1080 {
1081 /* This is an error condition. */
1082 png_zstream_error(png_ptr, ret);
1083 png_error(png_ptr, png_ptr->zstream.msg);
1084 }
1085 }
1086}
1087
1088/* Write an IEND chunk */
1089void /* PRIVATE */
1090png_write_IEND(png_structrp png_ptr)
1091{
1092 png_debug(1, "in png_write_IEND");
1093
1094 png_write_complete_chunk(png_ptr, png_IEND, NULL, 0);
1095 png_ptr->mode |= PNG_HAVE_IEND;
1096}
1097
1098#ifdef PNG_WRITE_gAMA_SUPPORTED
1099/* Write a gAMA chunk */
1100void /* PRIVATE */
1101png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
1102{
1103 png_byte buf[4];
1104
1105 png_debug(1, "in png_write_gAMA");
1106
1107 /* file_gamma is saved in 1/100,000ths */
1108 png_save_uint_32(buf, (png_uint_32)file_gamma);
1109 png_write_complete_chunk(png_ptr, png_gAMA, buf, 4);
1110}
1111#endif
1112
1113#ifdef PNG_WRITE_sRGB_SUPPORTED
1114/* Write a sRGB chunk */
1115void /* PRIVATE */
1116png_write_sRGB(png_structrp png_ptr, int srgb_intent)
1117{
1118 png_byte buf[1];
1119
1120 png_debug(1, "in png_write_sRGB");
1121
1122 if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1123 png_warning(png_ptr,
1124 "Invalid sRGB rendering intent specified");
1125
1126 buf[0]=(png_byte)srgb_intent;
1127 png_write_complete_chunk(png_ptr, png_sRGB, buf, 1);
1128}
1129#endif
1130
1131#ifdef PNG_WRITE_iCCP_SUPPORTED
1132/* Write an iCCP chunk */
1133void /* PRIVATE */
1135 png_const_bytep profile, png_uint_32 profile_len)
1136{
1137 png_uint_32 name_len;
1138 png_byte new_name[81]; /* 1 byte for the compression byte */
1139 compression_state comp;
1141
1142 png_debug(1, "in png_write_iCCP");
1143
1144 /* These are all internal problems: the profile should have been checked
1145 * before when it was stored.
1146 */
1147 if (profile == NULL)
1148 png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
1149
1150 if (profile_len < 132)
1151 png_error(png_ptr, "ICC profile too short");
1152
1153 if (png_get_uint_32(profile) != profile_len)
1154 png_error(png_ptr, "Incorrect data in iCCP");
1155
1156 temp = (png_uint_32) (*(profile+8));
1157 if (temp > 3 && (profile_len & 0x03))
1158 png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
1159
1160 {
1161 png_uint_32 embedded_profile_len = png_get_uint_32(profile);
1162
1163 if (profile_len != embedded_profile_len)
1164 png_error(png_ptr, "Profile length does not match profile");
1165 }
1166
1167 name_len = png_check_keyword(png_ptr, name, new_name);
1168
1169 if (name_len == 0)
1170 png_error(png_ptr, "iCCP: invalid keyword");
1171
1172 new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
1173
1174 /* Make sure we include the NULL after the name and the compression type */
1175 ++name_len;
1176
1177 png_text_compress_init(&comp, profile, profile_len);
1178
1179 /* Allow for keyword terminator and compression byte */
1180 if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
1181 png_error(png_ptr, png_ptr->zstream.msg);
1182
1183 png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
1184
1185 png_write_chunk_data(png_ptr, new_name, name_len);
1186
1187 png_write_compressed_data_out(png_ptr, &comp);
1188
1189 png_write_chunk_end(png_ptr);
1190}
1191#endif
1192
1193#ifdef PNG_WRITE_sPLT_SUPPORTED
1194/* Write a sPLT chunk */
1195void /* PRIVATE */
1196png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
1197{
1198 png_uint_32 name_len;
1199 png_byte new_name[80];
1200 png_byte entrybuf[10];
1201 size_t entry_size = (spalette->depth == 8 ? 6 : 10);
1202 size_t palette_size = entry_size * (size_t)spalette->nentries;
1203 png_sPLT_entryp ep;
1205 int i;
1206#endif
1207
1208 png_debug(1, "in png_write_sPLT");
1209
1210 name_len = png_check_keyword(png_ptr, spalette->name, new_name);
1211
1212 if (name_len == 0)
1213 png_error(png_ptr, "sPLT: invalid keyword");
1214
1215 /* Make sure we include the NULL after the name */
1216 png_write_chunk_header(png_ptr, png_sPLT,
1217 (png_uint_32)(name_len + 2 + palette_size));
1218
1219 png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1));
1220
1221 png_write_chunk_data(png_ptr, &spalette->depth, 1);
1222
1223 /* Loop through each palette entry, writing appropriately */
1224#ifdef PNG_POINTER_INDEXING_SUPPORTED
1225 for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1226 {
1227 if (spalette->depth == 8)
1228 {
1229 entrybuf[0] = (png_byte)ep->red;
1230 entrybuf[1] = (png_byte)ep->green;
1231 entrybuf[2] = (png_byte)ep->blue;
1232 entrybuf[3] = (png_byte)ep->alpha;
1233 png_save_uint_16(entrybuf + 4, ep->frequency);
1234 }
1235
1236 else
1237 {
1238 png_save_uint_16(entrybuf + 0, ep->red);
1239 png_save_uint_16(entrybuf + 2, ep->green);
1240 png_save_uint_16(entrybuf + 4, ep->blue);
1241 png_save_uint_16(entrybuf + 6, ep->alpha);
1242 png_save_uint_16(entrybuf + 8, ep->frequency);
1243 }
1244
1245 png_write_chunk_data(png_ptr, entrybuf, entry_size);
1246 }
1247#else
1248 ep=spalette->entries;
1249 for (i = 0; i>spalette->nentries; i++)
1250 {
1251 if (spalette->depth == 8)
1252 {
1253 entrybuf[0] = (png_byte)ep[i].red;
1254 entrybuf[1] = (png_byte)ep[i].green;
1255 entrybuf[2] = (png_byte)ep[i].blue;
1256 entrybuf[3] = (png_byte)ep[i].alpha;
1257 png_save_uint_16(entrybuf + 4, ep[i].frequency);
1258 }
1259
1260 else
1261 {
1262 png_save_uint_16(entrybuf + 0, ep[i].red);
1263 png_save_uint_16(entrybuf + 2, ep[i].green);
1264 png_save_uint_16(entrybuf + 4, ep[i].blue);
1265 png_save_uint_16(entrybuf + 6, ep[i].alpha);
1266 png_save_uint_16(entrybuf + 8, ep[i].frequency);
1267 }
1268
1269 png_write_chunk_data(png_ptr, entrybuf, entry_size);
1270 }
1271#endif
1272
1273 png_write_chunk_end(png_ptr);
1274}
1275#endif
1276
1277#ifdef PNG_WRITE_sBIT_SUPPORTED
1278/* Write the sBIT chunk */
1279void /* PRIVATE */
1280png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
1281{
1282 png_byte buf[4];
1283 size_t size;
1284
1285 png_debug(1, "in png_write_sBIT");
1286
1287 /* Make sure we don't depend upon the order of PNG_COLOR_8 */
1288 if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
1289 {
1290 png_byte maxbits;
1291
1292 maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
1293 png_ptr->usr_bit_depth);
1294
1295 if (sbit->red == 0 || sbit->red > maxbits ||
1296 sbit->green == 0 || sbit->green > maxbits ||
1297 sbit->blue == 0 || sbit->blue > maxbits)
1298 {
1299 png_warning(png_ptr, "Invalid sBIT depth specified");
1300 return;
1301 }
1302
1303 buf[0] = sbit->red;
1304 buf[1] = sbit->green;
1305 buf[2] = sbit->blue;
1306 size = 3;
1307 }
1308
1309 else
1310 {
1311 if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
1312 {
1313 png_warning(png_ptr, "Invalid sBIT depth specified");
1314 return;
1315 }
1316
1317 buf[0] = sbit->gray;
1318 size = 1;
1319 }
1320
1321 if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
1322 {
1323 if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
1324 {
1325 png_warning(png_ptr, "Invalid sBIT depth specified");
1326 return;
1327 }
1328
1329 buf[size++] = sbit->alpha;
1330 }
1331
1332 png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
1333}
1334#endif
1335
1336#ifdef PNG_WRITE_cHRM_SUPPORTED
1337/* Write the cHRM chunk */
1338void /* PRIVATE */
1339png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
1340{
1341 png_byte buf[32];
1342
1343 png_debug(1, "in png_write_cHRM");
1344
1345 /* Each value is saved in 1/100,000ths */
1346 png_save_int_32(buf, xy->whitex);
1347 png_save_int_32(buf + 4, xy->whitey);
1348
1349 png_save_int_32(buf + 8, xy->redx);
1350 png_save_int_32(buf + 12, xy->redy);
1351
1352 png_save_int_32(buf + 16, xy->greenx);
1353 png_save_int_32(buf + 20, xy->greeny);
1354
1355 png_save_int_32(buf + 24, xy->bluex);
1356 png_save_int_32(buf + 28, xy->bluey);
1357
1358 png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
1359}
1360#endif
1361
1362#ifdef PNG_WRITE_tRNS_SUPPORTED
1363/* Write the tRNS chunk */
1364void /* PRIVATE */
1365png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
1366 png_const_color_16p tran, int num_trans, int color_type)
1367{
1368 png_byte buf[6];
1369
1370 png_debug(1, "in png_write_tRNS");
1371
1372 if (color_type == PNG_COLOR_TYPE_PALETTE)
1373 {
1374 if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
1375 {
1377 "Invalid number of transparent colors specified");
1378 return;
1379 }
1380
1381 /* Write the chunk out as it is */
1382 png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
1383 (size_t)num_trans);
1384 }
1385
1386 else if (color_type == PNG_COLOR_TYPE_GRAY)
1387 {
1388 /* One 16-bit value */
1389 if (tran->gray >= (1 << png_ptr->bit_depth))
1390 {
1392 "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1393
1394 return;
1395 }
1396
1397 png_save_uint_16(buf, tran->gray);
1398 png_write_complete_chunk(png_ptr, png_tRNS, buf, 2);
1399 }
1400
1401 else if (color_type == PNG_COLOR_TYPE_RGB)
1402 {
1403 /* Three 16-bit values */
1404 png_save_uint_16(buf, tran->red);
1405 png_save_uint_16(buf + 2, tran->green);
1406 png_save_uint_16(buf + 4, tran->blue);
1407#ifdef PNG_WRITE_16BIT_SUPPORTED
1408 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1409#else
1410 if ((buf[0] | buf[2] | buf[4]) != 0)
1411#endif
1412 {
1414 "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1415 return;
1416 }
1417
1418 png_write_complete_chunk(png_ptr, png_tRNS, buf, 6);
1419 }
1420
1421 else
1422 {
1423 png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
1424 }
1425}
1426#endif
1427
1428#ifdef PNG_WRITE_bKGD_SUPPORTED
1429/* Write the background chunk */
1430void /* PRIVATE */
1431png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
1432{
1433 png_byte buf[6];
1434
1435 png_debug(1, "in png_write_bKGD");
1436
1437 if (color_type == PNG_COLOR_TYPE_PALETTE)
1438 {
1439 if (
1441 (png_ptr->num_palette != 0 ||
1442 (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
1443#endif
1444 back->index >= png_ptr->num_palette)
1445 {
1446 png_warning(png_ptr, "Invalid background palette index");
1447 return;
1448 }
1449
1450 buf[0] = back->index;
1451 png_write_complete_chunk(png_ptr, png_bKGD, buf, 1);
1452 }
1453
1454 else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
1455 {
1456 png_save_uint_16(buf, back->red);
1457 png_save_uint_16(buf + 2, back->green);
1458 png_save_uint_16(buf + 4, back->blue);
1459#ifdef PNG_WRITE_16BIT_SUPPORTED
1460 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
1461#else
1462 if ((buf[0] | buf[2] | buf[4]) != 0)
1463#endif
1464 {
1465 png_warning(png_ptr,
1466 "Ignoring attempt to write 16-bit bKGD chunk "
1467 "when bit_depth is 8");
1468
1469 return;
1470 }
1471
1472 png_write_complete_chunk(png_ptr, png_bKGD, buf, 6);
1473 }
1474
1475 else
1476 {
1477 if (back->gray >= (1 << png_ptr->bit_depth))
1478 {
1479 png_warning(png_ptr,
1480 "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1481
1482 return;
1483 }
1484
1485 png_save_uint_16(buf, back->gray);
1486 png_write_complete_chunk(png_ptr, png_bKGD, buf, 2);
1487 }
1488}
1489#endif
1490
1491#ifdef PNG_WRITE_cICP_SUPPORTED
1492/* Write the cICP data */
1493void /* PRIVATE */
1494png_write_cICP(png_structrp png_ptr,
1495 png_byte colour_primaries, png_byte transfer_function,
1496 png_byte matrix_coefficients, png_byte video_full_range_flag)
1497{
1498 png_byte buf[4];
1499
1500 png_debug(1, "in png_write_cICP");
1501
1502 png_write_chunk_header(png_ptr, png_cICP, 4);
1503
1504 buf[0] = colour_primaries;
1505 buf[1] = transfer_function;
1506 buf[2] = matrix_coefficients;
1507 buf[3] = video_full_range_flag;
1508 png_write_chunk_data(png_ptr, buf, 4);
1509
1510 png_write_chunk_end(png_ptr);
1511}
1512#endif
1513
1514#ifdef PNG_WRITE_cLLI_SUPPORTED
1515void /* PRIVATE */
1516png_write_cLLI_fixed(png_structrp png_ptr, png_uint_32 maxCLL,
1517 png_uint_32 maxFALL)
1518{
1519 png_byte buf[8];
1520
1521 png_debug(1, "in png_write_cLLI_fixed");
1522
1523 png_save_uint_32(buf, maxCLL);
1524 png_save_uint_32(buf + 4, maxFALL);
1525
1526 png_write_complete_chunk(png_ptr, png_cLLI, buf, 8);
1527}
1528#endif
1529
1530#ifdef PNG_WRITE_mDCV_SUPPORTED
1531void /* PRIVATE */
1532png_write_mDCV_fixed(png_structrp png_ptr,
1533 png_uint_16 red_x, png_uint_16 red_y,
1534 png_uint_16 green_x, png_uint_16 green_y,
1535 png_uint_16 blue_x, png_uint_16 blue_y,
1536 png_uint_16 white_x, png_uint_16 white_y,
1537 png_uint_32 maxDL, png_uint_32 minDL)
1538{
1539 png_byte buf[24];
1540
1541 png_debug(1, "in png_write_mDCV_fixed");
1542
1543 png_save_uint_16(buf + 0, red_x);
1544 png_save_uint_16(buf + 2, red_y);
1545 png_save_uint_16(buf + 4, green_x);
1546 png_save_uint_16(buf + 6, green_y);
1547 png_save_uint_16(buf + 8, blue_x);
1548 png_save_uint_16(buf + 10, blue_y);
1549 png_save_uint_16(buf + 12, white_x);
1550 png_save_uint_16(buf + 14, white_y);
1551 png_save_uint_32(buf + 16, maxDL);
1552 png_save_uint_32(buf + 20, minDL);
1553
1554 png_write_complete_chunk(png_ptr, png_mDCV, buf, 24);
1555}
1556#endif
1557
1558#ifdef PNG_WRITE_eXIf_SUPPORTED
1559/* Write the Exif data */
1560void /* PRIVATE */
1561png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif)
1562{
1563 int i;
1564 png_byte buf[1];
1565
1566 png_debug(1, "in png_write_eXIf");
1567
1568 png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif));
1569
1570 for (i = 0; i < num_exif; i++)
1571 {
1572 buf[0] = exif[i];
1573 png_write_chunk_data(png_ptr, buf, 1);
1574 }
1575
1576 png_write_chunk_end(png_ptr);
1577}
1578#endif
1579
1580#ifdef PNG_WRITE_hIST_SUPPORTED
1581/* Write the histogram */
1582void /* PRIVATE */
1583png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
1584{
1585 int i;
1586 png_byte buf[3];
1587
1588 png_debug(1, "in png_write_hIST");
1589
1590 if (num_hist > (int)png_ptr->num_palette)
1591 {
1592 png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1593 png_ptr->num_palette);
1594
1595 png_warning(png_ptr, "Invalid number of histogram entries specified");
1596 return;
1597 }
1598
1599 png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1600
1601 for (i = 0; i < num_hist; i++)
1602 {
1603 png_save_uint_16(buf, hist[i]);
1604 png_write_chunk_data(png_ptr, buf, 2);
1605 }
1606
1607 png_write_chunk_end(png_ptr);
1608}
1609#endif
1610
1611#ifdef PNG_WRITE_tEXt_SUPPORTED
1612/* Write a tEXt chunk */
1613void /* PRIVATE */
1615 size_t text_len)
1616{
1617 png_uint_32 key_len;
1618 png_byte new_key[80];
1619
1620 png_debug(1, "in png_write_tEXt");
1621
1622 key_len = png_check_keyword(png_ptr, key, new_key);
1623
1624 if (key_len == 0)
1625 png_error(png_ptr, "tEXt: invalid keyword");
1626
1627 if (text == NULL || *text == '\0')
1628 text_len = 0;
1629
1630 else
1631 text_len = strlen(text);
1632
1633 if (text_len > PNG_UINT_31_MAX - (key_len+1))
1634 png_error(png_ptr, "tEXt: text too long");
1635
1636 /* Make sure we include the 0 after the key */
1637 png_write_chunk_header(png_ptr, png_tEXt,
1638 (png_uint_32)/*checked above*/(key_len + text_len + 1));
1639 /*
1640 * We leave it to the application to meet PNG-1.0 requirements on the
1641 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1642 * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1643 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1644 */
1645 png_write_chunk_data(png_ptr, new_key, key_len + 1);
1646
1647 if (text_len != 0)
1648 png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
1649
1650 png_write_chunk_end(png_ptr);
1651}
1652#endif
1653
1654#ifdef PNG_WRITE_zTXt_SUPPORTED
1655/* Write a compressed text chunk */
1656void /* PRIVATE */
1658 int compression)
1659{
1660 png_uint_32 key_len;
1661 png_byte new_key[81];
1662 compression_state comp;
1663
1664 png_debug(1, "in png_write_zTXt");
1665
1667 {
1668 png_write_tEXt(png_ptr, key, text, 0);
1669 return;
1670 }
1671
1673 png_error(png_ptr, "zTXt: invalid compression type");
1674
1675 key_len = png_check_keyword(png_ptr, key, new_key);
1676
1677 if (key_len == 0)
1678 png_error(png_ptr, "zTXt: invalid keyword");
1679
1680 /* Add the compression method and 1 for the keyword separator. */
1682 ++key_len;
1683
1684 /* Compute the compressed data; do it now for the length */
1685 png_text_compress_init(&comp, (png_const_bytep)text,
1686 text == NULL ? 0 : strlen(text));
1687
1688 if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
1689 png_error(png_ptr, png_ptr->zstream.msg);
1690
1691 /* Write start of chunk */
1692 png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
1693
1694 /* Write key */
1695 png_write_chunk_data(png_ptr, new_key, key_len);
1696
1697 /* Write the compressed data */
1698 png_write_compressed_data_out(png_ptr, &comp);
1699
1700 /* Close the chunk */
1701 png_write_chunk_end(png_ptr);
1702}
1703#endif
1704
1705#ifdef PNG_WRITE_iTXt_SUPPORTED
1706/* Write an iTXt chunk */
1707void /* PRIVATE */
1710{
1711 png_uint_32 key_len, prefix_len;
1712 size_t lang_len, lang_key_len;
1713 png_byte new_key[82];
1714 compression_state comp;
1715
1716 png_debug(1, "in png_write_iTXt");
1717
1718 key_len = png_check_keyword(png_ptr, key, new_key);
1719
1720 if (key_len == 0)
1721 png_error(png_ptr, "iTXt: invalid keyword");
1722
1723 /* Set the compression flag */
1724 switch (compression)
1725 {
1728 compression = new_key[++key_len] = 0; /* no compression */
1729 break;
1730
1733 compression = new_key[++key_len] = 1; /* compressed */
1734 break;
1735
1736 default:
1737 png_error(png_ptr, "iTXt: invalid compression");
1738 }
1739
1741 ++key_len; /* for the keywod separator */
1742
1743 /* We leave it to the application to meet PNG-1.0 requirements on the
1744 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1745 * any non-Latin-1 characters except for NEWLINE. ISO PNG, however,
1746 * specifies that the text is UTF-8 and this really doesn't require any
1747 * checking.
1748 *
1749 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1750 *
1751 * TODO: validate the language tag correctly (see the spec.)
1752 */
1753 if (lang == NULL) lang = ""; /* empty language is valid */
1754 lang_len = strlen(lang)+1;
1755 if (lang_key == NULL) lang_key = ""; /* may be empty */
1756 lang_key_len = strlen(lang_key)+1;
1757 if (text == NULL) text = ""; /* may be empty */
1758
1759 prefix_len = key_len;
1760 if (lang_len > PNG_UINT_31_MAX-prefix_len)
1761 prefix_len = PNG_UINT_31_MAX;
1762 else
1763 prefix_len = (png_uint_32)(prefix_len + lang_len);
1764
1765 if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
1766 prefix_len = PNG_UINT_31_MAX;
1767 else
1768 prefix_len = (png_uint_32)(prefix_len + lang_key_len);
1769
1770 png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
1771
1772 if (compression != 0)
1773 {
1774 if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
1775 png_error(png_ptr, png_ptr->zstream.msg);
1776 }
1777
1778 else
1779 {
1780 if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
1781 png_error(png_ptr, "iTXt: uncompressed text too long");
1782
1783 /* So the string will fit in a chunk: */
1784 comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
1785 }
1786
1787 png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
1788
1789 png_write_chunk_data(png_ptr, new_key, key_len);
1790
1791 png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
1792
1793 png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
1794
1795 if (compression != 0)
1796 png_write_compressed_data_out(png_ptr, &comp);
1797
1798 else
1799 png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
1800
1801 png_write_chunk_end(png_ptr);
1802}
1803#endif
1804
1805#ifdef PNG_WRITE_oFFs_SUPPORTED
1806/* Write the oFFs chunk */
1807void /* PRIVATE */
1808png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1809 int unit_type)
1810{
1811 png_byte buf[9];
1812
1813 png_debug(1, "in png_write_oFFs");
1814
1815 if (unit_type >= PNG_OFFSET_LAST)
1816 png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
1817
1818 png_save_int_32(buf, x_offset);
1819 png_save_int_32(buf + 4, y_offset);
1820 buf[8] = (png_byte)unit_type;
1821
1822 png_write_complete_chunk(png_ptr, png_oFFs, buf, 9);
1823}
1824#endif
1825#ifdef PNG_WRITE_pCAL_SUPPORTED
1826/* Write the pCAL chunk (described in the PNG extensions document) */
1827void /* PRIVATE */
1828png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
1829 png_int_32 X1, int type, int nparams, png_const_charp units,
1831{
1832 png_uint_32 purpose_len;
1833 size_t units_len, total_len;
1834 size_t *params_len;
1835 png_byte buf[10];
1836 png_byte new_purpose[80];
1837 int i;
1838
1839 png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1840
1841 if (type >= PNG_EQUATION_LAST)
1842 png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
1843
1844 purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
1845
1846 if (purpose_len == 0)
1847 png_error(png_ptr, "pCAL: invalid keyword");
1848
1849 ++purpose_len; /* terminator */
1850
1851 png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
1852 units_len = strlen(units) + (nparams == 0 ? 0 : 1);
1853 png_debug1(3, "pCAL units length = %d", (int)units_len);
1854 total_len = purpose_len + units_len + 10;
1855
1856 params_len = (size_t *)png_malloc(png_ptr,
1857 (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t))));
1858
1859 /* Find the length of each parameter, making sure we don't count the
1860 * null terminator for the last parameter.
1861 */
1862 for (i = 0; i < nparams; i++)
1863 {
1864 params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1865 png_debug2(3, "pCAL parameter %d length = %lu", i,
1866 (unsigned long)params_len[i]);
1867 total_len += params_len[i];
1868 }
1869
1870 png_debug1(3, "pCAL total length = %d", (int)total_len);
1871 png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
1872 png_write_chunk_data(png_ptr, new_purpose, purpose_len);
1873 png_save_int_32(buf, X0);
1874 png_save_int_32(buf + 4, X1);
1875 buf[8] = (png_byte)type;
1876 buf[9] = (png_byte)nparams;
1877 png_write_chunk_data(png_ptr, buf, 10);
1878 png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len);
1879
1880 for (i = 0; i < nparams; i++)
1881 {
1882 png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
1883 }
1884
1885 png_free(png_ptr, params_len);
1886 png_write_chunk_end(png_ptr);
1887}
1888#endif
1889
1890#ifdef PNG_WRITE_sCAL_SUPPORTED
1891/* Write the sCAL chunk */
1892void /* PRIVATE */
1893png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
1895{
1896 png_byte buf[64];
1897 size_t wlen, hlen, total_len;
1898
1899 png_debug(1, "in png_write_sCAL_s");
1900
1901 wlen = strlen(width);
1902 hlen = strlen(height);
1903 total_len = wlen + hlen + 2;
1904
1905 if (total_len > 64)
1906 {
1907 png_warning(png_ptr, "Can't write sCAL (buffer too small)");
1908 return;
1909 }
1910
1911 buf[0] = (png_byte)unit;
1912 memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
1913 memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
1914
1915 png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1916 png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1917}
1918#endif
1919
1920#ifdef PNG_WRITE_pHYs_SUPPORTED
1921/* Write the pHYs chunk */
1922void /* PRIVATE */
1923png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
1924 png_uint_32 y_pixels_per_unit,
1925 int unit_type)
1926{
1927 png_byte buf[9];
1928
1929 png_debug(1, "in png_write_pHYs");
1930
1931 if (unit_type >= PNG_RESOLUTION_LAST)
1932 png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
1933
1934 png_save_uint_32(buf, x_pixels_per_unit);
1935 png_save_uint_32(buf + 4, y_pixels_per_unit);
1936 buf[8] = (png_byte)unit_type;
1937
1938 png_write_complete_chunk(png_ptr, png_pHYs, buf, 9);
1939}
1940#endif
1941
1942#ifdef PNG_WRITE_tIME_SUPPORTED
1943/* Write the tIME chunk. Use either png_convert_from_struct_tm()
1944 * or png_convert_from_time_t(), or fill in the structure yourself.
1945 */
1946void /* PRIVATE */
1947png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
1948{
1949 png_byte buf[7];
1950
1951 png_debug(1, "in png_write_tIME");
1952
1953 if (mod_time->month > 12 || mod_time->month < 1 ||
1954 mod_time->day > 31 || mod_time->day < 1 ||
1955 mod_time->hour > 23 || mod_time->second > 60)
1956 {
1957 png_warning(png_ptr, "Invalid time specified for tIME chunk");
1958 return;
1959 }
1960
1961 png_save_uint_16(buf, mod_time->year);
1962 buf[2] = mod_time->month;
1963 buf[3] = mod_time->day;
1964 buf[4] = mod_time->hour;
1965 buf[5] = mod_time->minute;
1966 buf[6] = mod_time->second;
1967
1968 png_write_complete_chunk(png_ptr, png_tIME, buf, 7);
1969}
1970#endif
1971
1972/* Initializes the row writing capability of libpng */
1973void /* PRIVATE */
1974png_write_start_row(png_structrp png_ptr)
1975{
1976 png_alloc_size_t buf_size;
1977 int usr_pixel_depth;
1978
1979#ifdef PNG_WRITE_FILTER_SUPPORTED
1980 png_byte filters;
1981#endif
1982
1983 png_debug(1, "in png_write_start_row");
1984
1985 usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
1986 buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
1987
1988 /* 1.5.6: added to allow checking in the row write code. */
1989 png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
1990 png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
1991
1992 /* Set up row buffer */
1993 png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
1994
1995 png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
1996
1997#ifdef PNG_WRITE_FILTER_SUPPORTED
1998 filters = png_ptr->do_filter;
1999
2000 if (png_ptr->height == 1)
2001 filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
2002
2003 if (png_ptr->width == 1)
2004 filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
2005
2006 if (filters == 0)
2007 filters = PNG_FILTER_NONE;
2008
2009 png_ptr->do_filter = filters;
2010
2011 if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG |
2012 PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL)
2013 {
2014 int num_filters = 0;
2015
2016 png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
2017
2018 if (filters & PNG_FILTER_SUB)
2019 num_filters++;
2020
2021 if (filters & PNG_FILTER_UP)
2022 num_filters++;
2023
2024 if (filters & PNG_FILTER_AVG)
2025 num_filters++;
2026
2027 if (filters & PNG_FILTER_PAETH)
2028 num_filters++;
2029
2030 if (num_filters > 1)
2031 png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr,
2032 buf_size));
2033 }
2034
2035 /* We only need to keep the previous row if we are using one of the following
2036 * filters.
2037 */
2038 if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
2039 png_ptr->prev_row = png_voidcast(png_bytep,
2040 png_calloc(png_ptr, buf_size));
2041#endif /* WRITE_FILTER */
2042
2043#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2044 /* If interlaced, we need to set up width and height of pass */
2045 if (png_ptr->interlaced != 0)
2046 {
2047 if ((png_ptr->transformations & PNG_INTERLACE) == 0)
2048 {
2049 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2050 png_pass_ystart[0]) / png_pass_yinc[0];
2051
2052 png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2053 png_pass_start[0]) / png_pass_inc[0];
2054 }
2055
2056 else
2057 {
2058 png_ptr->num_rows = png_ptr->height;
2059 png_ptr->usr_width = png_ptr->width;
2060 }
2061 }
2062
2063 else
2064#endif
2065 {
2066 png_ptr->num_rows = png_ptr->height;
2067 png_ptr->usr_width = png_ptr->width;
2068 }
2069}
2070
2071/* Internal use only. Called when finished processing a row of data. */
2072void /* PRIVATE */
2073png_write_finish_row(png_structrp png_ptr)
2074{
2075 png_debug(1, "in png_write_finish_row");
2076
2077 /* Next row */
2078 png_ptr->row_number++;
2079
2080 /* See if we are done */
2081 if (png_ptr->row_number < png_ptr->num_rows)
2082 return;
2083
2084#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2085 /* If interlaced, go to next pass */
2086 if (png_ptr->interlaced != 0)
2087 {
2088 png_ptr->row_number = 0;
2089 if ((png_ptr->transformations & PNG_INTERLACE) != 0)
2090 {
2091 png_ptr->pass++;
2092 }
2093
2094 else
2095 {
2096 /* Loop until we find a non-zero width or height pass */
2097 do
2098 {
2099 png_ptr->pass++;
2100
2101 if (png_ptr->pass >= 7)
2102 break;
2103
2104 png_ptr->usr_width = (png_ptr->width +
2105 png_pass_inc[png_ptr->pass] - 1 -
2106 png_pass_start[png_ptr->pass]) /
2107 png_pass_inc[png_ptr->pass];
2108
2109 png_ptr->num_rows = (png_ptr->height +
2110 png_pass_yinc[png_ptr->pass] - 1 -
2111 png_pass_ystart[png_ptr->pass]) /
2112 png_pass_yinc[png_ptr->pass];
2113
2114 if ((png_ptr->transformations & PNG_INTERLACE) != 0)
2115 break;
2116
2117 } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
2118
2119 }
2120
2121 /* Reset the row above the image for the next pass */
2122 if (png_ptr->pass < 7)
2123 {
2124 if (png_ptr->prev_row != NULL)
2125 memset(png_ptr->prev_row, 0,
2126 PNG_ROWBYTES(png_ptr->usr_channels *
2127 png_ptr->usr_bit_depth, png_ptr->width) + 1);
2128
2129 return;
2130 }
2131 }
2132#endif
2133
2134 /* If we get here, we've just written the last row, so we need
2135 to flush the compressor */
2136 png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
2137}
2138
2139#ifdef PNG_WRITE_INTERLACING_SUPPORTED
2140/* Pick out the correct pixels for the interlace pass.
2141 * The basic idea here is to go through the row with a source
2142 * pointer and a destination pointer (sp and dp), and copy the
2143 * correct pixels for the pass. As the row gets compacted,
2144 * sp will always be >= dp, so we should never overwrite anything.
2145 * See the default: case for the easiest code to understand.
2146 */
2147void /* PRIVATE */
2148png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
2149{
2150 png_debug(1, "in png_do_write_interlace");
2151
2152 /* We don't have to do anything on the last pass (6) */
2153 if (pass < 6)
2154 {
2155 /* Each pixel depth is handled separately */
2156 switch (row_info->pixel_depth)
2157 {
2158 case 1:
2159 {
2160 png_bytep sp;
2161 png_bytep dp;
2162 unsigned int shift;
2163 int d;
2164 int value;
2165 png_uint_32 i;
2166 png_uint_32 row_width = row_info->width;
2167
2168 dp = row;
2169 d = 0;
2170 shift = 7;
2171
2172 for (i = png_pass_start[pass]; i < row_width;
2173 i += png_pass_inc[pass])
2174 {
2175 sp = row + (size_t)(i >> 3);
2176 value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
2177 d |= (value << shift);
2178
2179 if (shift == 0)
2180 {
2181 shift = 7;
2182 *dp++ = (png_byte)d;
2183 d = 0;
2184 }
2185
2186 else
2187 shift--;
2188
2189 }
2190 if (shift != 7)
2191 *dp = (png_byte)d;
2192
2193 break;
2194 }
2195
2196 case 2:
2197 {
2198 png_bytep sp;
2199 png_bytep dp;
2200 unsigned int shift;
2201 int d;
2202 int value;
2203 png_uint_32 i;
2204 png_uint_32 row_width = row_info->width;
2205
2206 dp = row;
2207 shift = 6;
2208 d = 0;
2209
2210 for (i = png_pass_start[pass]; i < row_width;
2211 i += png_pass_inc[pass])
2212 {
2213 sp = row + (size_t)(i >> 2);
2214 value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
2215 d |= (value << shift);
2216
2217 if (shift == 0)
2218 {
2219 shift = 6;
2220 *dp++ = (png_byte)d;
2221 d = 0;
2222 }
2223
2224 else
2225 shift -= 2;
2226 }
2227 if (shift != 6)
2228 *dp = (png_byte)d;
2229
2230 break;
2231 }
2232
2233 case 4:
2234 {
2235 png_bytep sp;
2236 png_bytep dp;
2237 unsigned int shift;
2238 int d;
2239 int value;
2240 png_uint_32 i;
2241 png_uint_32 row_width = row_info->width;
2242
2243 dp = row;
2244 shift = 4;
2245 d = 0;
2246 for (i = png_pass_start[pass]; i < row_width;
2247 i += png_pass_inc[pass])
2248 {
2249 sp = row + (size_t)(i >> 1);
2250 value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
2251 d |= (value << shift);
2252
2253 if (shift == 0)
2254 {
2255 shift = 4;
2256 *dp++ = (png_byte)d;
2257 d = 0;
2258 }
2259
2260 else
2261 shift -= 4;
2262 }
2263 if (shift != 4)
2264 *dp = (png_byte)d;
2265
2266 break;
2267 }
2268
2269 default:
2270 {
2271 png_bytep sp;
2272 png_bytep dp;
2273 png_uint_32 i;
2274 png_uint_32 row_width = row_info->width;
2275 size_t pixel_bytes;
2276
2277 /* Start at the beginning */
2278 dp = row;
2279
2280 /* Find out how many bytes each pixel takes up */
2281 pixel_bytes = (row_info->pixel_depth >> 3);
2282
2283 /* Loop through the row, only looking at the pixels that matter */
2284 for (i = png_pass_start[pass]; i < row_width;
2285 i += png_pass_inc[pass])
2286 {
2287 /* Find out where the original pixel is */
2288 sp = row + (size_t)i * pixel_bytes;
2289
2290 /* Move the pixel */
2291 if (dp != sp)
2292 memcpy(dp, sp, pixel_bytes);
2293
2294 /* Next pixel */
2295 dp += pixel_bytes;
2296 }
2297 break;
2298 }
2299 }
2300 /* Set new row width */
2301 row_info->width = (row_info->width +
2302 png_pass_inc[pass] - 1 -
2303 png_pass_start[pass]) /
2304 png_pass_inc[pass];
2305
2306 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
2307 row_info->width);
2308 }
2309}
2310#endif
2311
2312
2313/* This filters the row, chooses which filter to use, if it has not already
2314 * been specified by the application, and then writes the row out with the
2315 * chosen filter.
2316 */
2317static void /* PRIVATE */
2318png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2319 size_t row_bytes);
2320
2321#ifdef PNG_WRITE_FILTER_SUPPORTED
2322static size_t /* PRIVATE */
2323png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
2324 size_t row_bytes, size_t lmins)
2325{
2326 png_bytep rp, dp, lp;
2327 size_t i;
2328 size_t sum = 0;
2329 unsigned int v;
2330
2331 png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
2332
2333 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
2334 i++, rp++, dp++)
2335 {
2336 v = *dp = *rp;
2337#ifdef PNG_USE_ABS
2338 sum += 128 - abs((int)v - 128);
2339#else
2340 sum += (v < 128) ? v : 256 - v;
2341#endif
2342 }
2343
2344 for (lp = png_ptr->row_buf + 1; i < row_bytes;
2345 i++, rp++, lp++, dp++)
2346 {
2347 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2348#ifdef PNG_USE_ABS
2349 sum += 128 - abs((int)v - 128);
2350#else
2351 sum += (v < 128) ? v : 256 - v;
2352#endif
2353
2354 if (sum > lmins) /* We are already worse, don't continue. */
2355 break;
2356 }
2357
2358 return sum;
2359}
2360
2361static void /* PRIVATE */
2362png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
2363 size_t row_bytes)
2364{
2365 png_bytep rp, dp, lp;
2366 size_t i;
2367
2368 png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
2369
2370 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
2371 i++, rp++, dp++)
2372 {
2373 *dp = *rp;
2374 }
2375
2376 for (lp = png_ptr->row_buf + 1; i < row_bytes;
2377 i++, rp++, lp++, dp++)
2378 {
2379 *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2380 }
2381}
2382
2383static size_t /* PRIVATE */
2384png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins)
2385{
2386 png_bytep rp, dp, pp;
2387 size_t i;
2388 size_t sum = 0;
2389 unsigned int v;
2390
2391 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
2392
2393 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2394 pp = png_ptr->prev_row + 1; i < row_bytes;
2395 i++, rp++, pp++, dp++)
2396 {
2397 v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2398#ifdef PNG_USE_ABS
2399 sum += 128 - abs((int)v - 128);
2400#else
2401 sum += (v < 128) ? v : 256 - v;
2402#endif
2403
2404 if (sum > lmins) /* We are already worse, don't continue. */
2405 break;
2406 }
2407
2408 return sum;
2409}
2410static void /* PRIVATE */
2411png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes)
2412{
2413 png_bytep rp, dp, pp;
2414 size_t i;
2415
2416 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
2417
2418 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2419 pp = png_ptr->prev_row + 1; i < row_bytes;
2420 i++, rp++, pp++, dp++)
2421 {
2422 *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2423 }
2424}
2425
2426static size_t /* PRIVATE */
2427png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
2428 size_t row_bytes, size_t lmins)
2429{
2430 png_bytep rp, dp, pp, lp;
2431 png_uint_32 i;
2432 size_t sum = 0;
2433 unsigned int v;
2434
2435 png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
2436
2437 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2438 pp = png_ptr->prev_row + 1; i < bpp; i++)
2439 {
2440 v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2441
2442#ifdef PNG_USE_ABS
2443 sum += 128 - abs((int)v - 128);
2444#else
2445 sum += (v < 128) ? v : 256 - v;
2446#endif
2447 }
2448
2449 for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
2450 {
2451 v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
2452 & 0xff);
2453
2454#ifdef PNG_USE_ABS
2455 sum += 128 - abs((int)v - 128);
2456#else
2457 sum += (v < 128) ? v : 256 - v;
2458#endif
2459
2460 if (sum > lmins) /* We are already worse, don't continue. */
2461 break;
2462 }
2463
2464 return sum;
2465}
2466static void /* PRIVATE */
2467png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
2468 size_t row_bytes)
2469{
2470 png_bytep rp, dp, pp, lp;
2471 png_uint_32 i;
2472
2473 png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
2474
2475 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2476 pp = png_ptr->prev_row + 1; i < bpp; i++)
2477 {
2478 *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2479 }
2480
2481 for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
2482 {
2483 *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
2484 & 0xff);
2485 }
2486}
2487
2488static size_t /* PRIVATE */
2489png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
2490 size_t row_bytes, size_t lmins)
2491{
2492 png_bytep rp, dp, pp, cp, lp;
2493 size_t i;
2494 size_t sum = 0;
2495 unsigned int v;
2496
2497 png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
2498
2499 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2500 pp = png_ptr->prev_row + 1; i < bpp; i++)
2501 {
2502 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2503
2504#ifdef PNG_USE_ABS
2505 sum += 128 - abs((int)v - 128);
2506#else
2507 sum += (v < 128) ? v : 256 - v;
2508#endif
2509 }
2510
2511 for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
2512 i++)
2513 {
2514 int a, b, c, pa, pb, pc, p;
2515
2516 b = *pp++;
2517 c = *cp++;
2518 a = *lp++;
2519
2520 p = b - c;
2521 pc = a - c;
2522
2523#ifdef PNG_USE_ABS
2524 pa = abs(p);
2525 pb = abs(pc);
2526 pc = abs(p + pc);
2527#else
2528 pa = p < 0 ? -p : p;
2529 pb = pc < 0 ? -pc : pc;
2530 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2531#endif
2532
2533 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2534
2535 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2536
2537#ifdef PNG_USE_ABS
2538 sum += 128 - abs((int)v - 128);
2539#else
2540 sum += (v < 128) ? v : 256 - v;
2541#endif
2542
2543 if (sum > lmins) /* We are already worse, don't continue. */
2544 break;
2545 }
2546
2547 return sum;
2548}
2549static void /* PRIVATE */
2550png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
2551 size_t row_bytes)
2552{
2553 png_bytep rp, dp, pp, cp, lp;
2554 size_t i;
2555
2556 png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
2557
2558 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
2559 pp = png_ptr->prev_row + 1; i < bpp; i++)
2560 {
2561 *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2562 }
2563
2564 for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
2565 i++)
2566 {
2567 int a, b, c, pa, pb, pc, p;
2568
2569 b = *pp++;
2570 c = *cp++;
2571 a = *lp++;
2572
2573 p = b - c;
2574 pc = a - c;
2575
2576#ifdef PNG_USE_ABS
2577 pa = abs(p);
2578 pb = abs(pc);
2579 pc = abs(p + pc);
2580#else
2581 pa = p < 0 ? -p : p;
2582 pb = pc < 0 ? -pc : pc;
2583 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2584#endif
2585
2586 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2587
2588 *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2589 }
2590}
2591#endif /* WRITE_FILTER */
2592
2593void /* PRIVATE */
2594png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
2595{
2596#ifndef PNG_WRITE_FILTER_SUPPORTED
2597 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
2598#else
2599 unsigned int filter_to_do = png_ptr->do_filter;
2600 png_bytep row_buf;
2601 png_bytep best_row;
2603 size_t mins;
2604 size_t row_bytes = row_info->rowbytes;
2605
2606 png_debug(1, "in png_write_find_filter");
2607
2608 /* Find out how many bytes offset each pixel is */
2609 bpp = (row_info->pixel_depth + 7) >> 3;
2610
2611 row_buf = png_ptr->row_buf;
2612 mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the
2613 running sum */;
2614
2615 /* The prediction method we use is to find which method provides the
2616 * smallest value when summing the absolute values of the distances
2617 * from zero, using anything >= 128 as negative numbers. This is known
2618 * as the "minimum sum of absolute differences" heuristic. Other
2619 * heuristics are the "weighted minimum sum of absolute differences"
2620 * (experimental and can in theory improve compression), and the "zlib
2621 * predictive" method (not implemented yet), which does test compressions
2622 * of lines using different filter methods, and then chooses the
2623 * (series of) filter(s) that give minimum compressed data size (VERY
2624 * computationally expensive).
2625 *
2626 * GRR 980525: consider also
2627 *
2628 * (1) minimum sum of absolute differences from running average (i.e.,
2629 * keep running sum of non-absolute differences & count of bytes)
2630 * [track dispersion, too? restart average if dispersion too large?]
2631 *
2632 * (1b) minimum sum of absolute differences from sliding average, probably
2633 * with window size <= deflate window (usually 32K)
2634 *
2635 * (2) minimum sum of squared differences from zero or running average
2636 * (i.e., ~ root-mean-square approach)
2637 */
2638
2639
2640 /* We don't need to test the 'no filter' case if this is the only filter
2641 * that has been chosen, as it doesn't actually do anything to the data.
2642 */
2643 best_row = png_ptr->row_buf;
2644
2645 if (PNG_SIZE_MAX/128 <= row_bytes)
2646 {
2647 /* Overflow can occur in the calculation, just select the lowest set
2648 * filter.
2649 */
2650 filter_to_do &= 0U-filter_to_do;
2651 }
2652 else if ((filter_to_do & PNG_FILTER_NONE) != 0 &&
2653 filter_to_do != PNG_FILTER_NONE)
2654 {
2655 /* Overflow not possible and multiple filters in the list, including the
2656 * 'none' filter.
2657 */
2658 png_bytep rp;
2659 size_t sum = 0;
2660 size_t i;
2661 unsigned int v;
2662
2663 {
2664 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
2665 {
2666 v = *rp;
2667#ifdef PNG_USE_ABS
2668 sum += 128 - abs((int)v - 128);
2669#else
2670 sum += (v < 128) ? v : 256 - v;
2671#endif
2672 }
2673 }
2674
2675 mins = sum;
2676 }
2677
2678 /* Sub filter */
2679 if (filter_to_do == PNG_FILTER_SUB)
2680 /* It's the only filter so no testing is needed */
2681 {
2682 png_setup_sub_row_only(png_ptr, bpp, row_bytes);
2683 best_row = png_ptr->try_row;
2684 }
2685
2686 else if ((filter_to_do & PNG_FILTER_SUB) != 0)
2687 {
2688 size_t sum;
2689 size_t lmins = mins;
2690
2691 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
2692
2693 if (sum < mins)
2694 {
2695 mins = sum;
2696 best_row = png_ptr->try_row;
2697 if (png_ptr->tst_row != NULL)
2698 {
2699 png_ptr->try_row = png_ptr->tst_row;
2700 png_ptr->tst_row = best_row;
2701 }
2702 }
2703 }
2704
2705 /* Up filter */
2706 if (filter_to_do == PNG_FILTER_UP)
2707 {
2708 png_setup_up_row_only(png_ptr, row_bytes);
2709 best_row = png_ptr->try_row;
2710 }
2711
2712 else if ((filter_to_do & PNG_FILTER_UP) != 0)
2713 {
2714 size_t sum;
2715 size_t lmins = mins;
2716
2717 sum = png_setup_up_row(png_ptr, row_bytes, lmins);
2718
2719 if (sum < mins)
2720 {
2721 mins = sum;
2722 best_row = png_ptr->try_row;
2723 if (png_ptr->tst_row != NULL)
2724 {
2725 png_ptr->try_row = png_ptr->tst_row;
2726 png_ptr->tst_row = best_row;
2727 }
2728 }
2729 }
2730
2731 /* Avg filter */
2732 if (filter_to_do == PNG_FILTER_AVG)
2733 {
2734 png_setup_avg_row_only(png_ptr, bpp, row_bytes);
2735 best_row = png_ptr->try_row;
2736 }
2737
2738 else if ((filter_to_do & PNG_FILTER_AVG) != 0)
2739 {
2740 size_t sum;
2741 size_t lmins = mins;
2742
2743 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
2744
2745 if (sum < mins)
2746 {
2747 mins = sum;
2748 best_row = png_ptr->try_row;
2749 if (png_ptr->tst_row != NULL)
2750 {
2751 png_ptr->try_row = png_ptr->tst_row;
2752 png_ptr->tst_row = best_row;
2753 }
2754 }
2755 }
2756
2757 /* Paeth filter */
2758 if (filter_to_do == PNG_FILTER_PAETH)
2759 {
2760 png_setup_paeth_row_only(png_ptr, bpp, row_bytes);
2761 best_row = png_ptr->try_row;
2762 }
2763
2764 else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
2765 {
2766 size_t sum;
2767 size_t lmins = mins;
2768
2769 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
2770
2771 if (sum < mins)
2772 {
2773 best_row = png_ptr->try_row;
2774 if (png_ptr->tst_row != NULL)
2775 {
2776 png_ptr->try_row = png_ptr->tst_row;
2777 png_ptr->tst_row = best_row;
2778 }
2779 }
2780 }
2781
2782 /* Do the actual writing of the filtered row data from the chosen filter. */
2783 png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
2784
2785#endif /* WRITE_FILTER */
2786}
2787
2788
2789/* Do the actual writing of a previously filtered row. */
2790static void
2791png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
2792 size_t full_row_length/*includes filter byte*/)
2793{
2794 png_debug(1, "in png_write_filtered_row");
2795
2796 png_debug1(2, "filter = %d", filtered_row[0]);
2797
2798 png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
2799
2800#ifdef PNG_WRITE_FILTER_SUPPORTED
2801 /* Swap the current and previous rows */
2802 if (png_ptr->prev_row != NULL)
2803 {
2804 png_bytep tptr;
2805
2806 tptr = png_ptr->prev_row;
2807 png_ptr->prev_row = png_ptr->row_buf;
2808 png_ptr->row_buf = tptr;
2809 }
2810#endif /* WRITE_FILTER */
2811
2812 /* Finish row - updates counters and flushes zlib if last row */
2813 png_write_finish_row(png_ptr);
2814
2815#ifdef PNG_WRITE_FLUSH_SUPPORTED
2816 png_ptr->flush_rows++;
2817
2818 if (png_ptr->flush_dist > 0 &&
2819 png_ptr->flush_rows >= png_ptr->flush_dist)
2820 {
2821 png_write_flush(png_ptr);
2822 }
2823#endif /* WRITE_FLUSH */
2824}
2825#endif /* WRITE */
static int avail
Definition: adh-main.c:39
#define msg(x)
Definition: auth_time.c:54
#define U(x)
Definition: wordpad.c:45
_In_ fcb _In_ chunk _In_ uint64_t _In_ uint64_t _In_ bool _In_opt_ void _In_opt_ PIRP _In_ LIST_ENTRY _In_ uint8_t compression
Definition: btrfs_drv.h:1365
Definition: list.h:37
struct list * next
Definition: list.h:38
int ZEXPORT deflateReset(z_streamp strm)
Definition: deflate.c:541
#define NULL
Definition: types.h:112
DWORD bpp
Definition: surface.c:185
static unsigned int palette_size(DWORD flags)
Definition: palette.c:241
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:137
#define Z_STREAM_END
Definition: zlib.h:115
#define Z_FINISH
Definition: zlib.h:109
unsigned int uInt
Definition: zlib.h:38
#define Z_OK
Definition: zlib.h:114
int deflate(z_streamp strm, int flush) DECLSPEC_HIDDEN
Definition: deflate.c:815
#define Z_STREAM_ERROR
Definition: zlib.h:118
#define Z_NO_FLUSH
Definition: zlib.h:105
int deflateEnd(z_streamp strm) DECLSPEC_HIDDEN
Definition: deflate.c:1130
#define Z_MEM_ERROR
Definition: zlib.h:120
const WCHAR * text
Definition: package.c:1794
unsigned int size_t
Definition: corecrt.h:203
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
static HCRYPTKEY new_key(HCRYPTPROV hProv, ALG_ID aiAlgid, DWORD dwFlags, CRYPTKEY **ppCryptKey)
Definition: rsaenh.c:794
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
method
Definition: dragdrop.c:54
return ret
Definition: mutex.c:146
#define abs(i)
Definition: fconv.c:206
GLint level
Definition: gl.h:1546
GLclampf green
Definition: gl.h:1740
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLclampf GLclampf blue
Definition: gl.h:1740
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizeiptr size
Definition: glext.h:5919
const GLubyte * c
Definition: glext.h:8905
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat units
Definition: glext.h:11727
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLenum GLenum GLenum input
Definition: glext.h:9031
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6102
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define d
Definition: ke_i.h:81
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define profile
Definition: kernel32.h:12
#define red
Definition: linetest.c:67
POINT cp
Definition: magnifier.c:59
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define PNG_COLOR_TYPE_RGB
Definition: image.c:5165
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition: image.c:5168
#define PNG_COLOR_TYPE_GRAY_ALPHA
Definition: image.c:5167
#define PNG_COLOR_TYPE_GRAY
Definition: image.c:5164
#define PNG_COLOR_TYPE_PALETTE
Definition: image.c:5166
static const WCHAR sp[]
Definition: suminfo.c:287
static LARGE_INTEGER * frequency
Definition: time.c:106
static int ** pa
Definition: server.c:145
static HPALETTE palette
Definition: clipboard.c:1457
#define shift
Definition: input.c:3271
#define PNG_UINT_31_MAX
Definition: png.h:644
#define PNG_FILTER_SUB
Definition: png.h:1528
#define PNG_FILTER_PAETH
Definition: png.h:1531
#define PNG_INTRAPIXEL_DIFFERENCING
Definition: png.h:678
png_const_structrp png_const_inforp int * unit
Definition: png.h:2392
#define PNG_HAVE_PLTE
Definition: png.h:640
#define PNG_IO_CHUNK_HDR
Definition: png.h:2664
#define PNG_MAX_PALETTE_LENGTH
Definition: png.h:720
#define PNG_FILTER_NONE
Definition: png.h:1527
png_structrp png_ptr
Definition: png.h:1122
#define PNG_ITXT_COMPRESSION_NONE
Definition: png.h:585
#define PNG_FILTER_AVG
Definition: png.h:1530
png_uint_32
Definition: png.h:2036
#define PNG_TEXT_COMPRESSION_zTXt
Definition: png.h:584
#define PNG_FLAG_MNG_FILTER_64
Definition: png.h:873
#define PNG_IO_SIGNATURE
Definition: png.h:2663
#define PNG_TEXT_COMPRESSION_NONE
Definition: png.h:583
#define PNG_sRGB_INTENT_LAST
Definition: png.h:714
#define PNG_EQUATION_LAST
Definition: png.h:696
#define PNG_FILTER_VALUE_AVG
Definition: png.h:1541
#define PNG_COLOR_MASK_COLOR
Definition: png.h:659
#define PNG_ALL_FILTERS
Definition: png.h:1533
#define PNG_PASS_ROWS(height, pass)
Definition: png.h:2704
#define PNG_FILTER_VALUE_UP
Definition: png.h:1540
#define PNG_IO_CHUNK_DATA
Definition: png.h:2665
#define PNG_FILTER_TYPE_BASE
Definition: png.h:677
#define png_get_uint_32(buf)
Definition: png.h:2842
#define PNG_AFTER_IDAT
Definition: png.h:641
#define PNG_COLOR_MASK_ALPHA
Definition: png.h:660
#define PNG_PASS_COLS(width, pass)
Definition: png.h:2706
#define PNG_HAVE_IHDR
Definition: png.h:639
#define PNG_INTERLACE_ADAM7
Definition: png.h:683
#define PNG_RESOLUTION_LAST
Definition: png.h:707
#define PNG_FLAG_MNG_EMPTY_PLTE
Definition: png.h:872
#define PNG_FILTER_UP
Definition: png.h:1529
#define PNG_SIZE_MAX
Definition: png.h:646
#define PNG_FILTER_VALUE_PAETH
Definition: png.h:1542
#define PNG_NO_FILTERS
Definition: png.h:1526
#define PNG_FILTER_VALUE_NONE
Definition: png.h:1538
#define PNG_IO_CHUNK_CRC
Definition: png.h:2666
#define PNG_OFFSET_LAST
Definition: png.h:689
#define PNG_INTERLACE_NONE
Definition: png.h:682
#define PNG_COMPRESSION_TYPE_BASE
Definition: png.h:673
#define PNG_FILTER_VALUE_SUB
Definition: png.h:1539
png_struct *PNG_RESTRICT png_structrp
Definition: png.h:464
#define PNG_IO_WRITING
Definition: png.h:2662
#define PNG_ITXT_COMPRESSION_zTXt
Definition: png.h:586
char * png_charp
Definition: pngconf.h:576
png_int_32 png_fixed_point
Definition: pngconf.h:561
const png_byte * png_const_bytep
Definition: pngconf.h:567
const png_uint_16 * png_const_uint_16p
Definition: pngconf.h:573
char ** png_charpp
Definition: pngconf.h:595
size_t png_alloc_size_t
Definition: pngconf.h:544
#define PNGAPI
Definition: pngconf.h:248
png_byte * png_bytep
Definition: pngconf.h:566
const char * png_const_charp
Definition: pngconf.h:577
#define png_debug2(l, m, p1, p2)
Definition: pngdebug.h:151
#define png_debug(l, m)
Definition: pngdebug.h:145
#define png_debug1(l, m, p1)
Definition: pngdebug.h:148
#define PNG_Z_DEFAULT_STRATEGY
Definition: pnglibconf.h:229
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY
Definition: pnglibconf.h:228
#define PNG_MNG_FEATURES_SUPPORTED
Definition: pnglibconf.h:49
#define PNG_POINTER_INDEXING_SUPPORTED
Definition: pnglibconf.h:50
#define png_sPLT
Definition: pngpriv.h:912
#define PNG_HAVE_PNG_SIGNATURE
Definition: pngpriv.h:652
#define png_sBIT
Definition: pngpriv.h:910
#define PNG_INTERLACE
Definition: pngpriv.h:659
#define png_hIST
Definition: pngpriv.h:903
#define PNG_ROWBYTES(pixel_bits, width)
Definition: pngpriv.h:754
#define png_cLLI
Definition: pngpriv.h:894
#define png_iCCP
Definition: pngpriv.h:904
#define png_app_warning(pp, s)
Definition: pngpriv.h:2037
#define png_IHDR
Definition: pngpriv.h:888
#define png_zTXt
Definition: pngpriv.h:918
#define png_cHRM
Definition: pngpriv.h:892
#define png_IEND
Definition: pngpriv.h:887
#define png_bKGD
Definition: pngpriv.h:891
#define PNG_HAVE_IDAT
Definition: pngpriv.h:642
#define PNG_CSTRING_FROM_CHUNK(s, c)
Definition: pngpriv.h:937
#define PNG_HAVE_IEND
Definition: pngpriv.h:644
#define png_tEXt
Definition: pngpriv.h:915
#define png_tIME
Definition: pngpriv.h:916
#define png_sRGB
Definition: pngpriv.h:913
#define png_eXIf
Definition: pngpriv.h:895
#define PNG_CHUNK_FROM_STRING(s)
Definition: pngpriv.h:923
#define png_gAMA
Definition: pngpriv.h:899
#define PNG_FLAG_ZSTREAM_INITIALIZED
Definition: pngpriv.h:696
#define png_oFFs
Definition: pngpriv.h:907
#define png_sCAL
Definition: pngpriv.h:911
#define png_mDCV
Definition: pngpriv.h:906
#define png_cICP
Definition: pngpriv.h:893
#define png_pCAL
Definition: pngpriv.h:908
#define png_pHYs
Definition: pngpriv.h:909
#define png_voidcast(type, value)
Definition: pngpriv.h:535
#define png_tRNS
Definition: pngpriv.h:917
#define png_PLTE
Definition: pngpriv.h:889
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY
Definition: pngpriv.h:695
#define png_iTXt
Definition: pngpriv.h:905
#define PNG_STRING_FROM_CHUNK(s, c)
Definition: pngpriv.h:930
#define png_IDAT
Definition: pngpriv.h:886
#define PNGZ_MSG_CAST(s)
Definition: pngstruct.h:37
#define PNGZ_INPUT_CAST(b)
Definition: pngstruct.h:38
#define ZLIB_IO_MAX
Definition: pngstruct.h:53
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
static unsigned __int64 next
Definition: rand_nt.c:6
static calc_node_t temp
Definition: rpn_ieee.c:38
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1814
int windowBits
Definition: zlib.h:813
#define memset(x, y, z)
Definition: compat.h:39
Definition: copy.c:22
Definition: name.c:39
png_uint_16 red
Definition: png.h:486
png_byte index
Definition: png.h:485
png_uint_16 gray
Definition: png.h:489
png_uint_16 green
Definition: png.h:487
png_uint_16 blue
Definition: png.h:488
png_byte green
Definition: png.h:498
png_byte gray
Definition: png.h:500
png_byte blue
Definition: png.h:499
png_byte red
Definition: png.h:497
png_byte alpha
Definition: png.h:501
png_byte blue
Definition: png.h:477
png_byte red
Definition: png.h:475
png_byte green
Definition: png.h:476
png_uint_32 width
Definition: png.h:766
png_byte pixel_depth
Definition: png.h:771
size_t rowbytes
Definition: png.h:767
Definition: png.h:512
png_sPLT_entryp entries
Definition: png.h:532
png_byte depth
Definition: png.h:531
png_int_32 nentries
Definition: png.h:533
png_charp name
Definition: png.h:530
png_byte month
Definition: png.h:598
png_uint_16 year
Definition: png.h:597
png_byte hour
Definition: png.h:600
png_byte second
Definition: png.h:602
png_byte minute
Definition: png.h:601
png_byte day
Definition: png.h:599
png_fixed_point bluey
Definition: pngstruct.h:78
png_fixed_point redx
Definition: pngstruct.h:76
png_fixed_point redy
Definition: pngstruct.h:76
png_fixed_point whitey
Definition: pngstruct.h:79
png_fixed_point bluex
Definition: pngstruct.h:78
png_fixed_point greenx
Definition: pngstruct.h:77
png_fixed_point greeny
Definition: pngstruct.h:77
png_fixed_point whitex
Definition: pngstruct.h:79
pass
Definition: typegen.h:25
Definition: pdh_main.c:96
static const WCHAR lang[]
Definition: wbemdisp.c:287