pngwutil.c
Go to the documentation of this file.
1 
2 /* pngwutil.c - utilities to write a PNG file
3  *
4  * Last changed in libpng 1.2.30 [August 15, 2008]
5  * For conditions of distribution and use, see copyright notice in png.h
6  * Copyright (c) 1998-2008 Glenn Randers-Pehrson
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9  */
10 
11 #define PNG_INTERNAL
12 #include "png.h"
13 #ifdef PNG_WRITE_SUPPORTED
14 
15 /* Place a 32-bit number into a buffer in PNG byte order. We work
16  * with unsigned numbers for convenience, although one supported
17  * ancillary chunk uses signed (two's complement) numbers.
18  */
19 void PNGAPI
21 {
22  buf[0] = (png_byte)((i >> 24) & 0xff);
23  buf[1] = (png_byte)((i >> 16) & 0xff);
24  buf[2] = (png_byte)((i >> 8) & 0xff);
25  buf[3] = (png_byte)(i & 0xff);
26 }
27 
28 /* The png_save_int_32 function assumes integers are stored in two's
29  * complement format. If this isn't the case, then this routine needs to
30  * be modified to write data in two's complement format.
31  */
32 void PNGAPI
34 {
35  buf[0] = (png_byte)((i >> 24) & 0xff);
36  buf[1] = (png_byte)((i >> 16) & 0xff);
37  buf[2] = (png_byte)((i >> 8) & 0xff);
38  buf[3] = (png_byte)(i & 0xff);
39 }
40 
41 /* Place a 16-bit number into a buffer in PNG byte order.
42  * The parameter is declared unsigned int, not png_uint_16,
43  * just to avoid potential problems on pre-ANSI C compilers.
44  */
45 void PNGAPI
47 {
48  buf[0] = (png_byte)((i >> 8) & 0xff);
49  buf[1] = (png_byte)(i & 0xff);
50 }
51 
52 /* Simple function to write the signature. If we have already written
53  * the magic bytes of the signature, or more likely, the PNG stream is
54  * being embedded into another stream and doesn't need its own signature,
55  * we should call png_set_sig_bytes() to tell libpng how many of the
56  * bytes have already been written.
57  */
58 void /* PRIVATE */
60 {
61  png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
62 
63  /* write the rest of the 8 byte signature */
64  png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
65  (png_size_t)(8 - png_ptr->sig_bytes));
66  if (png_ptr->sig_bytes < 3)
67  png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
68 }
69 
70 /* Write a PNG chunk all at once. The type is an array of ASCII characters
71  * representing the chunk name. The array must be at least 4 bytes in
72  * length, and does not need to be null terminated. To be safe, pass the
73  * pre-defined chunk names here, and if you need a new one, define it
74  * where the others are defined. The length is the length of the data.
75  * All the data must be present. If that is not possible, use the
76  * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
77  * functions instead.
78  */
79 void PNGAPI
82 {
83  if (png_ptr == NULL) return;
84  png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
85  png_write_chunk_data(png_ptr, data, (png_size_t)length);
86  png_write_chunk_end(png_ptr);
87 }
88 
89 /* Write the start of a PNG chunk. The type is the chunk type.
90  * The total_length is the sum of the lengths of all the data you will be
91  * passing in png_write_chunk_data().
92  */
93 void PNGAPI
96 {
97  png_byte buf[8];
98 
99  png_debug2(0, "Writing %s chunk, length = %lu\n", chunk_name,
100  (unsigned long)length);
101  if (png_ptr == NULL) return;
102 
103  /* write the length and the chunk name */
104  png_save_uint_32(buf, length);
105  png_memcpy(buf + 4, chunk_name, 4);
106  png_write_data(png_ptr, buf, (png_size_t)8);
107  /* put the chunk name into png_ptr->chunk_name */
108  png_memcpy(png_ptr->chunk_name, chunk_name, 4);
109  /* reset the crc and run it over the chunk name */
110  png_reset_crc(png_ptr);
111  png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
112 }
113 
114 /* Write the data of a PNG chunk started with png_write_chunk_start().
115  * Note that multiple calls to this function are allowed, and that the
116  * sum of the lengths from these calls *must* add up to the total_length
117  * given to png_write_chunk_start().
118  */
119 void PNGAPI
121 {
122  /* write the data, and run the CRC over it */
123  if (png_ptr == NULL) return;
124  if (data != NULL && length > 0)
125  {
126  png_write_data(png_ptr, data, length);
127  /* update the CRC after writing the data,
128  * in case that the user I/O routine alters it.
129  */
130  png_calculate_crc(png_ptr, data, length);
131  }
132 }
133 
134 /* Finish a chunk started with png_write_chunk_start(). */
135 void PNGAPI
137 {
138  png_byte buf[4];
139 
140  if (png_ptr == NULL) return;
141 
142  /* write the crc in a single operation */
143  png_save_uint_32(buf, png_ptr->crc);
144 
145  png_write_data(png_ptr, buf, (png_size_t)4);
146 }
147 
148 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
149 /*
150  * This pair of functions encapsulates the operation of (a) compressing a
151  * text string, and (b) issuing it later as a series of chunk data writes.
152  * The compression_state structure is shared context for these functions
153  * set up by the caller in order to make the whole mess thread-safe.
154  */
155 
156 typedef struct
157 {
158  char *input; /* the uncompressed input data */
159  int input_len; /* its length */
160  int num_output_ptr; /* number of output pointers used */
161  int max_output_ptr; /* size of output_ptr */
162  png_charpp output_ptr; /* array of pointers to output */
164 
165 /* compress given text into storage in the png_ptr structure */
166 static int /* PRIVATE */
168  png_charp text, png_size_t text_len, int compression,
169  compression_state *comp)
170 {
171  int ret;
172 
173  comp->num_output_ptr = 0;
174  comp->max_output_ptr = 0;
175  comp->output_ptr = NULL;
176  comp->input = NULL;
177  comp->input_len = 0;
178 
179  /* we may just want to pass the text right through */
180  if (compression == PNG_TEXT_COMPRESSION_NONE)
181  {
182  comp->input = text;
183  comp->input_len = text_len;
184  return((int)text_len);
185  }
186 
187  if (compression >= PNG_TEXT_COMPRESSION_LAST)
188  {
189 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
190  char msg[50];
191  png_snprintf(msg, 50, "Unknown compression type %d", compression);
192  png_warning(png_ptr, msg);
193 #else
194  png_warning(png_ptr, "Unknown compression type");
195 #endif
196  }
197 
198  /* We can't write the chunk until we find out how much data we have,
199  * which means we need to run the compressor first and save the
200  * output. This shouldn't be a problem, as the vast majority of
201  * comments should be reasonable, but we will set up an array of
202  * malloc'd pointers to be sure.
203  *
204  * If we knew the application was well behaved, we could simplify this
205  * greatly by assuming we can always malloc an output buffer large
206  * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
207  * and malloc this directly. The only time this would be a bad idea is
208  * if we can't malloc more than 64K and we have 64K of random input
209  * data, or if the input string is incredibly large (although this
210  * wouldn't cause a failure, just a slowdown due to swapping).
211  */
212 
213  /* set up the compression buffers */
214  png_ptr->zstream.avail_in = (uInt)text_len;
215  png_ptr->zstream.next_in = (Bytef *)text;
216  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
217  png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
218 
219  /* this is the same compression loop as in png_write_row() */
220  do
221  {
222  /* compress the data */
223  ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
224  if (ret != Z_OK)
225  {
226  /* error */
227  if (png_ptr->zstream.msg != NULL)
228  png_error(png_ptr, png_ptr->zstream.msg);
229  else
230  png_error(png_ptr, "zlib error");
231  }
232  /* check to see if we need more room */
233  if (!(png_ptr->zstream.avail_out))
234  {
235  /* make sure the output array has room */
236  if (comp->num_output_ptr >= comp->max_output_ptr)
237  {
238  int old_max;
239 
240  old_max = comp->max_output_ptr;
241  comp->max_output_ptr = comp->num_output_ptr + 4;
242  if (comp->output_ptr != NULL)
243  {
244  png_charpp old_ptr;
245 
246  old_ptr = comp->output_ptr;
247  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
248  (png_uint_32)
250  png_memcpy(comp->output_ptr, old_ptr, old_max
251  * png_sizeof(png_charp));
252  png_free(png_ptr, old_ptr);
253  }
254  else
255  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
256  (png_uint_32)
257  (comp->max_output_ptr * png_sizeof(png_charp)));
258  }
259 
260  /* save the data */
261  comp->output_ptr[comp->num_output_ptr] =
262  (png_charp)png_malloc(png_ptr,
263  (png_uint_32)png_ptr->zbuf_size);
264  png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
265  png_ptr->zbuf_size);
266  comp->num_output_ptr++;
267 
268  /* and reset the buffer */
269  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
270  png_ptr->zstream.next_out = png_ptr->zbuf;
271  }
272  /* continue until we don't have any more to compress */
273  } while (png_ptr->zstream.avail_in);
274 
275  /* finish the compression */
276  do
277  {
278  /* tell zlib we are finished */
279  ret = deflate(&png_ptr->zstream, Z_FINISH);
280 
281  if (ret == Z_OK)
282  {
283  /* check to see if we need more room */
284  if (!(png_ptr->zstream.avail_out))
285  {
286  /* check to make sure our output array has room */
287  if (comp->num_output_ptr >= comp->max_output_ptr)
288  {
289  int old_max;
290 
291  old_max = comp->max_output_ptr;
292  comp->max_output_ptr = comp->num_output_ptr + 4;
293  if (comp->output_ptr != NULL)
294  {
295  png_charpp old_ptr;
296 
297  old_ptr = comp->output_ptr;
298  /* This could be optimized to realloc() */
299  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
300  (png_uint_32)(comp->max_output_ptr *
302  png_memcpy(comp->output_ptr, old_ptr,
303  old_max * png_sizeof(png_charp));
304  png_free(png_ptr, old_ptr);
305  }
306  else
307  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
308  (png_uint_32)(comp->max_output_ptr *
310  }
311 
312  /* save off the data */
313  comp->output_ptr[comp->num_output_ptr] =
314  (png_charp)png_malloc(png_ptr,
315  (png_uint_32)png_ptr->zbuf_size);
316  png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
317  png_ptr->zbuf_size);
318  comp->num_output_ptr++;
319 
320  /* and reset the buffer pointers */
321  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
322  png_ptr->zstream.next_out = png_ptr->zbuf;
323  }
324  }
325  else if (ret != Z_STREAM_END)
326  {
327  /* we got an error */
328  if (png_ptr->zstream.msg != NULL)
329  png_error(png_ptr, png_ptr->zstream.msg);
330  else
331  png_error(png_ptr, "zlib error");
332  }
333  } while (ret != Z_STREAM_END);
334 
335  /* text length is number of buffers plus last buffer */
336  text_len = png_ptr->zbuf_size * comp->num_output_ptr;
337  if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
338  text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
339 
340  return((int)text_len);
341 }
342 
343 /* ship the compressed text out via chunk writes */
344 static void /* PRIVATE */
346 {
347  int i;
348 
349  /* handle the no-compression case */
350  if (comp->input)
351  {
352  png_write_chunk_data(png_ptr, (png_bytep)comp->input,
353  (png_size_t)comp->input_len);
354  return;
355  }
356 
357  /* write saved output buffers, if any */
358  for (i = 0; i < comp->num_output_ptr; i++)
359  {
360  png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i],
361  (png_size_t)png_ptr->zbuf_size);
362  png_free(png_ptr, comp->output_ptr[i]);
363  comp->output_ptr[i]=NULL;
364  }
365  if (comp->max_output_ptr != 0)
366  png_free(png_ptr, comp->output_ptr);
367  comp->output_ptr=NULL;
368  /* write anything left in zbuf */
369  if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
370  png_write_chunk_data(png_ptr, png_ptr->zbuf,
371  (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
372 
373  /* reset zlib for another zTXt/iTXt or image data */
374  deflateReset(&png_ptr->zstream);
375  png_ptr->zstream.data_type = Z_BINARY;
376 }
377 #endif
378 
379 /* Write the IHDR chunk, and update the png_struct with the necessary
380  * information. Note that the rest of this code depends upon this
381  * information being correct.
382  */
383 void /* PRIVATE */
385  int bit_depth, int color_type, int compression_type, int filter_type,
386  int interlace_type)
387 {
388 #ifdef PNG_USE_LOCAL_ARRAYS
389  PNG_IHDR;
390 #endif
391  int ret;
392 
393  png_byte buf[13]; /* buffer to store the IHDR info */
394 
395  png_debug(1, "in png_write_IHDR\n");
396  /* Check that we have valid input data from the application info */
397  switch (color_type)
398  {
399  case PNG_COLOR_TYPE_GRAY:
400  switch (bit_depth)
401  {
402  case 1:
403  case 2:
404  case 4:
405  case 8:
406  case 16: png_ptr->channels = 1; break;
407  default: png_error(png_ptr, "Invalid bit depth for grayscale image");
408  }
409  break;
410  case PNG_COLOR_TYPE_RGB:
411  if (bit_depth != 8 && bit_depth != 16)
412  png_error(png_ptr, "Invalid bit depth for RGB image");
413  png_ptr->channels = 3;
414  break;
416  switch (bit_depth)
417  {
418  case 1:
419  case 2:
420  case 4:
421  case 8: png_ptr->channels = 1; break;
422  default: png_error(png_ptr, "Invalid bit depth for paletted image");
423  }
424  break;
426  if (bit_depth != 8 && bit_depth != 16)
427  png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
428  png_ptr->channels = 2;
429  break;
431  if (bit_depth != 8 && bit_depth != 16)
432  png_error(png_ptr, "Invalid bit depth for RGBA image");
433  png_ptr->channels = 4;
434  break;
435  default:
436  png_error(png_ptr, "Invalid image color type specified");
437  }
438 
439  if (compression_type != PNG_COMPRESSION_TYPE_BASE)
440  {
441  png_warning(png_ptr, "Invalid compression type specified");
442  compression_type = PNG_COMPRESSION_TYPE_BASE;
443  }
444 
445  /* Write filter_method 64 (intrapixel differencing) only if
446  * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
447  * 2. Libpng did not write a PNG signature (this filter_method is only
448  * used in PNG datastreams that are embedded in MNG datastreams) and
449  * 3. The application called png_permit_mng_features with a mask that
450  * included PNG_FLAG_MNG_FILTER_64 and
451  * 4. The filter_method is 64 and
452  * 5. The color_type is RGB or RGBA
453  */
454  if (
455 #if defined(PNG_MNG_FEATURES_SUPPORTED)
456  !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
457  ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
458  (color_type == PNG_COLOR_TYPE_RGB ||
459  color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
460  (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
461 #endif
462  filter_type != PNG_FILTER_TYPE_BASE)
463  {
464  png_warning(png_ptr, "Invalid filter type specified");
465  filter_type = PNG_FILTER_TYPE_BASE;
466  }
467 
468 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
469  if (interlace_type != PNG_INTERLACE_NONE &&
470  interlace_type != PNG_INTERLACE_ADAM7)
471  {
472  png_warning(png_ptr, "Invalid interlace type specified");
473  interlace_type = PNG_INTERLACE_ADAM7;
474  }
475 #else
476  interlace_type=PNG_INTERLACE_NONE;
477 #endif
478 
479  /* save off the relevent information */
480  png_ptr->bit_depth = (png_byte)bit_depth;
481  png_ptr->color_type = (png_byte)color_type;
482  png_ptr->interlaced = (png_byte)interlace_type;
483 #if defined(PNG_MNG_FEATURES_SUPPORTED)
484  png_ptr->filter_type = (png_byte)filter_type;
485 #endif
486  png_ptr->compression_type = (png_byte)compression_type;
487  png_ptr->width = width;
488  png_ptr->height = height;
489 
490  png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
491  png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
492  /* set the usr info, so any transformations can modify it */
493  png_ptr->usr_width = png_ptr->width;
494  png_ptr->usr_bit_depth = png_ptr->bit_depth;
495  png_ptr->usr_channels = png_ptr->channels;
496 
497  /* pack the header information into the buffer */
498  png_save_uint_32(buf, width);
499  png_save_uint_32(buf + 4, height);
500  buf[8] = (png_byte)bit_depth;
501  buf[9] = (png_byte)color_type;
502  buf[10] = (png_byte)compression_type;
503  buf[11] = (png_byte)filter_type;
504  buf[12] = (png_byte)interlace_type;
505 
506  /* write the chunk */
507  png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
508 
509  /* initialize zlib with PNG info */
510  png_ptr->zstream.zalloc = png_zalloc;
511  png_ptr->zstream.zfree = png_zfree;
512  png_ptr->zstream.opaque = (voidpf)png_ptr;
513  if (!(png_ptr->do_filter))
514  {
515  if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
516  png_ptr->bit_depth < 8)
517  png_ptr->do_filter = PNG_FILTER_NONE;
518  else
519  png_ptr->do_filter = PNG_ALL_FILTERS;
520  }
521  if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
522  {
523  if (png_ptr->do_filter != PNG_FILTER_NONE)
524  png_ptr->zlib_strategy = Z_FILTERED;
525  else
526  png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
527  }
528  if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
529  png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
530  if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
531  png_ptr->zlib_mem_level = 8;
532  if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
533  png_ptr->zlib_window_bits = 15;
534  if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
535  png_ptr->zlib_method = 8;
536  ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
537  png_ptr->zlib_method, png_ptr->zlib_window_bits,
538  png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
539  if (ret != Z_OK)
540  {
541  if (ret == Z_VERSION_ERROR) png_error(png_ptr,
542  "zlib failed to initialize compressor -- version error");
543  if (ret == Z_STREAM_ERROR) png_error(png_ptr,
544  "zlib failed to initialize compressor -- stream error");
545  if (ret == Z_MEM_ERROR) png_error(png_ptr,
546  "zlib failed to initialize compressor -- mem error");
547  png_error(png_ptr, "zlib failed to initialize compressor");
548  }
549  png_ptr->zstream.next_out = png_ptr->zbuf;
550  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
551  /* libpng is not interested in zstream.data_type */
552  /* set it to a predefined value, to avoid its evaluation inside zlib */
553  png_ptr->zstream.data_type = Z_BINARY;
554 
555  png_ptr->mode = PNG_HAVE_IHDR;
556 }
557 
558 /* write the palette. We are careful not to trust png_color to be in the
559  * correct order for PNG, so people can redefine it to any convenient
560  * structure.
561  */
562 void /* PRIVATE */
564 {
565 #ifdef PNG_USE_LOCAL_ARRAYS
566  PNG_PLTE;
567 #endif
568  png_uint_32 i;
569  png_colorp pal_ptr;
570  png_byte buf[3];
571 
572  png_debug(1, "in png_write_PLTE\n");
573  if ((
574 #if defined(PNG_MNG_FEATURES_SUPPORTED)
575  !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
576 #endif
577  num_pal == 0) || num_pal > 256)
578  {
579  if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
580  {
581  png_error(png_ptr, "Invalid number of colors in palette");
582  }
583  else
584  {
585  png_warning(png_ptr, "Invalid number of colors in palette");
586  return;
587  }
588  }
589 
590  if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
591  {
592  png_warning(png_ptr,
593  "Ignoring request to write a PLTE chunk in grayscale PNG");
594  return;
595  }
596 
597  png_ptr->num_palette = (png_uint_16)num_pal;
598  png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
599 
600  png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
601  (png_uint_32)(num_pal * 3));
602 #ifndef PNG_NO_POINTER_INDEXING
603  for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
604  {
605  buf[0] = pal_ptr->red;
606  buf[1] = pal_ptr->green;
607  buf[2] = pal_ptr->blue;
608  png_write_chunk_data(png_ptr, buf, (png_size_t)3);
609  }
610 #else
611  /* This is a little slower but some buggy compilers need to do this instead */
612  pal_ptr=palette;
613  for (i = 0; i < num_pal; i++)
614  {
615  buf[0] = pal_ptr[i].red;
616  buf[1] = pal_ptr[i].green;
617  buf[2] = pal_ptr[i].blue;
618  png_write_chunk_data(png_ptr, buf, (png_size_t)3);
619  }
620 #endif
621  png_write_chunk_end(png_ptr);
622  png_ptr->mode |= PNG_HAVE_PLTE;
623 }
624 
625 /* write an IDAT chunk */
626 void /* PRIVATE */
628 {
629 #ifdef PNG_USE_LOCAL_ARRAYS
630  PNG_IDAT;
631 #endif
632  png_debug(1, "in png_write_IDAT\n");
633 
634  /* Optimize the CMF field in the zlib stream. */
635  /* This hack of the zlib stream is compliant to the stream specification. */
636  if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
637  png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
638  {
639  unsigned int z_cmf = data[0]; /* zlib compression method and flags */
640  if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
641  {
642  /* Avoid memory underflows and multiplication overflows. */
643  /* The conditions below are practically always satisfied;
644  however, they still must be checked. */
645  if (length >= 2 &&
646  png_ptr->height < 16384 && png_ptr->width < 16384)
647  {
648  png_uint_32 uncompressed_idat_size = png_ptr->height *
649  ((png_ptr->width *
650  png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
651  unsigned int z_cinfo = z_cmf >> 4;
652  unsigned int half_z_window_size = 1 << (z_cinfo + 7);
653  while (uncompressed_idat_size <= half_z_window_size &&
654  half_z_window_size >= 256)
655  {
656  z_cinfo--;
657  half_z_window_size >>= 1;
658  }
659  z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
660  if (data[0] != (png_byte)z_cmf)
661  {
662  data[0] = (png_byte)z_cmf;
663  data[1] &= 0xe0;
664  data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f);
665  }
666  }
667  }
668  else
669  png_error(png_ptr,
670  "Invalid zlib compression method or flags in IDAT");
671  }
672 
673  png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
674  png_ptr->mode |= PNG_HAVE_IDAT;
675 }
676 
677 /* write an IEND chunk */
678 void /* PRIVATE */
680 {
681 #ifdef PNG_USE_LOCAL_ARRAYS
682  PNG_IEND;
683 #endif
684  png_debug(1, "in png_write_IEND\n");
685  png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL,
686  (png_size_t)0);
687  png_ptr->mode |= PNG_HAVE_IEND;
688 }
689 
690 #if defined(PNG_WRITE_gAMA_SUPPORTED)
691 /* write a gAMA chunk */
692 #ifdef PNG_FLOATING_POINT_SUPPORTED
693 void /* PRIVATE */
695 {
696 #ifdef PNG_USE_LOCAL_ARRAYS
697  PNG_gAMA;
698 #endif
699  png_uint_32 igamma;
700  png_byte buf[4];
701 
702  png_debug(1, "in png_write_gAMA\n");
703  /* file_gamma is saved in 1/100,000ths */
704  igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
705  png_save_uint_32(buf, igamma);
706  png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
707 }
708 #endif
709 #ifdef PNG_FIXED_POINT_SUPPORTED
710 void /* PRIVATE */
712 {
713 #ifdef PNG_USE_LOCAL_ARRAYS
714  PNG_gAMA;
715 #endif
716  png_byte buf[4];
717 
718  png_debug(1, "in png_write_gAMA\n");
719  /* file_gamma is saved in 1/100,000ths */
720  png_save_uint_32(buf, (png_uint_32)file_gamma);
721  png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
722 }
723 #endif
724 #endif
725 
726 #if defined(PNG_WRITE_sRGB_SUPPORTED)
727 /* write a sRGB chunk */
728 void /* PRIVATE */
729 png_write_sRGB(png_structp png_ptr, int srgb_intent)
730 {
731 #ifdef PNG_USE_LOCAL_ARRAYS
732  PNG_sRGB;
733 #endif
734  png_byte buf[1];
735 
736  png_debug(1, "in png_write_sRGB\n");
737  if (srgb_intent >= PNG_sRGB_INTENT_LAST)
738  png_warning(png_ptr,
739  "Invalid sRGB rendering intent specified");
740  buf[0]=(png_byte)srgb_intent;
741  png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
742 }
743 #endif
744 
745 #if defined(PNG_WRITE_iCCP_SUPPORTED)
746 /* write an iCCP chunk */
747 void /* PRIVATE */
749  png_charp profile, int profile_len)
750 {
751 #ifdef PNG_USE_LOCAL_ARRAYS
752  PNG_iCCP;
753 #endif
754  png_size_t name_len;
755  png_charp new_name;
756  compression_state comp;
757  int embedded_profile_len = 0;
758 
759  png_debug(1, "in png_write_iCCP\n");
760 
761  comp.num_output_ptr = 0;
762  comp.max_output_ptr = 0;
763  comp.output_ptr = NULL;
764  comp.input = NULL;
765  comp.input_len = 0;
766 
767  if (name == NULL || (name_len = png_check_keyword(png_ptr, name,
768  &new_name)) == 0)
769  {
770  png_warning(png_ptr, "Empty keyword in iCCP chunk");
771  return;
772  }
773 
774  if (compression_type != PNG_COMPRESSION_TYPE_BASE)
775  png_warning(png_ptr, "Unknown compression type in iCCP chunk");
776 
777  if (profile == NULL)
778  profile_len = 0;
779 
780  if (profile_len > 3)
781  embedded_profile_len =
782  ((*( (png_bytep)profile ))<<24) |
783  ((*( (png_bytep)profile + 1))<<16) |
784  ((*( (png_bytep)profile + 2))<< 8) |
785  ((*( (png_bytep)profile + 3)) );
786 
787  if (profile_len < embedded_profile_len)
788  {
789  png_warning(png_ptr,
790  "Embedded profile length too large in iCCP chunk");
791  return;
792  }
793 
794  if (profile_len > embedded_profile_len)
795  {
796  png_warning(png_ptr,
797  "Truncating profile to actual length in iCCP chunk");
798  profile_len = embedded_profile_len;
799  }
800 
801  if (profile_len)
802  profile_len = png_text_compress(png_ptr, profile,
803  (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
804 
805  /* make sure we include the NULL after the name and the compression type */
806  png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
807  (png_uint_32)(name_len + profile_len + 2));
808  new_name[name_len + 1] = 0x00;
809  png_write_chunk_data(png_ptr, (png_bytep)new_name,
810  (png_size_t)(name_len + 2));
811 
812  if (profile_len)
813  png_write_compressed_data_out(png_ptr, &comp);
814 
815  png_write_chunk_end(png_ptr);
816  png_free(png_ptr, new_name);
817 }
818 #endif
819 
820 #if defined(PNG_WRITE_sPLT_SUPPORTED)
821 /* write a sPLT chunk */
822 void /* PRIVATE */
824 {
825 #ifdef PNG_USE_LOCAL_ARRAYS
826  PNG_sPLT;
827 #endif
828  png_size_t name_len;
829  png_charp new_name;
830  png_byte entrybuf[10];
831  int entry_size = (spalette->depth == 8 ? 6 : 10);
832  int palette_size = entry_size * spalette->nentries;
833  png_sPLT_entryp ep;
834 #ifdef PNG_NO_POINTER_INDEXING
835  int i;
836 #endif
837 
838  png_debug(1, "in png_write_sPLT\n");
839  if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr,
840  spalette->name, &new_name))==0)
841  {
842  png_warning(png_ptr, "Empty keyword in sPLT chunk");
843  return;
844  }
845 
846  /* make sure we include the NULL after the name */
847  png_write_chunk_start(png_ptr, (png_bytep)png_sPLT,
848  (png_uint_32)(name_len + 2 + palette_size));
849  png_write_chunk_data(png_ptr, (png_bytep)new_name,
850  (png_size_t)(name_len + 1));
851  png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
852 
853  /* loop through each palette entry, writing appropriately */
854 #ifndef PNG_NO_POINTER_INDEXING
855  for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
856  {
857  if (spalette->depth == 8)
858  {
859  entrybuf[0] = (png_byte)ep->red;
860  entrybuf[1] = (png_byte)ep->green;
861  entrybuf[2] = (png_byte)ep->blue;
862  entrybuf[3] = (png_byte)ep->alpha;
863  png_save_uint_16(entrybuf + 4, ep->frequency);
864  }
865  else
866  {
867  png_save_uint_16(entrybuf + 0, ep->red);
868  png_save_uint_16(entrybuf + 2, ep->green);
869  png_save_uint_16(entrybuf + 4, ep->blue);
870  png_save_uint_16(entrybuf + 6, ep->alpha);
871  png_save_uint_16(entrybuf + 8, ep->frequency);
872  }
873  png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
874  }
875 #else
876  ep=spalette->entries;
877  for (i=0; i>spalette->nentries; i++)
878  {
879  if (spalette->depth == 8)
880  {
881  entrybuf[0] = (png_byte)ep[i].red;
882  entrybuf[1] = (png_byte)ep[i].green;
883  entrybuf[2] = (png_byte)ep[i].blue;
884  entrybuf[3] = (png_byte)ep[i].alpha;
885  png_save_uint_16(entrybuf + 4, ep[i].frequency);
886  }
887  else
888  {
889  png_save_uint_16(entrybuf + 0, ep[i].red);
890  png_save_uint_16(entrybuf + 2, ep[i].green);
891  png_save_uint_16(entrybuf + 4, ep[i].blue);
892  png_save_uint_16(entrybuf + 6, ep[i].alpha);
893  png_save_uint_16(entrybuf + 8, ep[i].frequency);
894  }
895  png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
896  }
897 #endif
898 
899  png_write_chunk_end(png_ptr);
900  png_free(png_ptr, new_name);
901 }
902 #endif
903 
904 #if defined(PNG_WRITE_sBIT_SUPPORTED)
905 /* write the sBIT chunk */
906 void /* PRIVATE */
908 {
909 #ifdef PNG_USE_LOCAL_ARRAYS
910  PNG_sBIT;
911 #endif
912  png_byte buf[4];
914 
915  png_debug(1, "in png_write_sBIT\n");
916  /* make sure we don't depend upon the order of PNG_COLOR_8 */
917  if (color_type & PNG_COLOR_MASK_COLOR)
918  {
919  png_byte maxbits;
920 
921  maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
922  png_ptr->usr_bit_depth);
923  if (sbit->red == 0 || sbit->red > maxbits ||
924  sbit->green == 0 || sbit->green > maxbits ||
925  sbit->blue == 0 || sbit->blue > maxbits)
926  {
927  png_warning(png_ptr, "Invalid sBIT depth specified");
928  return;
929  }
930  buf[0] = sbit->red;
931  buf[1] = sbit->green;
932  buf[2] = sbit->blue;
933  size = 3;
934  }
935  else
936  {
937  if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
938  {
939  png_warning(png_ptr, "Invalid sBIT depth specified");
940  return;
941  }
942  buf[0] = sbit->gray;
943  size = 1;
944  }
945 
946  if (color_type & PNG_COLOR_MASK_ALPHA)
947  {
948  if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
949  {
950  png_warning(png_ptr, "Invalid sBIT depth specified");
951  return;
952  }
953  buf[size++] = sbit->alpha;
954  }
955 
956  png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
957 }
958 #endif
959 
960 #if defined(PNG_WRITE_cHRM_SUPPORTED)
961 /* write the cHRM chunk */
962 #ifdef PNG_FLOATING_POINT_SUPPORTED
963 void /* PRIVATE */
964 png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
965  double red_x, double red_y, double green_x, double green_y,
966  double blue_x, double blue_y)
967 {
968 #ifdef PNG_USE_LOCAL_ARRAYS
969  PNG_cHRM;
970 #endif
971  png_byte buf[32];
972  png_uint_32 itemp;
973 
974  png_debug(1, "in png_write_cHRM\n");
975  /* each value is saved in 1/100,000ths */
976  if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
977  white_x + white_y > 1.0)
978  {
979  png_warning(png_ptr, "Invalid cHRM white point specified");
980 #if !defined(PNG_NO_CONSOLE_IO)
981  fprintf(stderr, "white_x=%f, white_y=%f\n", white_x, white_y);
982 #endif
983  return;
984  }
985  itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
986  png_save_uint_32(buf, itemp);
987  itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
988  png_save_uint_32(buf + 4, itemp);
989 
990  if (red_x < 0 || red_y < 0 || red_x + red_y > 1.0)
991  {
992  png_warning(png_ptr, "Invalid cHRM red point specified");
993  return;
994  }
995  itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
996  png_save_uint_32(buf + 8, itemp);
997  itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
998  png_save_uint_32(buf + 12, itemp);
999 
1000  if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0)
1001  {
1002  png_warning(png_ptr, "Invalid cHRM green point specified");
1003  return;
1004  }
1005  itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
1006  png_save_uint_32(buf + 16, itemp);
1007  itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
1008  png_save_uint_32(buf + 20, itemp);
1009 
1010  if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0)
1011  {
1012  png_warning(png_ptr, "Invalid cHRM blue point specified");
1013  return;
1014  }
1015  itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
1016  png_save_uint_32(buf + 24, itemp);
1017  itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
1018  png_save_uint_32(buf + 28, itemp);
1019 
1020  png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
1021 }
1022 #endif
1023 #ifdef PNG_FIXED_POINT_SUPPORTED
1024 void /* PRIVATE */
1029 {
1030 #ifdef PNG_USE_LOCAL_ARRAYS
1031  PNG_cHRM;
1032 #endif
1033  png_byte buf[32];
1034 
1035  png_debug(1, "in png_write_cHRM\n");
1036  /* each value is saved in 1/100,000ths */
1037  if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L)
1038  {
1039  png_warning(png_ptr, "Invalid fixed cHRM white point specified");
1040 #if !defined(PNG_NO_CONSOLE_IO)
1041  fprintf(stderr, "white_x=%ld, white_y=%ld\n", (unsigned long)white_x,
1042  (unsigned long)white_y);
1043 #endif
1044  return;
1045  }
1046  png_save_uint_32(buf, (png_uint_32)white_x);
1047  png_save_uint_32(buf + 4, (png_uint_32)white_y);
1048 
1049  if (red_x + red_y > 100000L)
1050  {
1051  png_warning(png_ptr, "Invalid cHRM fixed red point specified");
1052  return;
1053  }
1054  png_save_uint_32(buf + 8, (png_uint_32)red_x);
1055  png_save_uint_32(buf + 12, (png_uint_32)red_y);
1056 
1057  if (green_x + green_y > 100000L)
1058  {
1059  png_warning(png_ptr, "Invalid fixed cHRM green point specified");
1060  return;
1061  }
1062  png_save_uint_32(buf + 16, (png_uint_32)green_x);
1063  png_save_uint_32(buf + 20, (png_uint_32)green_y);
1064 
1065  if (blue_x + blue_y > 100000L)
1066  {
1067  png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
1068  return;
1069  }
1070  png_save_uint_32(buf + 24, (png_uint_32)blue_x);
1071  png_save_uint_32(buf + 28, (png_uint_32)blue_y);
1072 
1073  png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
1074 }
1075 #endif
1076 #endif
1077 
1078 #if defined(PNG_WRITE_tRNS_SUPPORTED)
1079 /* write the tRNS chunk */
1080 void /* PRIVATE */
1082  int num_trans, int color_type)
1083 {
1084 #ifdef PNG_USE_LOCAL_ARRAYS
1085  PNG_tRNS;
1086 #endif
1087  png_byte buf[6];
1088 
1089  png_debug(1, "in png_write_tRNS\n");
1090  if (color_type == PNG_COLOR_TYPE_PALETTE)
1091  {
1092  if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
1093  {
1094  png_warning(png_ptr, "Invalid number of transparent colors specified");
1095  return;
1096  }
1097  /* write the chunk out as it is */
1098  png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans,
1099  (png_size_t)num_trans);
1100  }
1101  else if (color_type == PNG_COLOR_TYPE_GRAY)
1102  {
1103  /* one 16 bit value */
1104  if (tran->gray >= (1 << png_ptr->bit_depth))
1105  {
1106  png_warning(png_ptr,
1107  "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1108  return;
1109  }
1110  png_save_uint_16(buf, tran->gray);
1111  png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
1112  }
1113  else if (color_type == PNG_COLOR_TYPE_RGB)
1114  {
1115  /* three 16 bit values */
1116  png_save_uint_16(buf, tran->red);
1117  png_save_uint_16(buf + 2, tran->green);
1118  png_save_uint_16(buf + 4, tran->blue);
1119  if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1120  {
1121  png_warning(png_ptr,
1122  "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1123  return;
1124  }
1125  png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
1126  }
1127  else
1128  {
1129  png_warning(png_ptr, "Can't write tRNS with an alpha channel");
1130  }
1131 }
1132 #endif
1133 
1134 #if defined(PNG_WRITE_bKGD_SUPPORTED)
1135 /* write the background chunk */
1136 void /* PRIVATE */
1138 {
1139 #ifdef PNG_USE_LOCAL_ARRAYS
1140  PNG_bKGD;
1141 #endif
1142  png_byte buf[6];
1143 
1144  png_debug(1, "in png_write_bKGD\n");
1145  if (color_type == PNG_COLOR_TYPE_PALETTE)
1146  {
1147  if (
1148 #if defined(PNG_MNG_FEATURES_SUPPORTED)
1149  (png_ptr->num_palette ||
1150  (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
1151 #endif
1152  back->index > png_ptr->num_palette)
1153  {
1154  png_warning(png_ptr, "Invalid background palette index");
1155  return;
1156  }
1157  buf[0] = back->index;
1158  png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
1159  }
1160  else if (color_type & PNG_COLOR_MASK_COLOR)
1161  {
1162  png_save_uint_16(buf, back->red);
1163  png_save_uint_16(buf + 2, back->green);
1164  png_save_uint_16(buf + 4, back->blue);
1165  if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1166  {
1167  png_warning(png_ptr,
1168  "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
1169  return;
1170  }
1171  png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
1172  }
1173  else
1174  {
1175  if (back->gray >= (1 << png_ptr->bit_depth))
1176  {
1177  png_warning(png_ptr,
1178  "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1179  return;
1180  }
1181  png_save_uint_16(buf, back->gray);
1182  png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
1183  }
1184 }
1185 #endif
1186 
1187 #if defined(PNG_WRITE_hIST_SUPPORTED)
1188 /* write the histogram */
1189 void /* PRIVATE */
1191 {
1192 #ifdef PNG_USE_LOCAL_ARRAYS
1193  PNG_hIST;
1194 #endif
1195  int i;
1196  png_byte buf[3];
1197 
1198  png_debug(1, "in png_write_hIST\n");
1199  if (num_hist > (int)png_ptr->num_palette)
1200  {
1201  png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
1202  png_ptr->num_palette);
1203  png_warning(png_ptr, "Invalid number of histogram entries specified");
1204  return;
1205  }
1206 
1207  png_write_chunk_start(png_ptr, (png_bytep)png_hIST,
1208  (png_uint_32)(num_hist * 2));
1209  for (i = 0; i < num_hist; i++)
1210  {
1211  png_save_uint_16(buf, hist[i]);
1212  png_write_chunk_data(png_ptr, buf, (png_size_t)2);
1213  }
1214  png_write_chunk_end(png_ptr);
1215 }
1216 #endif
1217 
1218 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
1219  defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
1220 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
1221  * and if invalid, correct the keyword rather than discarding the entire
1222  * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
1223  * length, forbids leading or trailing whitespace, multiple internal spaces,
1224  * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
1225  *
1226  * The new_key is allocated to hold the corrected keyword and must be freed
1227  * by the calling routine. This avoids problems with trying to write to
1228  * static keywords without having to have duplicate copies of the strings.
1229  */
1230 png_size_t /* PRIVATE */
1232 {
1233  png_size_t key_len;
1234  png_charp kp, dp;
1235  int kflag;
1236  int kwarn=0;
1237 
1238  png_debug(1, "in png_check_keyword\n");
1239  *new_key = NULL;
1240 
1241  if (key == NULL || (key_len = png_strlen(key)) == 0)
1242  {
1243  png_warning(png_ptr, "zero length keyword");
1244  return ((png_size_t)0);
1245  }
1246 
1247  png_debug1(2, "Keyword to be checked is '%s'\n", key);
1248 
1249  *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
1250  if (*new_key == NULL)
1251  {
1252  png_warning(png_ptr, "Out of memory while procesing keyword");
1253  return ((png_size_t)0);
1254  }
1255 
1256  /* Replace non-printing characters with a blank and print a warning */
1257  for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
1258  {
1259  if ((png_byte)*kp < 0x20 ||
1260  ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
1261  {
1262 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1263  char msg[40];
1264 
1265  png_snprintf(msg, 40,
1266  "invalid keyword character 0x%02X", (png_byte)*kp);
1267  png_warning(png_ptr, msg);
1268 #else
1269  png_warning(png_ptr, "invalid character in keyword");
1270 #endif
1271  *dp = ' ';
1272  }
1273  else
1274  {
1275  *dp = *kp;
1276  }
1277  }
1278  *dp = '\0';
1279 
1280  /* Remove any trailing white space. */
1281  kp = *new_key + key_len - 1;
1282  if (*kp == ' ')
1283  {
1284  png_warning(png_ptr, "trailing spaces removed from keyword");
1285 
1286  while (*kp == ' ')
1287  {
1288  *(kp--) = '\0';
1289  key_len--;
1290  }
1291  }
1292 
1293  /* Remove any leading white space. */
1294  kp = *new_key;
1295  if (*kp == ' ')
1296  {
1297  png_warning(png_ptr, "leading spaces removed from keyword");
1298 
1299  while (*kp == ' ')
1300  {
1301  kp++;
1302  key_len--;
1303  }
1304  }
1305 
1306  png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
1307 
1308  /* Remove multiple internal spaces. */
1309  for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
1310  {
1311  if (*kp == ' ' && kflag == 0)
1312  {
1313  *(dp++) = *kp;
1314  kflag = 1;
1315  }
1316  else if (*kp == ' ')
1317  {
1318  key_len--;
1319  kwarn=1;
1320  }
1321  else
1322  {
1323  *(dp++) = *kp;
1324  kflag = 0;
1325  }
1326  }
1327  *dp = '\0';
1328  if (kwarn)
1329  png_warning(png_ptr, "extra interior spaces removed from keyword");
1330 
1331  if (key_len == 0)
1332  {
1333  png_free(png_ptr, *new_key);
1334  *new_key=NULL;
1335  png_warning(png_ptr, "Zero length keyword");
1336  }
1337 
1338  if (key_len > 79)
1339  {
1340  png_warning(png_ptr, "keyword length must be 1 - 79 characters");
1341  new_key[79] = '\0';
1342  key_len = 79;
1343  }
1344 
1345  return (key_len);
1346 }
1347 #endif
1348 
1349 #if defined(PNG_WRITE_tEXt_SUPPORTED)
1350 /* write a tEXt chunk */
1351 void /* PRIVATE */
1353  png_size_t text_len)
1354 {
1355 #ifdef PNG_USE_LOCAL_ARRAYS
1356  PNG_tEXt;
1357 #endif
1358  png_size_t key_len;
1359  png_charp new_key;
1360 
1361  png_debug(1, "in png_write_tEXt\n");
1362  if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1363  {
1364  png_warning(png_ptr, "Empty keyword in tEXt chunk");
1365  return;
1366  }
1367 
1368  if (text == NULL || *text == '\0')
1369  text_len = 0;
1370  else
1371  text_len = png_strlen(text);
1372 
1373  /* make sure we include the 0 after the key */
1374  png_write_chunk_start(png_ptr, (png_bytep)png_tEXt,
1375  (png_uint_32)(key_len + text_len + 1));
1376  /*
1377  * We leave it to the application to meet PNG-1.0 requirements on the
1378  * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1379  * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1380  * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1381  */
1382  png_write_chunk_data(png_ptr, (png_bytep)new_key,
1383  (png_size_t)(key_len + 1));
1384  if (text_len)
1385  png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len);
1386 
1387  png_write_chunk_end(png_ptr);
1388  png_free(png_ptr, new_key);
1389 }
1390 #endif
1391 
1392 #if defined(PNG_WRITE_zTXt_SUPPORTED)
1393 /* write a compressed text chunk */
1394 void /* PRIVATE */
1396  png_size_t text_len, int compression)
1397 {
1398 #ifdef PNG_USE_LOCAL_ARRAYS
1399  PNG_zTXt;
1400 #endif
1401  png_size_t key_len;
1402  char buf[1];
1403  png_charp new_key;
1404  compression_state comp;
1405 
1406  png_debug(1, "in png_write_zTXt\n");
1407 
1408  comp.num_output_ptr = 0;
1409  comp.max_output_ptr = 0;
1410  comp.output_ptr = NULL;
1411  comp.input = NULL;
1412  comp.input_len = 0;
1413 
1414  if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1415  {
1416  png_warning(png_ptr, "Empty keyword in zTXt chunk");
1417  png_free(png_ptr, new_key);
1418  return;
1419  }
1420 
1421  if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
1422  {
1423  png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
1424  png_free(png_ptr, new_key);
1425  return;
1426  }
1427 
1428  text_len = png_strlen(text);
1429 
1430  /* compute the compressed data; do it now for the length */
1431  text_len = png_text_compress(png_ptr, text, text_len, compression,
1432  &comp);
1433 
1434  /* write start of chunk */
1435  png_write_chunk_start(png_ptr, (png_bytep)png_zTXt,
1436  (png_uint_32)(key_len+text_len + 2));
1437  /* write key */
1438  png_write_chunk_data(png_ptr, (png_bytep)new_key,
1439  (png_size_t)(key_len + 1));
1440  png_free(png_ptr, new_key);
1441 
1442  buf[0] = (png_byte)compression;
1443  /* write compression */
1444  png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
1445  /* write the compressed data */
1446  png_write_compressed_data_out(png_ptr, &comp);
1447 
1448  /* close the chunk */
1449  png_write_chunk_end(png_ptr);
1450 }
1451 #endif
1452 
1453 #if defined(PNG_WRITE_iTXt_SUPPORTED)
1454 /* write an iTXt chunk */
1455 void /* PRIVATE */
1456 png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
1457  png_charp lang, png_charp lang_key, png_charp text)
1458 {
1459 #ifdef PNG_USE_LOCAL_ARRAYS
1460  PNG_iTXt;
1461 #endif
1462  png_size_t lang_len, key_len, lang_key_len, text_len;
1463  png_charp new_lang, new_key;
1464  png_byte cbuf[2];
1465  compression_state comp;
1466 
1467  png_debug(1, "in png_write_iTXt\n");
1468 
1469  comp.num_output_ptr = 0;
1470  comp.max_output_ptr = 0;
1471  comp.output_ptr = NULL;
1472  comp.input = NULL;
1473 
1474  if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1475  {
1476  png_warning(png_ptr, "Empty keyword in iTXt chunk");
1477  return;
1478  }
1479  if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0)
1480  {
1481  png_warning(png_ptr, "Empty language field in iTXt chunk");
1482  new_lang = NULL;
1483  lang_len = 0;
1484  }
1485 
1486  if (lang_key == NULL)
1487  lang_key_len = 0;
1488  else
1489  lang_key_len = png_strlen(lang_key);
1490 
1491  if (text == NULL)
1492  text_len = 0;
1493  else
1494  text_len = png_strlen(text);
1495 
1496  /* compute the compressed data; do it now for the length */
1497  text_len = png_text_compress(png_ptr, text, text_len, compression-2,
1498  &comp);
1499 
1500 
1501  /* make sure we include the compression flag, the compression byte,
1502  * and the NULs after the key, lang, and lang_key parts */
1503 
1504  png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
1505  (png_uint_32)(
1506  5 /* comp byte, comp flag, terminators for key, lang and lang_key */
1507  + key_len
1508  + lang_len
1509  + lang_key_len
1510  + text_len));
1511 
1512  /*
1513  * We leave it to the application to meet PNG-1.0 requirements on the
1514  * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1515  * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1516  * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1517  */
1518  png_write_chunk_data(png_ptr, (png_bytep)new_key,
1519  (png_size_t)(key_len + 1));
1520 
1521  /* set the compression flag */
1522  if (compression == PNG_ITXT_COMPRESSION_NONE || \
1523  compression == PNG_TEXT_COMPRESSION_NONE)
1524  cbuf[0] = 0;
1525  else /* compression == PNG_ITXT_COMPRESSION_zTXt */
1526  cbuf[0] = 1;
1527  /* set the compression method */
1528  cbuf[1] = 0;
1529  png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
1530 
1531  cbuf[0] = 0;
1532  png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf),
1533  (png_size_t)(lang_len + 1));
1534  png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf),
1535  (png_size_t)(lang_key_len + 1));
1536  png_write_compressed_data_out(png_ptr, &comp);
1537 
1538  png_write_chunk_end(png_ptr);
1539  png_free(png_ptr, new_key);
1540  png_free(png_ptr, new_lang);
1541 }
1542 #endif
1543 
1544 #if defined(PNG_WRITE_oFFs_SUPPORTED)
1545 /* write the oFFs chunk */
1546 void /* PRIVATE */
1547 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1548  int unit_type)
1549 {
1550 #ifdef PNG_USE_LOCAL_ARRAYS
1551  PNG_oFFs;
1552 #endif
1553  png_byte buf[9];
1554 
1555  png_debug(1, "in png_write_oFFs\n");
1556  if (unit_type >= PNG_OFFSET_LAST)
1557  png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
1558 
1559  png_save_int_32(buf, x_offset);
1560  png_save_int_32(buf + 4, y_offset);
1561  buf[8] = (png_byte)unit_type;
1562 
1563  png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
1564 }
1565 #endif
1566 #if defined(PNG_WRITE_pCAL_SUPPORTED)
1567 /* write the pCAL chunk (described in the PNG extensions document) */
1568 void /* PRIVATE */
1571 {
1572 #ifdef PNG_USE_LOCAL_ARRAYS
1573  PNG_pCAL;
1574 #endif
1575  png_size_t purpose_len, units_len, total_len;
1576  png_uint_32p params_len;
1577  png_byte buf[10];
1578  png_charp new_purpose;
1579  int i;
1580 
1581  png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
1582  if (type >= PNG_EQUATION_LAST)
1583  png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1584 
1585  purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
1586  png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len);
1587  units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
1588  png_debug1(3, "pCAL units length = %d\n", (int)units_len);
1589  total_len = purpose_len + units_len + 10;
1590 
1591  params_len = (png_uint_32p)png_malloc(png_ptr,
1592  (png_uint_32)(nparams * png_sizeof(png_uint_32)));
1593 
1594  /* Find the length of each parameter, making sure we don't count the
1595  null terminator for the last parameter. */
1596  for (i = 0; i < nparams; i++)
1597  {
1598  params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1599  png_debug2(3, "pCAL parameter %d length = %lu\n", i,
1600  (unsigned long) params_len[i]);
1601  total_len += (png_size_t)params_len[i];
1602  }
1603 
1604  png_debug1(3, "pCAL total length = %d\n", (int)total_len);
1605  png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
1606  png_write_chunk_data(png_ptr, (png_bytep)new_purpose,
1607  (png_size_t)purpose_len);
1608  png_save_int_32(buf, X0);
1609  png_save_int_32(buf + 4, X1);
1610  buf[8] = (png_byte)type;
1611  buf[9] = (png_byte)nparams;
1612  png_write_chunk_data(png_ptr, buf, (png_size_t)10);
1613  png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
1614 
1615  png_free(png_ptr, new_purpose);
1616 
1617  for (i = 0; i < nparams; i++)
1618  {
1619  png_write_chunk_data(png_ptr, (png_bytep)params[i],
1620  (png_size_t)params_len[i]);
1621  }
1622 
1623  png_free(png_ptr, params_len);
1624  png_write_chunk_end(png_ptr);
1625 }
1626 #endif
1627 
1628 #if defined(PNG_WRITE_sCAL_SUPPORTED)
1629 /* write the sCAL chunk */
1630 #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
1631 void /* PRIVATE */
1632 png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
1633 {
1634 #ifdef PNG_USE_LOCAL_ARRAYS
1635  PNG_sCAL;
1636 #endif
1637  char buf[64];
1638  png_size_t total_len;
1639 
1640  png_debug(1, "in png_write_sCAL\n");
1641 
1642  buf[0] = (char)unit;
1643 #if defined(_WIN32_WCE)
1644 /* sprintf() function is not supported on WindowsCE */
1645  {
1646  wchar_t wc_buf[32];
1647  size_t wc_len;
1648  swprintf(wc_buf, TEXT("%12.12e"), width);
1649  wc_len = wcslen(wc_buf);
1650  WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL);
1651  total_len = wc_len + 2;
1652  swprintf(wc_buf, TEXT("%12.12e"), height);
1653  wc_len = wcslen(wc_buf);
1654  WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len,
1655  NULL, NULL);
1656  total_len += wc_len;
1657  }
1658 #else
1659  png_snprintf(buf + 1, 63, "%12.12e", width);
1660  total_len = 1 + png_strlen(buf + 1) + 1;
1661  png_snprintf(buf + total_len, 64-total_len, "%12.12e", height);
1662  total_len += png_strlen(buf + total_len);
1663 #endif
1664 
1665  png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len);
1666  png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
1667 }
1668 #else
1669 #ifdef PNG_FIXED_POINT_SUPPORTED
1670 void /* PRIVATE */
1671 png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
1672  png_charp height)
1673 {
1674 #ifdef PNG_USE_LOCAL_ARRAYS
1675  PNG_sCAL;
1676 #endif
1677  png_byte buf[64];
1678  png_size_t wlen, hlen, total_len;
1679 
1680  png_debug(1, "in png_write_sCAL_s\n");
1681 
1682  wlen = png_strlen(width);
1683  hlen = png_strlen(height);
1684  total_len = wlen + hlen + 2;
1685  if (total_len > 64)
1686  {
1687  png_warning(png_ptr, "Can't write sCAL (buffer too small)");
1688  return;
1689  }
1690 
1691  buf[0] = (png_byte)unit;
1692  png_memcpy(buf + 1, width, wlen + 1); /* append the '\0' here */
1693  png_memcpy(buf + wlen + 2, height, hlen); /* do NOT append the '\0' here */
1694 
1695  png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len);
1696  png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len);
1697 }
1698 #endif
1699 #endif
1700 #endif
1701 
1702 #if defined(PNG_WRITE_pHYs_SUPPORTED)
1703 /* write the pHYs chunk */
1704 void /* PRIVATE */
1705 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1706  png_uint_32 y_pixels_per_unit,
1707  int unit_type)
1708 {
1709 #ifdef PNG_USE_LOCAL_ARRAYS
1710  PNG_pHYs;
1711 #endif
1712  png_byte buf[9];
1713 
1714  png_debug(1, "in png_write_pHYs\n");
1715  if (unit_type >= PNG_RESOLUTION_LAST)
1716  png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
1717 
1718  png_save_uint_32(buf, x_pixels_per_unit);
1719  png_save_uint_32(buf + 4, y_pixels_per_unit);
1720  buf[8] = (png_byte)unit_type;
1721 
1722  png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
1723 }
1724 #endif
1725 
1726 #if defined(PNG_WRITE_tIME_SUPPORTED)
1727 /* Write the tIME chunk. Use either png_convert_from_struct_tm()
1728  * or png_convert_from_time_t(), or fill in the structure yourself.
1729  */
1730 void /* PRIVATE */
1732 {
1733 #ifdef PNG_USE_LOCAL_ARRAYS
1734  PNG_tIME;
1735 #endif
1736  png_byte buf[7];
1737 
1738  png_debug(1, "in png_write_tIME\n");
1739  if (mod_time->month > 12 || mod_time->month < 1 ||
1740  mod_time->day > 31 || mod_time->day < 1 ||
1741  mod_time->hour > 23 || mod_time->second > 60)
1742  {
1743  png_warning(png_ptr, "Invalid time specified for tIME chunk");
1744  return;
1745  }
1746 
1747  png_save_uint_16(buf, mod_time->year);
1748  buf[2] = mod_time->month;
1749  buf[3] = mod_time->day;
1750  buf[4] = mod_time->hour;
1751  buf[5] = mod_time->minute;
1752  buf[6] = mod_time->second;
1753 
1754  png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
1755 }
1756 #endif
1757 
1758 /* initializes the row writing capability of libpng */
1759 void /* PRIVATE */
1761 {
1762 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
1763 #ifdef PNG_USE_LOCAL_ARRAYS
1764  /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1765 
1766  /* start of interlace block */
1767  int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1768 
1769  /* offset to next interlace block */
1770  int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1771 
1772  /* start of interlace block in the y direction */
1773  int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1774 
1775  /* offset to next interlace block in the y direction */
1776  int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1777 #endif
1778 #endif
1779 
1780  png_size_t buf_size;
1781 
1782  png_debug(1, "in png_write_start_row\n");
1783  buf_size = (png_size_t)(PNG_ROWBYTES(
1784  png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
1785 
1786  /* set up row buffer */
1787  png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
1788  (png_uint_32)buf_size);
1789  png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
1790 
1791 #ifndef PNG_NO_WRITE_FILTER
1792  /* set up filtering buffer, if using this filter */
1793  if (png_ptr->do_filter & PNG_FILTER_SUB)
1794  {
1795  png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
1796  (png_uint_32)(png_ptr->rowbytes + 1));
1797  png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
1798  }
1799 
1800  /* We only need to keep the previous row if we are using one of these. */
1801  if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
1802  {
1803  /* set up previous row buffer */
1804  png_ptr->prev_row = (png_bytep)png_malloc(png_ptr,
1805  (png_uint_32)buf_size);
1806  png_memset(png_ptr->prev_row, 0, buf_size);
1807 
1808  if (png_ptr->do_filter & PNG_FILTER_UP)
1809  {
1810  png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
1811  (png_uint_32)(png_ptr->rowbytes + 1));
1812  png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
1813  }
1814 
1815  if (png_ptr->do_filter & PNG_FILTER_AVG)
1816  {
1817  png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
1818  (png_uint_32)(png_ptr->rowbytes + 1));
1819  png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
1820  }
1821 
1822  if (png_ptr->do_filter & PNG_FILTER_PAETH)
1823  {
1824  png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
1825  (png_uint_32)(png_ptr->rowbytes + 1));
1826  png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
1827  }
1828  }
1829 #endif /* PNG_NO_WRITE_FILTER */
1830 
1831 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
1832  /* if interlaced, we need to set up width and height of pass */
1833  if (png_ptr->interlaced)
1834  {
1835  if (!(png_ptr->transformations & PNG_INTERLACE))
1836  {
1837  png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
1838  png_pass_ystart[0]) / png_pass_yinc[0];
1839  png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
1840  png_pass_start[0]) / png_pass_inc[0];
1841  }
1842  else
1843  {
1844  png_ptr->num_rows = png_ptr->height;
1845  png_ptr->usr_width = png_ptr->width;
1846  }
1847  }
1848  else
1849 #endif
1850  {
1851  png_ptr->num_rows = png_ptr->height;
1852  png_ptr->usr_width = png_ptr->width;
1853  }
1854  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1855  png_ptr->zstream.next_out = png_ptr->zbuf;
1856 }
1857 
1858 /* Internal use only. Called when finished processing a row of data. */
1859 void /* PRIVATE */
1861 {
1862 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
1863 #ifdef PNG_USE_LOCAL_ARRAYS
1864  /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1865 
1866  /* start of interlace block */
1867  int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1868 
1869  /* offset to next interlace block */
1870  int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1871 
1872  /* start of interlace block in the y direction */
1873  int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
1874 
1875  /* offset to next interlace block in the y direction */
1876  int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
1877 #endif
1878 #endif
1879 
1880  int ret;
1881 
1882  png_debug(1, "in png_write_finish_row\n");
1883  /* next row */
1884  png_ptr->row_number++;
1885 
1886  /* see if we are done */
1887  if (png_ptr->row_number < png_ptr->num_rows)
1888  return;
1889 
1890 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
1891  /* if interlaced, go to next pass */
1892  if (png_ptr->interlaced)
1893  {
1894  png_ptr->row_number = 0;
1895  if (png_ptr->transformations & PNG_INTERLACE)
1896  {
1897  png_ptr->pass++;
1898  }
1899  else
1900  {
1901  /* loop until we find a non-zero width or height pass */
1902  do
1903  {
1904  png_ptr->pass++;
1905  if (png_ptr->pass >= 7)
1906  break;
1907  png_ptr->usr_width = (png_ptr->width +
1908  png_pass_inc[png_ptr->pass] - 1 -
1909  png_pass_start[png_ptr->pass]) /
1910  png_pass_inc[png_ptr->pass];
1911  png_ptr->num_rows = (png_ptr->height +
1912  png_pass_yinc[png_ptr->pass] - 1 -
1913  png_pass_ystart[png_ptr->pass]) /
1914  png_pass_yinc[png_ptr->pass];
1915  if (png_ptr->transformations & PNG_INTERLACE)
1916  break;
1917  } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
1918 
1919  }
1920 
1921  /* reset the row above the image for the next pass */
1922  if (png_ptr->pass < 7)
1923  {
1924  if (png_ptr->prev_row != NULL)
1925  png_memset(png_ptr->prev_row, 0,
1926  (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
1927  png_ptr->usr_bit_depth, png_ptr->width)) + 1);
1928  return;
1929  }
1930  }
1931 #endif
1932 
1933  /* if we get here, we've just written the last row, so we need
1934  to flush the compressor */
1935  do
1936  {
1937  /* tell the compressor we are done */
1938  ret = deflate(&png_ptr->zstream, Z_FINISH);
1939  /* check for an error */
1940  if (ret == Z_OK)
1941  {
1942  /* check to see if we need more room */
1943  if (!(png_ptr->zstream.avail_out))
1944  {
1945  png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
1946  png_ptr->zstream.next_out = png_ptr->zbuf;
1947  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1948  }
1949  }
1950  else if (ret != Z_STREAM_END)
1951  {
1952  if (png_ptr->zstream.msg != NULL)
1953  png_error(png_ptr, png_ptr->zstream.msg);
1954  else
1955  png_error(png_ptr, "zlib error");
1956  }
1957  } while (ret != Z_STREAM_END);
1958 
1959  /* write any extra space */
1960  if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
1961  {
1962  png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
1963  png_ptr->zstream.avail_out);
1964  }
1965 
1966  deflateReset(&png_ptr->zstream);
1967  png_ptr->zstream.data_type = Z_BINARY;
1968 }
1969 
1970 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
1971 /* Pick out the correct pixels for the interlace pass.
1972  * The basic idea here is to go through the row with a source
1973  * pointer and a destination pointer (sp and dp), and copy the
1974  * correct pixels for the pass. As the row gets compacted,
1975  * sp will always be >= dp, so we should never overwrite anything.
1976  * See the default: case for the easiest code to understand.
1977  */
1978 void /* PRIVATE */
1980 {
1981 #ifdef PNG_USE_LOCAL_ARRAYS
1982  /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
1983 
1984  /* start of interlace block */
1985  int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
1986 
1987  /* offset to next interlace block */
1988  int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
1989 #endif
1990 
1991  png_debug(1, "in png_do_write_interlace\n");
1992  /* we don't have to do anything on the last pass (6) */
1993 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1994  if (row != NULL && row_info != NULL && pass < 6)
1995 #else
1996  if (pass < 6)
1997 #endif
1998  {
1999  /* each pixel depth is handled separately */
2000  switch (row_info->pixel_depth)
2001  {
2002  case 1:
2003  {
2004  png_bytep sp;
2005  png_bytep dp;
2006  int shift;
2007  int d;
2008  int value;
2009  png_uint_32 i;
2010  png_uint_32 row_width = row_info->width;
2011 
2012  dp = row;
2013  d = 0;
2014  shift = 7;
2015  for (i = png_pass_start[pass]; i < row_width;
2016  i += png_pass_inc[pass])
2017  {
2018  sp = row + (png_size_t)(i >> 3);
2019  value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
2020  d |= (value << shift);
2021 
2022  if (shift == 0)
2023  {
2024  shift = 7;
2025  *dp++ = (png_byte)d;
2026  d = 0;
2027  }
2028  else
2029  shift--;
2030 
2031  }
2032  if (shift != 7)
2033  *dp = (png_byte)d;
2034  break;
2035  }
2036  case 2:
2037  {
2038  png_bytep sp;
2039  png_bytep dp;
2040  int shift;
2041  int d;
2042  int value;
2043  png_uint_32 i;
2044  png_uint_32 row_width = row_info->width;
2045 
2046  dp = row;
2047  shift = 6;
2048  d = 0;
2049  for (i = png_pass_start[pass]; i < row_width;
2050  i += png_pass_inc[pass])
2051  {
2052  sp = row + (png_size_t)(i >> 2);
2053  value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
2054  d |= (value << shift);
2055 
2056  if (shift == 0)
2057  {
2058  shift = 6;
2059  *dp++ = (png_byte)d;
2060  d = 0;
2061  }
2062  else
2063  shift -= 2;
2064  }
2065  if (shift != 6)
2066  *dp = (png_byte)d;
2067  break;
2068  }
2069  case 4:
2070  {
2071  png_bytep sp;
2072  png_bytep dp;
2073  int shift;
2074  int d;
2075  int value;
2076  png_uint_32 i;
2077  png_uint_32 row_width = row_info->width;
2078 
2079  dp = row;
2080  shift = 4;
2081  d = 0;
2082  for (i = png_pass_start[pass]; i < row_width;
2083  i += png_pass_inc[pass])
2084  {
2085  sp = row + (png_size_t)(i >> 1);
2086  value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
2087  d |= (value << shift);
2088 
2089  if (shift == 0)
2090  {
2091  shift = 4;
2092  *dp++ = (png_byte)d;
2093  d = 0;
2094  }
2095  else
2096  shift -= 4;
2097  }
2098  if (shift != 4)
2099  *dp = (png_byte)d;
2100  break;
2101  }
2102  default:
2103  {
2104  png_bytep sp;
2105  png_bytep dp;
2106  png_uint_32 i;
2107  png_uint_32 row_width = row_info->width;
2108  png_size_t pixel_bytes;
2109 
2110  /* start at the beginning */
2111  dp = row;
2112  /* find out how many bytes each pixel takes up */
2113  pixel_bytes = (row_info->pixel_depth >> 3);
2114  /* loop through the row, only looking at the pixels that
2115  matter */
2116  for (i = png_pass_start[pass]; i < row_width;
2117  i += png_pass_inc[pass])
2118  {
2119  /* find out where the original pixel is */
2120  sp = row + (png_size_t)i * pixel_bytes;
2121  /* move the pixel */
2122  if (dp != sp)
2123  png_memcpy(dp, sp, pixel_bytes);
2124  /* next pixel */
2125  dp += pixel_bytes;
2126  }
2127  break;
2128  }
2129  }
2130  /* set new row width */
2131  row_info->width = (row_info->width +
2132  png_pass_inc[pass] - 1 -
2133  png_pass_start[pass]) /
2134  png_pass_inc[pass];
2135  row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
2136  row_info->width);
2137  }
2138 }
2139 #endif
2140 
2141 /* This filters the row, chooses which filter to use, if it has not already
2142  * been specified by the application, and then writes the row out with the
2143  * chosen filter.
2144  */
2145 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
2146 #define PNG_HISHIFT 10
2147 #define PNG_LOMASK ((png_uint_32)0xffffL)
2148 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
2149 void /* PRIVATE */
2151 {
2152  png_bytep best_row;
2153 #ifndef PNG_NO_WRITE_FILTER
2154  png_bytep prev_row, row_buf;
2155  png_uint_32 mins, bpp;
2156  png_byte filter_to_do = png_ptr->do_filter;
2157  png_uint_32 row_bytes = row_info->rowbytes;
2158 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2159  int num_p_filters = (int)png_ptr->num_prev_filters;
2160 #endif
2161 
2162  png_debug(1, "in png_write_find_filter\n");
2163  /* find out how many bytes offset each pixel is */
2164  bpp = (row_info->pixel_depth + 7) >> 3;
2165 
2166  prev_row = png_ptr->prev_row;
2167 #endif
2168  best_row = png_ptr->row_buf;
2169 #ifndef PNG_NO_WRITE_FILTER
2170  row_buf = best_row;
2171  mins = PNG_MAXSUM;
2172 
2173  /* The prediction method we use is to find which method provides the
2174  * smallest value when summing the absolute values of the distances
2175  * from zero, using anything >= 128 as negative numbers. This is known
2176  * as the "minimum sum of absolute differences" heuristic. Other
2177  * heuristics are the "weighted minimum sum of absolute differences"
2178  * (experimental and can in theory improve compression), and the "zlib
2179  * predictive" method (not implemented yet), which does test compressions
2180  * of lines using different filter methods, and then chooses the
2181  * (series of) filter(s) that give minimum compressed data size (VERY
2182  * computationally expensive).
2183  *
2184  * GRR 980525: consider also
2185  * (1) minimum sum of absolute differences from running average (i.e.,
2186  * keep running sum of non-absolute differences & count of bytes)
2187  * [track dispersion, too? restart average if dispersion too large?]
2188  * (1b) minimum sum of absolute differences from sliding average, probably
2189  * with window size <= deflate window (usually 32K)
2190  * (2) minimum sum of squared differences from zero or running average
2191  * (i.e., ~ root-mean-square approach)
2192  */
2193 
2194 
2195  /* We don't need to test the 'no filter' case if this is the only filter
2196  * that has been chosen, as it doesn't actually do anything to the data.
2197  */
2198  if ((filter_to_do & PNG_FILTER_NONE) &&
2199  filter_to_do != PNG_FILTER_NONE)
2200  {
2201  png_bytep rp;
2202  png_uint_32 sum = 0;
2203  png_uint_32 i;
2204  int v;
2205 
2206  for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
2207  {
2208  v = *rp;
2209  sum += (v < 128) ? v : 256 - v;
2210  }
2211 
2212 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2213  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2214  {
2215  png_uint_32 sumhi, sumlo;
2216  int j;
2217  sumlo = sum & PNG_LOMASK;
2218  sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
2219 
2220  /* Reduce the sum if we match any of the previous rows */
2221  for (j = 0; j < num_p_filters; j++)
2222  {
2223  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2224  {
2225  sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2226  PNG_WEIGHT_SHIFT;
2227  sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2228  PNG_WEIGHT_SHIFT;
2229  }
2230  }
2231 
2232  /* Factor in the cost of this filter (this is here for completeness,
2233  * but it makes no sense to have a "cost" for the NONE filter, as
2234  * it has the minimum possible computational cost - none).
2235  */
2236  sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2237  PNG_COST_SHIFT;
2238  sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2239  PNG_COST_SHIFT;
2240 
2241  if (sumhi > PNG_HIMASK)
2242  sum = PNG_MAXSUM;
2243  else
2244  sum = (sumhi << PNG_HISHIFT) + sumlo;
2245  }
2246 #endif
2247  mins = sum;
2248  }
2249 
2250  /* sub filter */
2251  if (filter_to_do == PNG_FILTER_SUB)
2252  /* it's the only filter so no testing is needed */
2253  {
2254  png_bytep rp, lp, dp;
2255  png_uint_32 i;
2256  for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2257  i++, rp++, dp++)
2258  {
2259  *dp = *rp;
2260  }
2261  for (lp = row_buf + 1; i < row_bytes;
2262  i++, rp++, lp++, dp++)
2263  {
2264  *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2265  }
2266  best_row = png_ptr->sub_row;
2267  }
2268 
2269  else if (filter_to_do & PNG_FILTER_SUB)
2270  {
2271  png_bytep rp, dp, lp;
2272  png_uint_32 sum = 0, lmins = mins;
2273  png_uint_32 i;
2274  int v;
2275 
2276 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2277  /* We temporarily increase the "minimum sum" by the factor we
2278  * would reduce the sum of this filter, so that we can do the
2279  * early exit comparison without scaling the sum each time.
2280  */
2281  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2282  {
2283  int j;
2284  png_uint_32 lmhi, lmlo;
2285  lmlo = lmins & PNG_LOMASK;
2286  lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2287 
2288  for (j = 0; j < num_p_filters; j++)
2289  {
2290  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2291  {
2292  lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2293  PNG_WEIGHT_SHIFT;
2294  lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2295  PNG_WEIGHT_SHIFT;
2296  }
2297  }
2298 
2299  lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2300  PNG_COST_SHIFT;
2301  lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2302  PNG_COST_SHIFT;
2303 
2304  if (lmhi > PNG_HIMASK)
2305  lmins = PNG_MAXSUM;
2306  else
2307  lmins = (lmhi << PNG_HISHIFT) + lmlo;
2308  }
2309 #endif
2310 
2311  for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2312  i++, rp++, dp++)
2313  {
2314  v = *dp = *rp;
2315 
2316  sum += (v < 128) ? v : 256 - v;
2317  }
2318  for (lp = row_buf + 1; i < row_bytes;
2319  i++, rp++, lp++, dp++)
2320  {
2321  v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2322 
2323  sum += (v < 128) ? v : 256 - v;
2324 
2325  if (sum > lmins) /* We are already worse, don't continue. */
2326  break;
2327  }
2328 
2329 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2330  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2331  {
2332  int j;
2333  png_uint_32 sumhi, sumlo;
2334  sumlo = sum & PNG_LOMASK;
2335  sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2336 
2337  for (j = 0; j < num_p_filters; j++)
2338  {
2339  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2340  {
2341  sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
2342  PNG_WEIGHT_SHIFT;
2343  sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
2344  PNG_WEIGHT_SHIFT;
2345  }
2346  }
2347 
2348  sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2349  PNG_COST_SHIFT;
2350  sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2351  PNG_COST_SHIFT;
2352 
2353  if (sumhi > PNG_HIMASK)
2354  sum = PNG_MAXSUM;
2355  else
2356  sum = (sumhi << PNG_HISHIFT) + sumlo;
2357  }
2358 #endif
2359 
2360  if (sum < mins)
2361  {
2362  mins = sum;
2363  best_row = png_ptr->sub_row;
2364  }
2365  }
2366 
2367  /* up filter */
2368  if (filter_to_do == PNG_FILTER_UP)
2369  {
2370  png_bytep rp, dp, pp;
2371  png_uint_32 i;
2372 
2373  for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2374  pp = prev_row + 1; i < row_bytes;
2375  i++, rp++, pp++, dp++)
2376  {
2377  *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2378  }
2379  best_row = png_ptr->up_row;
2380  }
2381 
2382  else if (filter_to_do & PNG_FILTER_UP)
2383  {
2384  png_bytep rp, dp, pp;
2385  png_uint_32 sum = 0, lmins = mins;
2386  png_uint_32 i;
2387  int v;
2388 
2389 
2390 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2391  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2392  {
2393  int j;
2394  png_uint_32 lmhi, lmlo;
2395  lmlo = lmins & PNG_LOMASK;
2396  lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2397 
2398  for (j = 0; j < num_p_filters; j++)
2399  {
2400  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2401  {
2402  lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2403  PNG_WEIGHT_SHIFT;
2404  lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2405  PNG_WEIGHT_SHIFT;
2406  }
2407  }
2408 
2409  lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2410  PNG_COST_SHIFT;
2411  lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2412  PNG_COST_SHIFT;
2413 
2414  if (lmhi > PNG_HIMASK)
2415  lmins = PNG_MAXSUM;
2416  else
2417  lmins = (lmhi << PNG_HISHIFT) + lmlo;
2418  }
2419 #endif
2420 
2421  for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2422  pp = prev_row + 1; i < row_bytes; i++)
2423  {
2424  v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2425 
2426  sum += (v < 128) ? v : 256 - v;
2427 
2428  if (sum > lmins) /* We are already worse, don't continue. */
2429  break;
2430  }
2431 
2432 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2433  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2434  {
2435  int j;
2436  png_uint_32 sumhi, sumlo;
2437  sumlo = sum & PNG_LOMASK;
2438  sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2439 
2440  for (j = 0; j < num_p_filters; j++)
2441  {
2442  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2443  {
2444  sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2445  PNG_WEIGHT_SHIFT;
2446  sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2447  PNG_WEIGHT_SHIFT;
2448  }
2449  }
2450 
2451  sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2452  PNG_COST_SHIFT;
2453  sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2454  PNG_COST_SHIFT;
2455 
2456  if (sumhi > PNG_HIMASK)
2457  sum = PNG_MAXSUM;
2458  else
2459  sum = (sumhi << PNG_HISHIFT) + sumlo;
2460  }
2461 #endif
2462 
2463  if (sum < mins)
2464  {
2465  mins = sum;
2466  best_row = png_ptr->up_row;
2467  }
2468  }
2469 
2470  /* avg filter */
2471  if (filter_to_do == PNG_FILTER_AVG)
2472  {
2473  png_bytep rp, dp, pp, lp;
2474  png_uint_32 i;
2475  for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2476  pp = prev_row + 1; i < bpp; i++)
2477  {
2478  *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2479  }
2480  for (lp = row_buf + 1; i < row_bytes; i++)
2481  {
2482  *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
2483  & 0xff);
2484  }
2485  best_row = png_ptr->avg_row;
2486  }
2487 
2488  else if (filter_to_do & PNG_FILTER_AVG)
2489  {
2490  png_bytep rp, dp, pp, lp;
2491  png_uint_32 sum = 0, lmins = mins;
2492  png_uint_32 i;
2493  int v;
2494 
2495 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2496  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2497  {
2498  int j;
2499  png_uint_32 lmhi, lmlo;
2500  lmlo = lmins & PNG_LOMASK;
2501  lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2502 
2503  for (j = 0; j < num_p_filters; j++)
2504  {
2505  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
2506  {
2507  lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2508  PNG_WEIGHT_SHIFT;
2509  lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2510  PNG_WEIGHT_SHIFT;
2511  }
2512  }
2513 
2514  lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2515  PNG_COST_SHIFT;
2516  lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2517  PNG_COST_SHIFT;
2518 
2519  if (lmhi > PNG_HIMASK)
2520  lmins = PNG_MAXSUM;
2521  else
2522  lmins = (lmhi << PNG_HISHIFT) + lmlo;
2523  }
2524 #endif
2525 
2526  for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2527  pp = prev_row + 1; i < bpp; i++)
2528  {
2529  v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2530 
2531  sum += (v < 128) ? v : 256 - v;
2532  }
2533  for (lp = row_buf + 1; i < row_bytes; i++)
2534  {
2535  v = *dp++ =
2536  (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
2537 
2538  sum += (v < 128) ? v : 256 - v;
2539 
2540  if (sum > lmins) /* We are already worse, don't continue. */
2541  break;
2542  }
2543 
2544 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2545  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2546  {
2547  int j;
2548  png_uint_32 sumhi, sumlo;
2549  sumlo = sum & PNG_LOMASK;
2550  sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2551 
2552  for (j = 0; j < num_p_filters; j++)
2553  {
2554  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2555  {
2556  sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2557  PNG_WEIGHT_SHIFT;
2558  sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2559  PNG_WEIGHT_SHIFT;
2560  }
2561  }
2562 
2563  sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2564  PNG_COST_SHIFT;
2565  sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2566  PNG_COST_SHIFT;
2567 
2568  if (sumhi > PNG_HIMASK)
2569  sum = PNG_MAXSUM;
2570  else
2571  sum = (sumhi << PNG_HISHIFT) + sumlo;
2572  }
2573 #endif
2574 
2575  if (sum < mins)
2576  {
2577  mins = sum;
2578  best_row = png_ptr->avg_row;
2579  }
2580  }
2581 
2582  /* Paeth filter */
2583  if (filter_to_do == PNG_FILTER_PAETH)
2584  {
2585  png_bytep rp, dp, pp, cp, lp;
2586  png_uint_32 i;
2587  for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2588  pp = prev_row + 1; i < bpp; i++)
2589  {
2590  *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2591  }
2592 
2593  for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2594  {
2595  int a, b, c, pa, pb, pc, p;
2596 
2597  b = *pp++;
2598  c = *cp++;
2599  a = *lp++;
2600 
2601  p = b - c;
2602  pc = a - c;
2603 
2604 #ifdef PNG_USE_ABS
2605  pa = abs(p);
2606  pb = abs(pc);
2607  pc = abs(p + pc);
2608 #else
2609  pa = p < 0 ? -p : p;
2610  pb = pc < 0 ? -pc : pc;
2611  pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2612 #endif
2613 
2614  p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2615 
2616  *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2617  }
2618  best_row = png_ptr->paeth_row;
2619  }
2620 
2621  else if (filter_to_do & PNG_FILTER_PAETH)
2622  {
2623  png_bytep rp, dp, pp, cp, lp;
2624  png_uint_32 sum = 0, lmins = mins;
2625  png_uint_32 i;
2626  int v;
2627 
2628 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2629  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2630  {
2631  int j;
2632  png_uint_32 lmhi, lmlo;
2633  lmlo = lmins & PNG_LOMASK;
2634  lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2635 
2636  for (j = 0; j < num_p_filters; j++)
2637  {
2638  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
2639  {
2640  lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2641  PNG_WEIGHT_SHIFT;
2642  lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2643  PNG_WEIGHT_SHIFT;
2644  }
2645  }
2646 
2647  lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2648  PNG_COST_SHIFT;
2649  lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2650  PNG_COST_SHIFT;
2651 
2652  if (lmhi > PNG_HIMASK)
2653  lmins = PNG_MAXSUM;
2654  else
2655  lmins = (lmhi << PNG_HISHIFT) + lmlo;
2656  }
2657 #endif
2658 
2659  for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2660  pp = prev_row + 1; i < bpp; i++)
2661  {
2662  v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2663 
2664  sum += (v < 128) ? v : 256 - v;
2665  }
2666 
2667  for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2668  {
2669  int a, b, c, pa, pb, pc, p;
2670 
2671  b = *pp++;
2672  c = *cp++;
2673  a = *lp++;
2674 
2675 #ifndef PNG_SLOW_PAETH
2676  p = b - c;
2677  pc = a - c;
2678 #ifdef PNG_USE_ABS
2679  pa = abs(p);
2680  pb = abs(pc);
2681  pc = abs(p + pc);
2682 #else
2683  pa = p < 0 ? -p : p;
2684  pb = pc < 0 ? -pc : pc;
2685  pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2686 #endif
2687  p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2688 #else /* PNG_SLOW_PAETH */
2689  p = a + b - c;
2690  pa = abs(p - a);
2691  pb = abs(p - b);
2692  pc = abs(p - c);
2693  if (pa <= pb && pa <= pc)
2694  p = a;
2695  else if (pb <= pc)
2696  p = b;
2697  else
2698  p = c;
2699 #endif /* PNG_SLOW_PAETH */
2700 
2701  v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
2702 
2703  sum += (v < 128) ? v : 256 - v;
2704 
2705  if (sum > lmins) /* We are already worse, don't continue. */
2706  break;
2707  }
2708 
2709 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2710  if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2711  {
2712  int j;
2713  png_uint_32 sumhi, sumlo;
2714  sumlo = sum & PNG_LOMASK;
2715  sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2716 
2717  for (j = 0; j < num_p_filters; j++)
2718  {
2719  if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
2720  {
2721  sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2722  PNG_WEIGHT_SHIFT;
2723  sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2724  PNG_WEIGHT_SHIFT;
2725  }
2726  }
2727 
2728  sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2729  PNG_COST_SHIFT;
2730  sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
2731  PNG_COST_SHIFT;
2732 
2733  if (sumhi > PNG_HIMASK)
2734  sum = PNG_MAXSUM;
2735  else
2736  sum = (sumhi << PNG_HISHIFT) + sumlo;
2737  }
2738 #endif
2739 
2740  if (sum < mins)
2741  {
2742  best_row = png_ptr->paeth_row;
2743  }
2744  }
2745 #endif /* PNG_NO_WRITE_FILTER */
2746  /* Do the actual writing of the filtered row data from the chosen filter. */
2747 
2748  png_write_filtered_row(png_ptr, best_row);
2749 
2750 #ifndef PNG_NO_WRITE_FILTER
2751 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
2752  /* Save the type of filter we picked this time for future calculations */
2753  if (png_ptr->num_prev_filters > 0)
2754  {
2755  int j;
2756  for (j = 1; j < num_p_filters; j++)
2757  {
2758  png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
2759  }
2760  png_ptr->prev_filters[j] = best_row[0];
2761  }
2762 #endif
2763 #endif /* PNG_NO_WRITE_FILTER */
2764 }
2765 
2766 
2767 /* Do the actual writing of a previously filtered row. */
2768 void /* PRIVATE */
2770 {
2771  png_debug(1, "in png_write_filtered_row\n");
2772  png_debug1(2, "filter = %d\n", filtered_row[0]);
2773  /* set up the zlib input buffer */
2774 
2775  png_ptr->zstream.next_in = filtered_row;
2776  png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
2777  /* repeat until we have compressed all the data */
2778  do
2779  {
2780  int ret; /* return of zlib */
2781 
2782  /* compress the data */
2783  ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
2784  /* check for compression errors */
2785  if (ret != Z_OK)
2786  {
2787  if (png_ptr->zstream.msg != NULL)
2788  png_error(png_ptr, png_ptr->zstream.msg);
2789  else
2790  png_error(png_ptr, "zlib error");
2791  }
2792 
2793  /* see if it is time to write another IDAT */
2794  if (!(png_ptr->zstream.avail_out))
2795  {
2796  /* write the IDAT and reset the zlib output buffer */
2797  png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
2798  png_ptr->zstream.next_out = png_ptr->zbuf;
2799  png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2800  }
2801  /* repeat until all data has been compressed */
2802  } while (png_ptr->zstream.avail_in);
2803 
2804  /* swap the current and previous rows */
2805  if (png_ptr->prev_row != NULL)
2806  {
2807  png_bytep tptr;
2808 
2809  tptr = png_ptr->prev_row;
2810  png_ptr->prev_row = png_ptr->row_buf;
2811  png_ptr->row_buf = tptr;
2812  }
2813 
2814  /* finish row - updates counters and flushes zlib if last row */
2815  png_write_finish_row(png_ptr);
2816 
2817 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
2818  png_ptr->flush_rows++;
2819 
2820  if (png_ptr->flush_dist > 0 &&
2821  png_ptr->flush_rows >= png_ptr->flush_dist)
2822  {
2823  png_write_flush(png_ptr);
2824  }
2825 #endif
2826 }
2827 #endif /* PNG_WRITE_SUPPORTED */
void png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
Definition: pngwutil.c:1632
png_infop png_charpp int png_charpp profile
Definition: png.h:2382
#define PNG_FILTER_VALUE_AVG
Definition: png.h:1870
void PNGAPI png_write_chunk(png_structp png_ptr, png_bytep chunk_name, png_bytep data, png_size_t length)
Definition: pngwutil.c:80
#define PNG_TEXT_COMPRESSION_LAST
Definition: png.h:666
PNG_tRNS
Definition: png.c:52
png_infop png_charp png_int_32 png_int_32 int int png_charp * units
Definition: png.h:2332
int c
Definition: autoplay.py:16
PNG_CONST int FARDATA png_pass_start[]
Definition: png.c:59
void png_write_start_row(png_structp png_ptr)
Definition: pngwutil.c:1760
void png_zfree(voidpf png_ptr, voidpf ptr)
Definition: png.c:192
Byte FAR * voidpf
Definition: zconf.h:283
#define png_snprintf
Definition: pngconf.h:1448
void png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
Definition: pngwutil.c:1190
#define deflateInit2(strm, level, method, windowBits, memLevel, strategy)
Definition: zlib.h:1335
PNG_PLTE
Definition: png.c:36
#define PNG_FILTER_PAETH
Definition: png.h:1860
png_infop png_charp png_int_32 png_int_32 int * type
Definition: png.h:2332
PNG_sRGB
Definition: png.c:49
#define PNG_FILTER_HEURISTIC_WEIGHTED
Definition: png.h:1915
#define png_strlen
Definition: pngconf.h:1463
png_infop double double double double double double double double * blue_y
Definition: png.h:2252
#define PNG_FILTER_SUB
Definition: png.h:1857
static int png_text_compress(png_structp png_ptr, png_charp text, png_size_t text_len, int compression, compression_state *comp)
Definition: pngwutil.c:167
png_infop double double double double double double double * blue_x
Definition: png.h:2252
#define Z_NO_FLUSH
Definition: zlib.h:162
void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i)
Definition: pngwutil.c:33
#define PNG_INTERLACE_NONE
Definition: png.h:1022
png_color_16 FAR * png_color_16p
Definition: png.h:582
png_infop int * unit
Definition: png.h:2451
#define PNG_COLOR_TYPE_RGB
Definition: png.h:1005
PNG_sPLT
Definition: png.c:48
#define PNG_COLOR_TYPE_GRAY_ALPHA
Definition: png.h:1007
void png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
Definition: pngwutil.c:711
png_byte FAR * png_bytep
Definition: pngconf.h:1197
#define PNG_INTERLACE_ADAM7
Definition: png.h:1023
#define png_memset
Definition: pngconf.h:1466
char FAR * png_charp
Definition: pngconf.h:1203
#define PNG_COLOR_TYPE_PALETTE
Definition: png.h:1004
void png_write_sig(png_structp png_ptr)
Definition: pngwutil.c:59
png_uint_32 size
Definition: png.h:1521
PNG_CONST int FARDATA png_pass_yinc[]
Definition: png.c:68
png_infop png_charp png_int_32 png_int_32 * X1
Definition: png.h:2332
int double double green
Definition: png.h:1628
#define PNG_FILTER_VALUE_PAETH
Definition: png.h:1871
png_infop png_charpp name
Definition: png.h:2382
png_voidp int value
Definition: png.h:2113
RTC::ReturnCode_t ret(RTC::Local::ReturnCode_t r)
png_infop png_charp png_int_32 png_int_32 int int png_charp png_charpp * params
Definition: png.h:2332
#define PNG_MNG_FEATURES_SUPPORTED
Definition: pngconf.h:119
PNG_bKGD
Definition: png.c:37
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition: png.h:1006
#define PNG_HAVE_PLTE
Definition: png.h:2760
long png_int_32
Definition: pngconf.h:1117
void png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
Definition: pngwutil.c:907
PNG_sCAL
Definition: png.c:45
PNG_cHRM
Definition: png.c:38
#define PNG_HIMASK
Definition: pngwutil.c:2148
#define Z_FILTERED
Definition: zlib.h:189
#define PNG_OFFSET_LAST
Definition: png.h:1029
void png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, int unit_type)
Definition: pngwutil.c:1547
PNG_CONST int FARDATA png_pass_ystart[]
Definition: png.c:65
void png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
Definition: pngwutil.c:627
#define Z_STREAM_ERROR
Definition: zlib.h:174
void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
Definition: pngwio.c:29
png_bytep png_bytep png_size_t length
Definition: png.h:1541
png_uint_32 i
Definition: png.h:2735
void png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, png_charp profile, int profile_len)
Definition: pngwutil.c:748
png_infop double double double double * red_y
Definition: png.h:2252
Byte FAR Bytef
Definition: zconf.h:270
long b
Definition: jpegint.h:371
#define PNG_sRGB_INTENT_LAST
Definition: png.h:1054
png_infop png_bytep * trans
Definition: png.h:2435
voidpf png_zalloc(voidpf png_ptr, uInt items, uInt size)
Definition: png.c:149
png_bytep chunk_name
Definition: png.h:1541
png_infop png_charp png_int_32 * X0
Definition: png.h:2332
PNG_zTXt
Definition: png.c:53
png_infop png_uint_32 * width
Definition: png.h:2309
void png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, png_size_t text_len)
Definition: pngwutil.c:1352
void png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, int unit_type)
Definition: pngwutil.c:1705
void png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
Definition: png.c:212
png_infop png_charpp int * compression_type
Definition: png.h:2382
PNG_IDAT
Definition: png.c:34
png_infop png_uint_16p * hist
Definition: png.h:2300
#define PNG_HAVE_IHDR
Definition: png.h:2759
#define PNG_LOMASK
Definition: pngwutil.c:2147
#define Z_FINISH
Definition: zlib.h:166
void png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
Definition: pngwutil.c:823
#define PNG_TEXT_COMPRESSION_NONE
Definition: png.h:662
#define png_debug(l, m)
Definition: png.h:2556
#define PNGAPI
Definition: pngconf.h:1386
png_struct FAR * png_structp
Definition: png.h:1108
void png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, png_fixed_point blue_y)
Definition: pngwutil.c:1025
#define PNG_COLOR_MASK_COLOR
Definition: png.h:999
PNG_pHYs
Definition: png.c:46
PNG_tEXt
Definition: png.c:50
#define PNG_ITXT_COMPRESSION_NONE
Definition: png.h:664
png_time FAR * png_timep
Definition: png.h:683
void PNGAPI png_error(png_structp png_ptr, png_const_charp error_message)
Definition: pngerror.c:36
png_infop png_uint_32 png_uint_32 * height
Definition: png.h:2309
void PNGAPI png_write_flush(png_structp png_ptr)
Definition: pngwrite.c:949
void png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
Definition: pngwutil.c:2150
PNG_sBIT
Definition: png.c:47
PNG_IHDR
Definition: png.c:33
unsigned char png_byte
Definition: pngconf.h:1120
#define png_memcpy
Definition: pngconf.h:1465
unsigned short png_uint_16
Definition: pngconf.h:1118
#define PNG_FILTER_VALUE_SUB
Definition: png.h:1868
void png_write_IHDR(png_structp 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:384
void png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, int num_trans, int color_type)
Definition: pngwutil.c:1081
png_infop png_bytep int * num_trans
Definition: png.h:2435
#define PNG_COLOR_TYPE_GRAY
Definition: png.h:1003
void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
Definition: pngwutil.c:2769
png_sPLT_entry FAR * png_sPLT_entryp
Definition: png.h:608
void PNGAPI png_warning(png_structp png_ptr, png_const_charp warning_message)
Definition: pngerror.c:102
#define PNG_ALL_FILTERS
Definition: png.h:1861
#define Z_STREAM_END
Definition: zlib.h:171
PNG_IEND
Definition: png.c:35
void png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
Definition: pngwutil.c:1569
void png_write_gAMA(png_structp png_ptr, double file_gamma)
Definition: pngwutil.c:694
string a
png_charpp output_ptr
Definition: pngwutil.c:162
png_uint_16 FAR * png_uint_16p
Definition: pngconf.h:1200
png_colorp palette
Definition: png.h:1637
png_bytepp row
Definition: png.h:1759
#define PNG_FILTER_UP
Definition: png.h:1858
#define PNG_HAVE_IDAT
Definition: png.h:2761
#define PNG_FILTER_AVG
Definition: png.h:1859
#define Z_MEM_ERROR
Definition: zlib.h:176
#define PNG_EQUATION_LAST
Definition: png.h:1036
#define PNG_RESOLUTION_LAST
Definition: png.h:1047
#define png_debug1(l, m, p1)
Definition: png.h:2559
png_bytep buf
Definition: png.h:2729
PNG_tIME
Definition: png.c:51
#define Z_BINARY
Definition: zlib.h:196
PNG_gAMA
Definition: png.c:39
#define PNG_FILTER_VALUE_UP
Definition: png.h:1869
int ZEXPORT deflate(z_streamp strm, int flush)
Definition: deflate.c:552
void PNGAPI png_save_uint_32(png_bytep buf, png_uint_32 i)
Definition: pngwutil.c:20
png_infop png_uint_32 png_uint_32 int * bit_depth
Definition: png.h:2309
png_infop double * file_gamma
Definition: png.h:2283
#define PNG_FLAG_MNG_FILTER_64
Definition: png.h:1156
fMat tran(const fMat &mat)
Definition: fMatrix.cpp:1013
static void png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
Definition: pngwutil.c:345
void PNGAPI png_write_chunk_end(png_structp png_ptr)
Definition: pngwutil.c:136
png_infop png_sPLT_tpp entries
Definition: png.h:2396
PNG_hIST
Definition: png.c:40
PNG_iTXt
Definition: png.c:42
#define PNG_FILTER_TYPE_BASE
Definition: png.h:1017
void png_write_tIME(png_structp png_ptr, png_timep mod_time)
Definition: pngwutil.c:1731
typedef int
Definition: png.h:1113
PNG_CONST int FARDATA png_pass_inc[]
Definition: png.c:62
#define PNG_COLOR_MASK_ALPHA
Definition: png.h:1000
#define Z_VERSION_ERROR
Definition: zlib.h:178
png_infop png_charp * purpose
Definition: png.h:2332
void png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
Definition: pngwutil.c:563
#define PNG_COMPRESSION_TYPE_BASE
Definition: png.h:1013
#define png_bytep_NULL
Definition: png.h:501
void png_write_sRGB(png_structp png_ptr, int srgb_intent)
Definition: pngwutil.c:729
#define PNG_HISHIFT
Definition: pngwutil.c:2146
png_infop png_uint_32 png_uint_32 int int * color_type
Definition: png.h:2309
png_infop double double double double double double * green_y
Definition: png.h:2252
png_sPLT_t FAR * png_sPLT_tp
Definition: png.h:623
png_infop double double * white_y
Definition: png.h:2252
void PNGAPI png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
Definition: pngwutil.c:120
png_infop png_charp png_int_32 png_int_32 int int * nparams
Definition: png.h:2332
png_color_8 FAR * png_color_8p
Definition: png.h:593
void png_write_IEND(png_structp png_ptr)
Definition: pngwutil.c:679
png_int_32 png_fixed_point
Definition: pngconf.h:1193
png_infop double double double * red_x
Definition: png.h:2252
char FAR *FAR * png_charpp
Definition: pngconf.h:1225
void png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
Definition: pngwutil.c:1137
#define Z_OK
Definition: zlib.h:170
#define PNG_FILTER_VALUE_NONE
Definition: png.h:1867
size_t png_size_t
Definition: pngconf.h:1128
PNG_pCAL
Definition: png.c:44
png_infop png_int_32 png_int_32 int * unit_type
Definition: png.h:2320
void PNGAPI png_save_uint_16(png_bytep buf, unsigned int i)
Definition: pngwutil.c:46
JSAMPIMAGE data
Definition: jpeglib.h:945
#define PNG_INTRAPIXEL_DIFFERENCING
Definition: png.h:1018
#define PNG_FLAG_MNG_EMPTY_PLTE
Definition: png.h:1155
#define Z_DEFAULT_STRATEGY
Definition: zlib.h:193
png_uint_32 FAR * png_uint_32p
Definition: pngconf.h:1198
int ZEXPORT deflateReset(z_streamp strm)
Definition: deflate.c:357
int double red
Definition: png.h:1628
void png_write_finish_row(png_structp png_ptr)
Definition: pngwutil.c:1860
void PNGAPI png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, png_uint_32 length)
Definition: pngwutil.c:94
png_infop double double double double double * green_x
Definition: png.h:2252
unsigned long png_uint_32
Definition: pngconf.h:1116
PNG_iCCP
Definition: png.c:41
png_row_info FAR * png_row_infop
Definition: png.h:1098
#define PNG_FILTER_NONE
Definition: png.h:1856
void png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, png_size_t text_len, int compression)
Definition: pngwutil.c:1395
#define PNG_MAXSUM
Definition: pngwutil.c:2145
void PNGAPI png_free(png_structp png_ptr, png_voidp ptr)
Definition: pngmem.c:498
#define png_debug2(l, m, p1, p2)
Definition: png.h:2562
png_size_t png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
Definition: pngwutil.c:1231
png_infop double * white_x
Definition: png.h:2252
png_infop png_timep * mod_time
Definition: png.h:2425
void png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
Definition: pngwutil.c:1979
png_voidp PNGAPI png_malloc(png_structp png_ptr, png_uint_32 size)
Definition: pngmem.c:429
PNG_oFFs
Definition: png.c:43
void png_reset_crc(png_structp png_ptr)
Definition: png.c:201
png_voidp PNGAPI png_malloc_warn(png_structp png_ptr, png_uint_32 size)
Definition: pngmem.c:541
#define Z_DEFAULT_COMPRESSION
Definition: zlib.h:186
unsigned int uInt
Definition: zconf.h:263
void png_write_cHRM(png_structp png_ptr, double white_x, double white_y, double red_x, double red_y, double green_x, double green_y, double blue_x, double blue_y)
Definition: pngwutil.c:964
#define PNG_HAVE_IEND
Definition: png.h:2763
#define png_sizeof(x)
Definition: pngconf.h:1129
png_color FAR * png_colorp
Definition: png.h:571


openhrp3
Author(s): AIST, General Robotix Inc., Nakamura Lab of Dept. of Mechano Informatics at University of Tokyo
autogenerated on Thu Sep 8 2022 02:24:05