Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

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