w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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