ReactOS 0.4.15-dev-7677-g8209aa5
pngwrite.c
Go to the documentation of this file.
1
2/* pngwrite.c - general routines to write a PNG file
3 *
4 * Copyright (c) 2018-2022 Cosmin Truta
5 * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6 * Copyright (c) 1996-1997 Andreas Dilger
7 * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
8 *
9 * This code is released under the libpng license.
10 * For conditions of distribution and use, see the disclaimer
11 * and license in png.h
12 */
13
14#include "pngpriv.h"
15#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
16# include <errno.h>
17#endif /* SIMPLIFIED_WRITE_STDIO */
18
19#ifdef PNG_WRITE_SUPPORTED
20
21#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
22/* Write out all the unknown chunks for the current given location */
23static void
24write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
25 unsigned int where)
26{
27 if (info_ptr->unknown_chunks_num != 0)
28 {
30
31 png_debug(5, "writing extra chunks");
32
33 for (up = info_ptr->unknown_chunks;
34 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
35 ++up)
36 if ((up->location & where) != 0)
37 {
38 /* If per-chunk unknown chunk handling is enabled use it, otherwise
39 * just write the chunks the application has set.
40 */
41#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
42 int keep = png_handle_as_unknown(png_ptr, up->name);
43
44 /* NOTE: this code is radically different from the read side in the
45 * matter of handling an ancillary unknown chunk. In the read side
46 * the default behavior is to discard it, in the code below the default
47 * behavior is to write it. Critical chunks are, however, only
48 * written if explicitly listed or if the default is set to write all
49 * unknown chunks.
50 *
51 * The default handling is also slightly weird - it is not possible to
52 * stop the writing of all unsafe-to-copy chunks!
53 *
54 * TODO: REVIEW: this would seem to be a bug.
55 */
56 if (keep != PNG_HANDLE_CHUNK_NEVER &&
57 ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
60 png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
61#endif
62 {
63 /* TODO: review, what is wrong with a zero length unknown chunk? */
64 if (up->size == 0)
65 png_warning(png_ptr, "Writing zero-length unknown chunk");
66
67 png_write_chunk(png_ptr, up->name, up->data, up->size);
68 }
69 }
70 }
71}
72#endif /* WRITE_UNKNOWN_CHUNKS */
73
74/* Writes all the PNG information. This is the suggested way to use the
75 * library. If you have a new chunk to add, make a function to write it,
76 * and put it in the correct location here. If you want the chunk written
77 * after the image data, put it in png_write_end(). I strongly encourage
78 * you to supply a PNG_INFO_<chunk> flag, and check info_ptr->valid before
79 * writing the chunk, as that will keep the code from breaking if you want
80 * to just write a plain PNG file. If you have long comments, I suggest
81 * writing them in png_write_end(), and compressing them.
82 */
83void PNGAPI
84png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
85{
86 png_debug(1, "in png_write_info_before_PLTE");
87
88 if (png_ptr == NULL || info_ptr == NULL)
89 return;
90
91 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
92 {
93 /* Write PNG signature */
94 png_write_sig(png_ptr);
95
96#ifdef PNG_MNG_FEATURES_SUPPORTED
97 if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
98 png_ptr->mng_features_permitted != 0)
99 {
100 png_warning(png_ptr,
101 "MNG features are not allowed in a PNG datastream");
102 png_ptr->mng_features_permitted = 0;
103 }
104#endif
105
106 /* Write IHDR information. */
107 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
108 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
109 info_ptr->filter_type,
111 info_ptr->interlace_type
112#else
113 0
114#endif
115 );
116
117 /* The rest of these check to see if the valid field has the appropriate
118 * flag set, and if it does, writes the chunk.
119 *
120 * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
121 * the chunks will be written if the WRITE routine is there and
122 * information * is available in the COLORSPACE. (See
123 * png_colorspace_sync_info in png.c for where the valid flags get set.)
124 *
125 * Under certain circumstances the colorspace can be invalidated without
126 * syncing the info_struct 'valid' flags; this happens if libpng detects
127 * an error and calls png_error while the color space is being set, yet
128 * the application continues writing the PNG. So check the 'invalid'
129 * flag here too.
130 */
131#ifdef PNG_GAMMA_SUPPORTED
132# ifdef PNG_WRITE_gAMA_SUPPORTED
133 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
134 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
135 (info_ptr->valid & PNG_INFO_gAMA) != 0)
136 png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
137# endif
138#endif
139
140#ifdef PNG_COLORSPACE_SUPPORTED
141 /* Write only one of sRGB or an ICC profile. If a profile was supplied
142 * and it matches one of the known sRGB ones issue a warning.
143 */
144# ifdef PNG_WRITE_iCCP_SUPPORTED
145 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
146 (info_ptr->valid & PNG_INFO_iCCP) != 0)
147 {
148# ifdef PNG_WRITE_sRGB_SUPPORTED
149 if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
151 "profile matches sRGB but writing iCCP instead");
152# endif
153
154 png_write_iCCP(png_ptr, info_ptr->iccp_name,
155 info_ptr->iccp_profile);
156 }
157# ifdef PNG_WRITE_sRGB_SUPPORTED
158 else
159# endif
160# endif
161
162# ifdef PNG_WRITE_sRGB_SUPPORTED
163 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
164 (info_ptr->valid & PNG_INFO_sRGB) != 0)
165 png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
166# endif /* WRITE_sRGB */
167#endif /* COLORSPACE */
168
169#ifdef PNG_WRITE_sBIT_SUPPORTED
170 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
171 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
172#endif
173
174#ifdef PNG_COLORSPACE_SUPPORTED
175# ifdef PNG_WRITE_cHRM_SUPPORTED
176 if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
177 (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
178 (info_ptr->valid & PNG_INFO_cHRM) != 0)
179 png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
180# endif
181#endif
182
183#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
184 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
185#endif
186
188 }
189}
190
191void PNGAPI
193{
194#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
195 int i;
196#endif
197
198 png_debug(1, "in png_write_info");
199
200 if (png_ptr == NULL || info_ptr == NULL)
201 return;
202
203 png_write_info_before_PLTE(png_ptr, info_ptr);
204
205 if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
206 png_write_PLTE(png_ptr, info_ptr->palette,
207 (png_uint_32)info_ptr->num_palette);
208
209 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
210 png_error(png_ptr, "Valid palette required for paletted images");
211
212#ifdef PNG_WRITE_tRNS_SUPPORTED
213 if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
214 {
215#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
216 /* Invert the alpha channel (in tRNS) */
217 if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
218 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
219 {
220 int j, jend;
221
222 jend = info_ptr->num_trans;
223 if (jend > PNG_MAX_PALETTE_LENGTH)
225
226 for (j = 0; j<jend; ++j)
227 info_ptr->trans_alpha[j] =
228 (png_byte)(255 - info_ptr->trans_alpha[j]);
229 }
230#endif
231 png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
232 info_ptr->num_trans, info_ptr->color_type);
233 }
234#endif
235#ifdef PNG_WRITE_bKGD_SUPPORTED
236 if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
237 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
238#endif
239
240#ifdef PNG_WRITE_eXIf_SUPPORTED
241 if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
242 png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
243#endif
244
245#ifdef PNG_WRITE_hIST_SUPPORTED
246 if ((info_ptr->valid & PNG_INFO_hIST) != 0)
247 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
248#endif
249
250#ifdef PNG_WRITE_oFFs_SUPPORTED
251 if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
252 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
253 info_ptr->offset_unit_type);
254#endif
255
256#ifdef PNG_WRITE_pCAL_SUPPORTED
257 if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
258 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
259 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
260 info_ptr->pcal_units, info_ptr->pcal_params);
261#endif
262
263#ifdef PNG_WRITE_sCAL_SUPPORTED
264 if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
265 png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
266 info_ptr->scal_s_width, info_ptr->scal_s_height);
267#endif /* sCAL */
268
269#ifdef PNG_WRITE_pHYs_SUPPORTED
270 if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
271 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
272 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
273#endif /* pHYs */
274
275#ifdef PNG_WRITE_tIME_SUPPORTED
276 if ((info_ptr->valid & PNG_INFO_tIME) != 0)
277 {
278 png_write_tIME(png_ptr, &(info_ptr->mod_time));
279 png_ptr->mode |= PNG_WROTE_tIME;
280 }
281#endif /* tIME */
282
283#ifdef PNG_WRITE_sPLT_SUPPORTED
284 if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
285 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
286 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
287#endif /* sPLT */
288
289#ifdef PNG_WRITE_TEXT_SUPPORTED
290 /* Check to see if we need to write text chunks */
291 for (i = 0; i < info_ptr->num_text; i++)
292 {
293 png_debug2(2, "Writing header text chunk %d, type %d", i,
294 info_ptr->text[i].compression);
295 /* An internationalized chunk? */
296 if (info_ptr->text[i].compression > 0)
297 {
298#ifdef PNG_WRITE_iTXt_SUPPORTED
299 /* Write international chunk */
300 png_write_iTXt(png_ptr,
301 info_ptr->text[i].compression,
302 info_ptr->text[i].key,
303 info_ptr->text[i].lang,
304 info_ptr->text[i].lang_key,
305 info_ptr->text[i].text);
306 /* Mark this chunk as written */
307 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
308 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
309 else
310 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
311#else
312 png_warning(png_ptr, "Unable to write international text");
313#endif
314 }
315
316 /* If we want a compressed text chunk */
317 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
318 {
319#ifdef PNG_WRITE_zTXt_SUPPORTED
320 /* Write compressed chunk */
321 png_write_zTXt(png_ptr, info_ptr->text[i].key,
322 info_ptr->text[i].text, info_ptr->text[i].compression);
323 /* Mark this chunk as written */
324 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
325#else
326 png_warning(png_ptr, "Unable to write compressed text");
327#endif
328 }
329
330 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
331 {
332#ifdef PNG_WRITE_tEXt_SUPPORTED
333 /* Write uncompressed chunk */
334 png_write_tEXt(png_ptr, info_ptr->text[i].key,
335 info_ptr->text[i].text,
336 0);
337 /* Mark this chunk as written */
338 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
339#else
340 /* Can't get here */
341 png_warning(png_ptr, "Unable to write uncompressed text");
342#endif
343 }
344 }
345#endif /* tEXt */
346
347#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
348 write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
349#endif
350}
351
352/* Writes the end of the PNG file. If you don't want to write comments or
353 * time information, you can pass NULL for info. If you already wrote these
354 * in png_write_info(), do not write them again here. If you have long
355 * comments, I suggest writing them here, and compressing them.
356 */
357void PNGAPI
359{
360 png_debug(1, "in png_write_end");
361
362 if (png_ptr == NULL)
363 return;
364
365 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
366 png_error(png_ptr, "No IDATs written into file");
367
368#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
369 if (png_ptr->num_palette_max > png_ptr->num_palette)
370 png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
371#endif
372
373 /* See if user wants us to write information chunks */
374 if (info_ptr != NULL)
375 {
376#ifdef PNG_WRITE_TEXT_SUPPORTED
377 int i; /* local index variable */
378#endif
379#ifdef PNG_WRITE_tIME_SUPPORTED
380 /* Check to see if user has supplied a time chunk */
381 if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
382 (png_ptr->mode & PNG_WROTE_tIME) == 0)
383 png_write_tIME(png_ptr, &(info_ptr->mod_time));
384
385#endif
386#ifdef PNG_WRITE_TEXT_SUPPORTED
387 /* Loop through comment chunks */
388 for (i = 0; i < info_ptr->num_text; i++)
389 {
390 png_debug2(2, "Writing trailer text chunk %d, type %d", i,
391 info_ptr->text[i].compression);
392 /* An internationalized chunk? */
393 if (info_ptr->text[i].compression > 0)
394 {
395#ifdef PNG_WRITE_iTXt_SUPPORTED
396 /* Write international chunk */
397 png_write_iTXt(png_ptr,
398 info_ptr->text[i].compression,
399 info_ptr->text[i].key,
400 info_ptr->text[i].lang,
401 info_ptr->text[i].lang_key,
402 info_ptr->text[i].text);
403 /* Mark this chunk as written */
404 if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
405 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
406 else
407 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
408#else
409 png_warning(png_ptr, "Unable to write international text");
410#endif
411 }
412
413 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
414 {
415#ifdef PNG_WRITE_zTXt_SUPPORTED
416 /* Write compressed chunk */
417 png_write_zTXt(png_ptr, info_ptr->text[i].key,
418 info_ptr->text[i].text, info_ptr->text[i].compression);
419 /* Mark this chunk as written */
420 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
421#else
422 png_warning(png_ptr, "Unable to write compressed text");
423#endif
424 }
425
426 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
427 {
428#ifdef PNG_WRITE_tEXt_SUPPORTED
429 /* Write uncompressed chunk */
430 png_write_tEXt(png_ptr, info_ptr->text[i].key,
431 info_ptr->text[i].text, 0);
432 /* Mark this chunk as written */
433 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
434#else
435 png_warning(png_ptr, "Unable to write uncompressed text");
436#endif
437 }
438 }
439#endif
440
441#ifdef PNG_WRITE_eXIf_SUPPORTED
442 if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
443 png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
444#endif
445
446#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
447 write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
448#endif
449 }
450
451 png_ptr->mode |= PNG_AFTER_IDAT;
452
453 /* Write end of PNG file */
454 png_write_IEND(png_ptr);
455
456 /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
457 * and restored again in libpng-1.2.30, may cause some applications that
458 * do not set png_ptr->output_flush_fn to crash. If your application
459 * experiences a problem, please try building libpng with
460 * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
461 * png-mng-implement at lists.sf.net .
462 */
463#ifdef PNG_WRITE_FLUSH_SUPPORTED
464# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
465 png_flush(png_ptr);
466# endif
467#endif
468}
469
470#ifdef PNG_CONVERT_tIME_SUPPORTED
471void PNGAPI
472png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime)
473{
474 png_debug(1, "in png_convert_from_struct_tm");
475
476 ptime->year = (png_uint_16)(1900 + ttime->tm_year);
477 ptime->month = (png_byte)(ttime->tm_mon + 1);
478 ptime->day = (png_byte)ttime->tm_mday;
479 ptime->hour = (png_byte)ttime->tm_hour;
480 ptime->minute = (png_byte)ttime->tm_min;
481 ptime->second = (png_byte)ttime->tm_sec;
482}
483
484void PNGAPI
485png_convert_from_time_t(png_timep ptime, time_t ttime)
486{
487 struct tm *tbuf;
488
489 png_debug(1, "in png_convert_from_time_t");
490
491 tbuf = gmtime(&ttime);
492 if (tbuf == NULL)
493 {
494 /* TODO: add a safe function which takes a png_ptr argument and raises
495 * a png_error if the ttime argument is invalid and the call to gmtime
496 * fails as a consequence.
497 */
498 memset(ptime, 0, sizeof(*ptime));
499 return;
500 }
501
502 png_convert_from_struct_tm(ptime, tbuf);
503}
504#endif
505
506/* Initialize png_ptr structure, and allocate any memory needed */
508png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
509 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
510{
511#ifndef PNG_USER_MEM_SUPPORTED
512 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
513 error_fn, warn_fn, NULL, NULL, NULL);
514#else
515 return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
516 warn_fn, NULL, NULL, NULL);
517}
518
519/* Alternate initialize png_ptr structure, and allocate any memory needed */
521png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
522 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
523 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
524{
525 png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
526 error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
527#endif /* USER_MEM */
528 if (png_ptr != NULL)
529 {
530 /* Set the zlib control values to defaults; they can be overridden by the
531 * application after the struct has been created.
532 */
533 png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
534
535 /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
536 * pngwutil.c defaults it according to whether or not filters will be
537 * used, and ignores this setting.
538 */
539 png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
541 png_ptr->zlib_mem_level = 8;
542 png_ptr->zlib_window_bits = 15;
543 png_ptr->zlib_method = 8;
544
545#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
546 png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
547 png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
548 png_ptr->zlib_text_mem_level = 8;
549 png_ptr->zlib_text_window_bits = 15;
550 png_ptr->zlib_text_method = 8;
551#endif /* WRITE_COMPRESSED_TEXT */
552
553 /* This is a highly dubious configuration option; by default it is off,
554 * but it may be appropriate for private builds that are testing
555 * extensions not conformant to the current specification, or of
556 * applications that must not fail to write at all costs!
557 */
558#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
559 /* In stable builds only warn if an application error can be completely
560 * handled.
561 */
563#endif
564
565 /* App warnings are warnings in release (or release candidate) builds but
566 * are errors during development.
567 */
568#if PNG_RELEASE_BUILD
570#endif
571
572 /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
573 * do it itself) avoiding setting the default function if it is not
574 * required.
575 */
576 png_set_write_fn(png_ptr, NULL, NULL, NULL);
577 }
578
579 return png_ptr;
580}
581
582
583/* Write a few rows of image data. If the image is interlaced,
584 * either you will have to write the 7 sub images, or, if you
585 * have called png_set_interlace_handling(), you will have to
586 * "write" the image seven times.
587 */
588void PNGAPI
589png_write_rows(png_structrp png_ptr, png_bytepp row,
591{
592 png_uint_32 i; /* row counter */
593 png_bytepp rp; /* row pointer */
594
595 png_debug(1, "in png_write_rows");
596
597 if (png_ptr == NULL)
598 return;
599
600 /* Loop through the rows */
601 for (i = 0, rp = row; i < num_rows; i++, rp++)
602 {
603 png_write_row(png_ptr, *rp);
604 }
605}
606
607/* Write the image. You only need to call this function once, even
608 * if you are writing an interlaced image.
609 */
610void PNGAPI
611png_write_image(png_structrp png_ptr, png_bytepp image)
612{
613 png_uint_32 i; /* row index */
614 int pass, num_pass; /* pass variables */
615 png_bytepp rp; /* points to current row */
616
617 if (png_ptr == NULL)
618 return;
619
620 png_debug(1, "in png_write_image");
621
622#ifdef PNG_WRITE_INTERLACING_SUPPORTED
623 /* Initialize interlace handling. If image is not interlaced,
624 * this will set pass to 1
625 */
626 num_pass = png_set_interlace_handling(png_ptr);
627#else
628 num_pass = 1;
629#endif
630 /* Loop through passes */
631 for (pass = 0; pass < num_pass; pass++)
632 {
633 /* Loop through image */
634 for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
635 {
636 png_write_row(png_ptr, *rp);
637 }
638 }
639}
640
641#ifdef PNG_MNG_FEATURES_SUPPORTED
642/* Performs intrapixel differencing */
643static void
644png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
645{
646 png_debug(1, "in png_do_write_intrapixel");
647
648 if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
649 {
650 int bytes_per_pixel;
651 png_uint_32 row_width = row_info->width;
652 if (row_info->bit_depth == 8)
653 {
654 png_bytep rp;
656
657 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
658 bytes_per_pixel = 3;
659
660 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
661 bytes_per_pixel = 4;
662
663 else
664 return;
665
666 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
667 {
668 *(rp) = (png_byte)(*rp - *(rp + 1));
669 *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
670 }
671 }
672
673#ifdef PNG_WRITE_16BIT_SUPPORTED
674 else if (row_info->bit_depth == 16)
675 {
676 png_bytep rp;
678
679 if (row_info->color_type == PNG_COLOR_TYPE_RGB)
680 bytes_per_pixel = 6;
681
682 else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
683 bytes_per_pixel = 8;
684
685 else
686 return;
687
688 for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
689 {
690 png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);
691 png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
692 png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
693 png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
694 png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
695 *(rp ) = (png_byte)(red >> 8);
696 *(rp + 1) = (png_byte)red;
697 *(rp + 4) = (png_byte)(blue >> 8);
698 *(rp + 5) = (png_byte)blue;
699 }
700 }
701#endif /* WRITE_16BIT */
702 }
703}
704#endif /* MNG_FEATURES */
705
706/* Called by user to write a row of image data */
707void PNGAPI
709{
710 /* 1.5.6: moved from png_struct to be a local structure: */
711 png_row_info row_info;
712
713 if (png_ptr == NULL)
714 return;
715
716 png_debug2(1, "in png_write_row (row %u, pass %d)",
717 png_ptr->row_number, png_ptr->pass);
718
719 /* Initialize transformations and other stuff if first time */
720 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
721 {
722 /* Make sure we wrote the header info */
723 if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
724 png_error(png_ptr,
725 "png_write_info was never called before png_write_row");
726
727 /* Check for transforms that have been set but were defined out */
728#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
729 if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
730 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
731#endif
732
733#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
734 if ((png_ptr->transformations & PNG_FILLER) != 0)
735 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
736#endif
737#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
738 defined(PNG_READ_PACKSWAP_SUPPORTED)
739 if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
740 png_warning(png_ptr,
741 "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
742#endif
743
744#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
745 if ((png_ptr->transformations & PNG_PACK) != 0)
746 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
747#endif
748
749#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
750 if ((png_ptr->transformations & PNG_SHIFT) != 0)
751 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
752#endif
753
754#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
755 if ((png_ptr->transformations & PNG_BGR) != 0)
756 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
757#endif
758
759#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
760 if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
761 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
762#endif
763
764 png_write_start_row(png_ptr);
765 }
766
767#ifdef PNG_WRITE_INTERLACING_SUPPORTED
768 /* If interlaced and not interested in row, return */
769 if (png_ptr->interlaced != 0 &&
770 (png_ptr->transformations & PNG_INTERLACE) != 0)
771 {
772 switch (png_ptr->pass)
773 {
774 case 0:
775 if ((png_ptr->row_number & 0x07) != 0)
776 {
777 png_write_finish_row(png_ptr);
778 return;
779 }
780 break;
781
782 case 1:
783 if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
784 {
785 png_write_finish_row(png_ptr);
786 return;
787 }
788 break;
789
790 case 2:
791 if ((png_ptr->row_number & 0x07) != 4)
792 {
793 png_write_finish_row(png_ptr);
794 return;
795 }
796 break;
797
798 case 3:
799 if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
800 {
801 png_write_finish_row(png_ptr);
802 return;
803 }
804 break;
805
806 case 4:
807 if ((png_ptr->row_number & 0x03) != 2)
808 {
809 png_write_finish_row(png_ptr);
810 return;
811 }
812 break;
813
814 case 5:
815 if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
816 {
817 png_write_finish_row(png_ptr);
818 return;
819 }
820 break;
821
822 case 6:
823 if ((png_ptr->row_number & 0x01) == 0)
824 {
825 png_write_finish_row(png_ptr);
826 return;
827 }
828 break;
829
830 default: /* error: ignore it */
831 break;
832 }
833 }
834#endif
835
836 /* Set up row info for transformations */
837 row_info.color_type = png_ptr->color_type;
838 row_info.width = png_ptr->usr_width;
839 row_info.channels = png_ptr->usr_channels;
840 row_info.bit_depth = png_ptr->usr_bit_depth;
841 row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
842 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
843
844 png_debug1(3, "row_info->color_type = %d", row_info.color_type);
845 png_debug1(3, "row_info->width = %u", row_info.width);
846 png_debug1(3, "row_info->channels = %d", row_info.channels);
847 png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
848 png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
849 png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
850
851 /* Copy user's row into buffer, leaving room for filter byte. */
852 memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
853
854#ifdef PNG_WRITE_INTERLACING_SUPPORTED
855 /* Handle interlacing */
856 if (png_ptr->interlaced && png_ptr->pass < 6 &&
857 (png_ptr->transformations & PNG_INTERLACE) != 0)
858 {
859 png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
860 /* This should always get caught above, but still ... */
861 if (row_info.width == 0)
862 {
863 png_write_finish_row(png_ptr);
864 return;
865 }
866 }
867#endif
868
869#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
870 /* Handle other transformations */
871 if (png_ptr->transformations != 0)
872 png_do_write_transformations(png_ptr, &row_info);
873#endif
874
875 /* At this point the row_info pixel depth must match the 'transformed' depth,
876 * which is also the output depth.
877 */
878 if (row_info.pixel_depth != png_ptr->pixel_depth ||
879 row_info.pixel_depth != png_ptr->transformed_pixel_depth)
880 png_error(png_ptr, "internal write transform logic error");
881
882#ifdef PNG_MNG_FEATURES_SUPPORTED
883 /* Write filter_method 64 (intrapixel differencing) only if
884 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
885 * 2. Libpng did not write a PNG signature (this filter_method is only
886 * used in PNG datastreams that are embedded in MNG datastreams) and
887 * 3. The application called png_permit_mng_features with a mask that
888 * included PNG_FLAG_MNG_FILTER_64 and
889 * 4. The filter_method is 64 and
890 * 5. The color_type is RGB or RGBA
891 */
892 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
893 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
894 {
895 /* Intrapixel differencing */
896 png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
897 }
898#endif
899
900/* Added at libpng-1.5.10 */
901#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
902 /* Check for out-of-range palette index */
903 if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
904 png_ptr->num_palette_max >= 0)
905 png_do_check_palette_indexes(png_ptr, &row_info);
906#endif
907
908 /* Find a filter if necessary, filter the row and write it out. */
909 png_write_find_filter(png_ptr, &row_info);
910
911 if (png_ptr->write_row_fn != NULL)
912 (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
913}
914
915#ifdef PNG_WRITE_FLUSH_SUPPORTED
916/* Set the automatic flush interval or 0 to turn flushing off */
917void PNGAPI
918png_set_flush(png_structrp png_ptr, int nrows)
919{
920 png_debug(1, "in png_set_flush");
921
922 if (png_ptr == NULL)
923 return;
924
925 png_ptr->flush_dist = (nrows < 0 ? 0 : (png_uint_32)nrows);
926}
927
928/* Flush the current output buffers now */
929void PNGAPI
930png_write_flush(png_structrp png_ptr)
931{
932 png_debug(1, "in png_write_flush");
933
934 if (png_ptr == NULL)
935 return;
936
937 /* We have already written out all of the data */
938 if (png_ptr->row_number >= png_ptr->num_rows)
939 return;
940
941 png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
942 png_ptr->flush_rows = 0;
943 png_flush(png_ptr);
944}
945#endif /* WRITE_FLUSH */
946
947/* Free any memory used in png_ptr struct without freeing the struct itself. */
948static void
949png_write_destroy(png_structrp png_ptr)
950{
951 png_debug(1, "in png_write_destroy");
952
953 /* Free any memory zlib uses */
954 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
955 deflateEnd(&png_ptr->zstream);
956
957 /* Free our memory. png_free checks NULL for us. */
958 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
959 png_free(png_ptr, png_ptr->row_buf);
960 png_ptr->row_buf = NULL;
961#ifdef PNG_WRITE_FILTER_SUPPORTED
962 png_free(png_ptr, png_ptr->prev_row);
963 png_free(png_ptr, png_ptr->try_row);
964 png_free(png_ptr, png_ptr->tst_row);
965 png_ptr->prev_row = NULL;
966 png_ptr->try_row = NULL;
967 png_ptr->tst_row = NULL;
968#endif
969
970#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
971 png_free(png_ptr, png_ptr->chunk_list);
972 png_ptr->chunk_list = NULL;
973#endif
974
975 /* The error handling and memory handling information is left intact at this
976 * point: the jmp_buf may still have to be freed. See png_destroy_png_struct
977 * for how this happens.
978 */
979}
980
981/* Free all memory used by the write.
982 * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
983 * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
984 * the passed in info_structs but it would quietly fail to free any of the data
985 * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
986 * has no png_ptr.)
987 */
988void PNGAPI
989png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
990{
991 png_debug(1, "in png_destroy_write_struct");
992
993 if (png_ptr_ptr != NULL)
994 {
995 png_structrp png_ptr = *png_ptr_ptr;
996
997 if (png_ptr != NULL) /* added in libpng 1.6.0 */
998 {
999 png_destroy_info_struct(png_ptr, info_ptr_ptr);
1000
1001 *png_ptr_ptr = NULL;
1002 png_write_destroy(png_ptr);
1003 png_destroy_png_struct(png_ptr);
1004 }
1005 }
1006}
1007
1008/* Allow the application to select one or more row filters to use. */
1009void PNGAPI
1010png_set_filter(png_structrp png_ptr, int method, int filters)
1011{
1012 png_debug(1, "in png_set_filter");
1013
1014 if (png_ptr == NULL)
1015 return;
1016
1017#ifdef PNG_MNG_FEATURES_SUPPORTED
1018 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
1021
1022#endif
1024 {
1025 switch (filters & (PNG_ALL_FILTERS | 0x07))
1026 {
1027#ifdef PNG_WRITE_FILTER_SUPPORTED
1028 case 5:
1029 case 6:
1030 case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
1031#endif /* WRITE_FILTER */
1032 /* FALLTHROUGH */
1034 png_ptr->do_filter = PNG_FILTER_NONE; break;
1035
1036#ifdef PNG_WRITE_FILTER_SUPPORTED
1038 png_ptr->do_filter = PNG_FILTER_SUB; break;
1039
1041 png_ptr->do_filter = PNG_FILTER_UP; break;
1042
1044 png_ptr->do_filter = PNG_FILTER_AVG; break;
1045
1047 png_ptr->do_filter = PNG_FILTER_PAETH; break;
1048
1049 default:
1050 png_ptr->do_filter = (png_byte)filters; break;
1051#else
1052 default:
1053 png_app_error(png_ptr, "Unknown row filter for method 0");
1054#endif /* WRITE_FILTER */
1055 }
1056
1057#ifdef PNG_WRITE_FILTER_SUPPORTED
1058 /* If we have allocated the row_buf, this means we have already started
1059 * with the image and we should have allocated all of the filter buffers
1060 * that have been selected. If prev_row isn't already allocated, then
1061 * it is too late to start using the filters that need it, since we
1062 * will be missing the data in the previous row. If an application
1063 * wants to start and stop using particular filters during compression,
1064 * it should start out with all of the filters, and then remove them
1065 * or add them back after the start of compression.
1066 *
1067 * NOTE: this is a nasty constraint on the code, because it means that the
1068 * prev_row buffer must be maintained even if there are currently no
1069 * 'prev_row' requiring filters active.
1070 */
1071 if (png_ptr->row_buf != NULL)
1072 {
1073 int num_filters;
1074 png_alloc_size_t buf_size;
1075
1076 /* Repeat the checks in png_write_start_row; 1 pixel high or wide
1077 * images cannot benefit from certain filters. If this isn't done here
1078 * the check below will fire on 1 pixel high images.
1079 */
1080 if (png_ptr->height == 1)
1082
1083 if (png_ptr->width == 1)
1085
1086 if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0
1087 && png_ptr->prev_row == NULL)
1088 {
1089 /* This is the error case, however it is benign - the previous row
1090 * is not available so the filter can't be used. Just warn here.
1091 */
1093 "png_set_filter: UP/AVG/PAETH cannot be added after start");
1095 }
1096
1097 num_filters = 0;
1098
1099 if (filters & PNG_FILTER_SUB)
1100 num_filters++;
1101
1102 if (filters & PNG_FILTER_UP)
1103 num_filters++;
1104
1105 if (filters & PNG_FILTER_AVG)
1106 num_filters++;
1107
1108 if (filters & PNG_FILTER_PAETH)
1109 num_filters++;
1110
1111 /* Allocate needed row buffers if they have not already been
1112 * allocated.
1113 */
1114 buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth,
1115 png_ptr->width) + 1;
1116
1117 if (png_ptr->try_row == NULL)
1118 png_ptr->try_row = png_voidcast(png_bytep,
1119 png_malloc(png_ptr, buf_size));
1120
1121 if (num_filters > 1)
1122 {
1123 if (png_ptr->tst_row == NULL)
1124 png_ptr->tst_row = png_voidcast(png_bytep,
1125 png_malloc(png_ptr, buf_size));
1126 }
1127 }
1128 png_ptr->do_filter = (png_byte)filters;
1129#endif
1130 }
1131 else
1132 png_error(png_ptr, "Unknown custom filter method");
1133}
1134
1135#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
1136/* Provide floating and fixed point APIs */
1137#ifdef PNG_FLOATING_POINT_SUPPORTED
1138void PNGAPI
1139png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
1141 png_const_doublep filter_costs)
1142{
1147 PNG_UNUSED(filter_costs)
1148}
1149#endif /* FLOATING_POINT */
1150
1151#ifdef PNG_FIXED_POINT_SUPPORTED
1152void PNGAPI
1155 png_const_fixed_point_p filter_costs)
1156{
1161 PNG_UNUSED(filter_costs)
1162}
1163#endif /* FIXED_POINT */
1164#endif /* WRITE_WEIGHTED_FILTER */
1165
1166#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
1167void PNGAPI
1168png_set_compression_level(png_structrp png_ptr, int level)
1169{
1170 png_debug(1, "in png_set_compression_level");
1171
1172 if (png_ptr == NULL)
1173 return;
1174
1175 png_ptr->zlib_level = level;
1176}
1177
1178void PNGAPI
1179png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
1180{
1181 png_debug(1, "in png_set_compression_mem_level");
1182
1183 if (png_ptr == NULL)
1184 return;
1185
1186 png_ptr->zlib_mem_level = mem_level;
1187}
1188
1189void PNGAPI
1190png_set_compression_strategy(png_structrp png_ptr, int strategy)
1191{
1192 png_debug(1, "in png_set_compression_strategy");
1193
1194 if (png_ptr == NULL)
1195 return;
1196
1197 /* The flag setting here prevents the libpng dynamic selection of strategy.
1198 */
1200 png_ptr->zlib_strategy = strategy;
1201}
1202
1203/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1204 * smaller value of window_bits if it can do so safely.
1205 */
1206void PNGAPI
1207png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
1208{
1209 if (png_ptr == NULL)
1210 return;
1211
1212 /* Prior to 1.6.0 this would warn but then set the window_bits value. This
1213 * meant that negative window bits values could be selected that would cause
1214 * libpng to write a non-standard PNG file with raw deflate or gzip
1215 * compressed IDAT or ancillary chunks. Such files can be read and there is
1216 * no warning on read, so this seems like a very bad idea.
1217 */
1218 if (window_bits > 15)
1219 {
1220 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1221 window_bits = 15;
1222 }
1223
1224 else if (window_bits < 8)
1225 {
1226 png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
1227 window_bits = 8;
1228 }
1229
1230 png_ptr->zlib_window_bits = window_bits;
1231}
1232
1233void PNGAPI
1234png_set_compression_method(png_structrp png_ptr, int method)
1235{
1236 png_debug(1, "in png_set_compression_method");
1237
1238 if (png_ptr == NULL)
1239 return;
1240
1241 /* This would produce an invalid PNG file if it worked, but it doesn't and
1242 * deflate will fault it, so it is harmless to just warn here.
1243 */
1244 if (method != 8)
1245 png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1246
1247 png_ptr->zlib_method = method;
1248}
1249#endif /* WRITE_CUSTOMIZE_COMPRESSION */
1250
1251/* The following were added to libpng-1.5.4 */
1252#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
1253void PNGAPI
1254png_set_text_compression_level(png_structrp png_ptr, int level)
1255{
1256 png_debug(1, "in png_set_text_compression_level");
1257
1258 if (png_ptr == NULL)
1259 return;
1260
1261 png_ptr->zlib_text_level = level;
1262}
1263
1264void PNGAPI
1265png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
1266{
1267 png_debug(1, "in png_set_text_compression_mem_level");
1268
1269 if (png_ptr == NULL)
1270 return;
1271
1272 png_ptr->zlib_text_mem_level = mem_level;
1273}
1274
1275void PNGAPI
1276png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
1277{
1278 png_debug(1, "in png_set_text_compression_strategy");
1279
1280 if (png_ptr == NULL)
1281 return;
1282
1283 png_ptr->zlib_text_strategy = strategy;
1284}
1285
1286/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
1287 * smaller value of window_bits if it can do so safely.
1288 */
1289void PNGAPI
1290png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
1291{
1292 if (png_ptr == NULL)
1293 return;
1294
1295 if (window_bits > 15)
1296 {
1297 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
1298 window_bits = 15;
1299 }
1300
1301 else if (window_bits < 8)
1302 {
1303 png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
1304 window_bits = 8;
1305 }
1306
1307 png_ptr->zlib_text_window_bits = window_bits;
1308}
1309
1310void PNGAPI
1311png_set_text_compression_method(png_structrp png_ptr, int method)
1312{
1313 png_debug(1, "in png_set_text_compression_method");
1314
1315 if (png_ptr == NULL)
1316 return;
1317
1318 if (method != 8)
1319 png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1320
1321 png_ptr->zlib_text_method = method;
1322}
1323#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
1324/* end of API added to libpng-1.5.4 */
1325
1326void PNGAPI
1327png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
1328{
1329 if (png_ptr == NULL)
1330 return;
1331
1332 png_ptr->write_row_fn = write_row_fn;
1333}
1334
1335#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
1336void PNGAPI
1337png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
1338 write_user_transform_fn)
1339{
1340 png_debug(1, "in png_set_write_user_transform_fn");
1341
1342 if (png_ptr == NULL)
1343 return;
1344
1345 png_ptr->transformations |= PNG_USER_TRANSFORM;
1346 png_ptr->write_user_transform_fn = write_user_transform_fn;
1347}
1348#endif
1349
1350
1351#ifdef PNG_INFO_IMAGE_SUPPORTED
1352void PNGAPI
1354 int transforms, voidp params)
1355{
1356 if (png_ptr == NULL || info_ptr == NULL)
1357 return;
1358
1359 if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
1360 {
1361 png_app_error(png_ptr, "no rows for png_write_image to write");
1362 return;
1363 }
1364
1365 /* Write the file header information. */
1366 png_write_info(png_ptr, info_ptr);
1367
1368 /* ------ these transformations don't touch the info structure ------- */
1369
1370 /* Invert monochrome pixels */
1371 if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
1372#ifdef PNG_WRITE_INVERT_SUPPORTED
1373 png_set_invert_mono(png_ptr);
1374#else
1375 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
1376#endif
1377
1378 /* Shift the pixels up to a legal bit depth and fill in
1379 * as appropriate to correctly scale the image.
1380 */
1381 if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
1382#ifdef PNG_WRITE_SHIFT_SUPPORTED
1383 if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
1384 png_set_shift(png_ptr, &info_ptr->sig_bit);
1385#else
1386 png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
1387#endif
1388
1389 /* Pack pixels into bytes */
1390 if ((transforms & PNG_TRANSFORM_PACKING) != 0)
1391#ifdef PNG_WRITE_PACK_SUPPORTED
1392 png_set_packing(png_ptr);
1393#else
1394 png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
1395#endif
1396
1397 /* Swap location of alpha bytes from ARGB to RGBA */
1398 if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
1399#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
1400 png_set_swap_alpha(png_ptr);
1401#else
1402 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
1403#endif
1404
1405 /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
1406 * RGB, note that the code expects the input color type to be G or RGB; no
1407 * alpha channel.
1408 */
1409 if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
1411 {
1412#ifdef PNG_WRITE_FILLER_SUPPORTED
1413 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
1414 {
1415 if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1417 "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
1418
1419 /* Continue if ignored - this is the pre-1.6.10 behavior */
1420 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1421 }
1422
1423 else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
1424 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1425#else
1426 png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
1427#endif
1428 }
1429
1430 /* Flip BGR pixels to RGB */
1431 if ((transforms & PNG_TRANSFORM_BGR) != 0)
1432#ifdef PNG_WRITE_BGR_SUPPORTED
1433 png_set_bgr(png_ptr);
1434#else
1435 png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
1436#endif
1437
1438 /* Swap bytes of 16-bit files to most significant byte first */
1439 if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
1440#ifdef PNG_WRITE_SWAP_SUPPORTED
1441 png_set_swap(png_ptr);
1442#else
1443 png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
1444#endif
1445
1446 /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
1447 if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
1448#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
1449 png_set_packswap(png_ptr);
1450#else
1451 png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
1452#endif
1453
1454 /* Invert the alpha channel from opacity to transparency */
1455 if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
1456#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1457 png_set_invert_alpha(png_ptr);
1458#else
1459 png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
1460#endif
1461
1462 /* ----------------------- end of transformations ------------------- */
1463
1464 /* Write the bits */
1465 png_write_image(png_ptr, info_ptr->row_pointers);
1466
1467 /* It is REQUIRED to call this to finish writing the rest of the file */
1468 png_write_end(png_ptr, info_ptr);
1469
1471}
1472#endif
1473
1474
1475#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
1476/* Initialize the write structure - general purpose utility. */
1477static int
1478png_image_write_init(png_imagep image)
1479{
1480 png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
1481 png_safe_error, png_safe_warning);
1482
1483 if (png_ptr != NULL)
1484 {
1485 png_infop info_ptr = png_create_info_struct(png_ptr);
1486
1487 if (info_ptr != NULL)
1488 {
1490 png_malloc_warn(png_ptr, (sizeof *control)));
1491
1492 if (control != NULL)
1493 {
1494 memset(control, 0, (sizeof *control));
1495
1496 control->png_ptr = png_ptr;
1497 control->info_ptr = info_ptr;
1498 control->for_write = 1;
1499
1500 image->opaque = control;
1501 return 1;
1502 }
1503
1504 /* Error clean up */
1505 png_destroy_info_struct(png_ptr, &info_ptr);
1506 }
1507
1508 png_destroy_write_struct(&png_ptr, NULL);
1509 }
1510
1511 return png_image_error(image, "png_image_write_: out of memory");
1512}
1513
1514/* Arguments to png_image_write_main: */
1515typedef struct
1516{
1517 /* Arguments: */
1520 png_int_32 row_stride;
1521 png_const_voidp colormap;
1522 int convert_to_8bit;
1523 /* Local variables: */
1524 png_const_voidp first_row;
1525 ptrdiff_t row_bytes;
1526 png_voidp local_row;
1527 /* Byte count for memory writing */
1529 png_alloc_size_t memory_bytes; /* not used for STDIO */
1530 png_alloc_size_t output_bytes; /* running total */
1531} png_image_write_control;
1532
1533/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
1534 * do any necessary byte swapping. The component order is defined by the
1535 * png_image format value.
1536 */
1537static int
1538png_write_image_16bit(png_voidp argument)
1539{
1540 png_image_write_control *display = png_voidcast(png_image_write_control*,
1541 argument);
1542 png_imagep image = display->image;
1543 png_structrp png_ptr = image->opaque->png_ptr;
1544
1546 display->first_row);
1548 png_uint_16p row_end;
1549 unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
1550 3 : 1;
1551 int aindex = 0;
1552 png_uint_32 y = image->height;
1553
1554 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1555 {
1556# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1557 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1558 {
1559 aindex = -1;
1560 ++input_row; /* To point to the first component */
1561 ++output_row;
1562 }
1563 else
1564 aindex = (int)channels;
1565# else
1566 aindex = (int)channels;
1567# endif
1568 }
1569
1570 else
1571 png_error(png_ptr, "png_write_image: internal call error");
1572
1573 /* Work out the output row end and count over this, note that the increment
1574 * above to 'row' means that row_end can actually be beyond the end of the
1575 * row; this is correct.
1576 */
1577 row_end = output_row + image->width * (channels+1);
1578
1579 for (; y > 0; --y)
1580 {
1581 png_const_uint_16p in_ptr = input_row;
1582 png_uint_16p out_ptr = output_row;
1583
1584 while (out_ptr < row_end)
1585 {
1586 png_uint_16 alpha = in_ptr[aindex];
1587 png_uint_32 reciprocal = 0;
1588 int c;
1589
1590 out_ptr[aindex] = alpha;
1591
1592 /* Calculate a reciprocal. The correct calculation is simply
1593 * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
1594 * allows correct rounding by adding .5 before the shift. 'reciprocal'
1595 * is only initialized when required.
1596 */
1597 if (alpha > 0 && alpha < 65535)
1598 reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
1599
1600 c = (int)channels;
1601 do /* always at least one channel */
1602 {
1603 png_uint_16 component = *in_ptr++;
1604
1605 /* The following gives 65535 for an alpha of 0, which is fine,
1606 * otherwise if 0/0 is represented as some other value there is more
1607 * likely to be a discontinuity which will probably damage
1608 * compression when moving from a fully transparent area to a
1609 * nearly transparent one. (The assumption here is that opaque
1610 * areas tend not to be 0 intensity.)
1611 */
1612 if (component >= alpha)
1613 component = 65535;
1614
1615 /* component<alpha, so component/alpha is less than one and
1616 * component*reciprocal is less than 2^31.
1617 */
1618 else if (component > 0 && alpha < 65535)
1619 {
1620 png_uint_32 calc = component * reciprocal;
1621 calc += 16384; /* round to nearest */
1622 component = (png_uint_16)(calc >> 15);
1623 }
1624
1625 *out_ptr++ = component;
1626 }
1627 while (--c > 0);
1628
1629 /* Skip to next component (skip the intervening alpha channel) */
1630 ++in_ptr;
1631 ++out_ptr;
1632 }
1633
1634 png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
1635 input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
1636 }
1637
1638 return 1;
1639}
1640
1641/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
1642 * is present it must be removed from the components, the components are then
1643 * written in sRGB encoding. No components are added or removed.
1644 *
1645 * Calculate an alpha reciprocal to reverse pre-multiplication. As above the
1646 * calculation can be done to 15 bits of accuracy; however, the output needs to
1647 * be scaled in the range 0..255*65535, so include that scaling here.
1648 */
1649# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha))
1650
1651static png_byte
1652png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
1653 png_uint_32 reciprocal/*from the above macro*/)
1654{
1655 /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
1656 * is represented as some other value there is more likely to be a
1657 * discontinuity which will probably damage compression when moving from a
1658 * fully transparent area to a nearly transparent one. (The assumption here
1659 * is that opaque areas tend not to be 0 intensity.)
1660 *
1661 * There is a rounding problem here; if alpha is less than 128 it will end up
1662 * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
1663 * output change for this too.
1664 */
1665 if (component >= alpha || alpha < 128)
1666 return 255;
1667
1668 /* component<alpha, so component/alpha is less than one and
1669 * component*reciprocal is less than 2^31.
1670 */
1671 else if (component > 0)
1672 {
1673 /* The test is that alpha/257 (rounded) is less than 255, the first value
1674 * that becomes 255 is 65407.
1675 * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
1676 * be exact!) [Could also test reciprocal != 0]
1677 */
1678 if (alpha < 65407)
1679 {
1680 component *= reciprocal;
1681 component += 64; /* round to nearest */
1682 component >>= 7;
1683 }
1684
1685 else
1686 component *= 255;
1687
1688 /* Convert the component to sRGB. */
1689 return (png_byte)PNG_sRGB_FROM_LINEAR(component);
1690 }
1691
1692 else
1693 return 0;
1694}
1695
1696static int
1697png_write_image_8bit(png_voidp argument)
1698{
1699 png_image_write_control *display = png_voidcast(png_image_write_control*,
1700 argument);
1701 png_imagep image = display->image;
1702 png_structrp png_ptr = image->opaque->png_ptr;
1703
1705 display->first_row);
1707 png_uint_32 y = image->height;
1708 unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
1709 3 : 1;
1710
1711 if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
1712 {
1713 png_bytep row_end;
1714 int aindex;
1715
1716# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
1717 if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
1718 {
1719 aindex = -1;
1720 ++input_row; /* To point to the first component */
1721 ++output_row;
1722 }
1723
1724 else
1725# endif
1726 aindex = (int)channels;
1727
1728 /* Use row_end in place of a loop counter: */
1729 row_end = output_row + image->width * (channels+1);
1730
1731 for (; y > 0; --y)
1732 {
1733 png_const_uint_16p in_ptr = input_row;
1734 png_bytep out_ptr = output_row;
1735
1736 while (out_ptr < row_end)
1737 {
1738 png_uint_16 alpha = in_ptr[aindex];
1739 png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
1740 png_uint_32 reciprocal = 0;
1741 int c;
1742
1743 /* Scale and write the alpha channel. */
1744 out_ptr[aindex] = alphabyte;
1745
1746 if (alphabyte > 0 && alphabyte < 255)
1747 reciprocal = UNP_RECIPROCAL(alpha);
1748
1749 c = (int)channels;
1750 do /* always at least one channel */
1751 *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
1752 while (--c > 0);
1753
1754 /* Skip to next component (skip the intervening alpha channel) */
1755 ++in_ptr;
1756 ++out_ptr;
1757 } /* while out_ptr < row_end */
1758
1759 png_write_row(png_ptr, png_voidcast(png_const_bytep,
1760 display->local_row));
1761 input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
1762 } /* while y */
1763 }
1764
1765 else
1766 {
1767 /* No alpha channel, so the row_end really is the end of the row and it
1768 * is sufficient to loop over the components one by one.
1769 */
1770 png_bytep row_end = output_row + image->width * channels;
1771
1772 for (; y > 0; --y)
1773 {
1774 png_const_uint_16p in_ptr = input_row;
1775 png_bytep out_ptr = output_row;
1776
1777 while (out_ptr < row_end)
1778 {
1779 png_uint_32 component = *in_ptr++;
1780
1781 component *= 255;
1782 *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
1783 }
1784
1785 png_write_row(png_ptr, output_row);
1786 input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
1787 }
1788 }
1789
1790 return 1;
1791}
1792
1793static void
1794png_image_set_PLTE(png_image_write_control *display)
1795{
1796 png_imagep image = display->image;
1797 const void *cmap = display->colormap;
1798 int entries = image->colormap_entries > 256 ? 256 :
1799 (int)image->colormap_entries;
1800
1801 /* NOTE: the caller must check for cmap != NULL and entries != 0 */
1802 png_uint_32 format = image->format;
1804
1805# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
1806 defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
1807 int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
1809# else
1810# define afirst 0
1811# endif
1812
1813# ifdef PNG_FORMAT_BGR_SUPPORTED
1814 int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
1815# else
1816# define bgr 0
1817# endif
1818
1819 int i, num_trans;
1820 png_color palette[256];
1821 png_byte tRNS[256];
1822
1823 memset(tRNS, 255, (sizeof tRNS));
1824 memset(palette, 0, (sizeof palette));
1825
1826 for (i=num_trans=0; i<entries; ++i)
1827 {
1828 /* This gets automatically converted to sRGB with reversal of the
1829 * pre-multiplication if the color-map has an alpha channel.
1830 */
1831 if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
1832 {
1834
1835 entry += (unsigned int)i * channels;
1836
1837 if ((channels & 1) != 0) /* no alpha */
1838 {
1839 if (channels >= 3) /* RGB */
1840 {
1841 palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1842 entry[(2 ^ bgr)]);
1843 palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1844 entry[1]);
1845 palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
1846 entry[bgr]);
1847 }
1848
1849 else /* Gray */
1850 palette[i].blue = palette[i].red = palette[i].green =
1851 (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
1852 }
1853
1854 else /* alpha */
1855 {
1856 png_uint_16 alpha = entry[afirst ? 0 : channels-1];
1857 png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
1858 png_uint_32 reciprocal = 0;
1859
1860 /* Calculate a reciprocal, as in the png_write_image_8bit code above
1861 * this is designed to produce a value scaled to 255*65535 when
1862 * divided by 128 (i.e. asr 7).
1863 */
1864 if (alphabyte > 0 && alphabyte < 255)
1865 reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
1866
1867 tRNS[i] = alphabyte;
1868 if (alphabyte < 255)
1869 num_trans = i+1;
1870
1871 if (channels >= 3) /* RGB */
1872 {
1873 palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
1874 alpha, reciprocal);
1875 palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
1876 reciprocal);
1877 palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
1878 reciprocal);
1879 }
1880
1881 else /* gray */
1882 palette[i].blue = palette[i].red = palette[i].green =
1883 png_unpremultiply(entry[afirst], alpha, reciprocal);
1884 }
1885 }
1886
1887 else /* Color-map has sRGB values */
1888 {
1890
1891 entry += (unsigned int)i * channels;
1892
1893 switch (channels)
1894 {
1895 case 4:
1896 tRNS[i] = entry[afirst ? 0 : 3];
1897 if (tRNS[i] < 255)
1898 num_trans = i+1;
1899 /* FALLTHROUGH */
1900 case 3:
1901 palette[i].blue = entry[afirst + (2 ^ bgr)];
1902 palette[i].green = entry[afirst + 1];
1903 palette[i].red = entry[afirst + bgr];
1904 break;
1905
1906 case 2:
1907 tRNS[i] = entry[1 ^ afirst];
1908 if (tRNS[i] < 255)
1909 num_trans = i+1;
1910 /* FALLTHROUGH */
1911 case 1:
1912 palette[i].blue = palette[i].red = palette[i].green =
1913 entry[afirst];
1914 break;
1915
1916 default:
1917 break;
1918 }
1919 }
1920 }
1921
1922# ifdef afirst
1923# undef afirst
1924# endif
1925# ifdef bgr
1926# undef bgr
1927# endif
1928
1929 png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
1930 entries);
1931
1932 if (num_trans > 0)
1933 png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
1934 num_trans, NULL);
1935
1936 image->colormap_entries = (png_uint_32)entries;
1937}
1938
1939static int
1940png_image_write_main(png_voidp argument)
1941{
1942 png_image_write_control *display = png_voidcast(png_image_write_control*,
1943 argument);
1944 png_imagep image = display->image;
1945 png_structrp png_ptr = image->opaque->png_ptr;
1946 png_inforp info_ptr = image->opaque->info_ptr;
1947 png_uint_32 format = image->format;
1948
1949 /* The following four ints are actually booleans */
1950 int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
1951 int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
1952 int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
1953 int write_16bit = linear && (display->convert_to_8bit == 0);
1954
1955# ifdef PNG_BENIGN_ERRORS_SUPPORTED
1956 /* Make sure we error out on any bad situation */
1957 png_set_benign_errors(png_ptr, 0/*error*/);
1958# endif
1959
1960 /* Default the 'row_stride' parameter if required, also check the row stride
1961 * and total image size to ensure that they are within the system limits.
1962 */
1963 {
1964 unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
1965
1966 if (image->width <= 0x7fffffffU/channels) /* no overflow */
1967 {
1969 png_uint_32 png_row_stride = image->width * channels;
1970
1971 if (display->row_stride == 0)
1972 display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
1973
1974 if (display->row_stride < 0)
1975 check = (png_uint_32)(-display->row_stride);
1976
1977 else
1978 check = (png_uint_32)display->row_stride;
1979
1980 if (check >= png_row_stride)
1981 {
1982 /* Now check for overflow of the image buffer calculation; this
1983 * limits the whole image size to 32 bits for API compatibility with
1984 * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
1985 */
1986 if (image->height > 0xffffffffU/png_row_stride)
1987 png_error(image->opaque->png_ptr, "memory image too large");
1988 }
1989
1990 else
1991 png_error(image->opaque->png_ptr, "supplied row stride too small");
1992 }
1993
1994 else
1995 png_error(image->opaque->png_ptr, "image row stride too large");
1996 }
1997
1998 /* Set the required transforms then write the rows in the correct order. */
1999 if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
2000 {
2001 if (display->colormap != NULL && image->colormap_entries > 0)
2002 {
2003 png_uint_32 entries = image->colormap_entries;
2004
2005 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
2006 entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
2009
2010 png_image_set_PLTE(display);
2011 }
2012
2013 else
2014 png_error(image->opaque->png_ptr,
2015 "no color-map for color-mapped image");
2016 }
2017
2018 else
2019 png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
2020 write_16bit ? 16 : 8,
2024
2025 /* Counter-intuitively the data transformations must be called *after*
2026 * png_write_info, not before as in the read code, but the 'set' functions
2027 * must still be called before. Just set the color space information, never
2028 * write an interlaced image.
2029 */
2030
2031 if (write_16bit != 0)
2032 {
2033 /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
2035
2036 if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2037 png_set_cHRM_fixed(png_ptr, info_ptr,
2038 /* color x y */
2039 /* white */ 31270, 32900,
2040 /* red */ 64000, 33000,
2041 /* green */ 30000, 60000,
2042 /* blue */ 15000, 6000
2043 );
2044 }
2045
2046 else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
2048
2049 /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
2050 * space must still be gamma encoded.
2051 */
2052 else
2054
2055 /* Write the file header. */
2056 png_write_info(png_ptr, info_ptr);
2057
2058 /* Now set up the data transformations (*after* the header is written),
2059 * remove the handled transformations from the 'format' flags for checking.
2060 *
2061 * First check for a little endian system if writing 16-bit files.
2062 */
2063 if (write_16bit != 0)
2064 {
2065 png_uint_16 le = 0x0001;
2066
2067 if ((*(png_const_bytep) & le) != 0)
2068 png_set_swap(png_ptr);
2069 }
2070
2071# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
2072 if ((format & PNG_FORMAT_FLAG_BGR) != 0)
2073 {
2074 if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
2075 png_set_bgr(png_ptr);
2076 format &= ~PNG_FORMAT_FLAG_BGR;
2077 }
2078# endif
2079
2080# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
2081 if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
2082 {
2083 if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
2084 png_set_swap_alpha(png_ptr);
2085 format &= ~PNG_FORMAT_FLAG_AFIRST;
2086 }
2087# endif
2088
2089 /* If there are 16 or fewer color-map entries we wrote a lower bit depth
2090 * above, but the application data is still byte packed.
2091 */
2092 if (colormap != 0 && image->colormap_entries <= 16)
2093 png_set_packing(png_ptr);
2094
2095 /* That should have handled all (both) the transforms. */
2098 png_error(png_ptr, "png_write_image: unsupported transformation");
2099
2100 {
2102 ptrdiff_t row_bytes = display->row_stride;
2103
2104 if (linear != 0)
2105 row_bytes *= (sizeof (png_uint_16));
2106
2107 if (row_bytes < 0)
2108 row += (image->height-1) * (-row_bytes);
2109
2110 display->first_row = row;
2111 display->row_bytes = row_bytes;
2112 }
2113
2114 /* Apply 'fast' options if the flag is set. */
2115 if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
2116 {
2118 /* NOTE: determined by experiment using pngstest, this reflects some
2119 * balance between the time to write the image once and the time to read
2120 * it about 50 times. The speed-up in pngstest was about 10-20% of the
2121 * total (user) time on a heavily loaded system.
2122 */
2123# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
2124 png_set_compression_level(png_ptr, 3);
2125# endif
2126 }
2127
2128 /* Check for the cases that currently require a pre-transform on the row
2129 * before it is written. This only applies when the input is 16-bit and
2130 * either there is an alpha channel or it is converted to 8-bit.
2131 */
2132 if ((linear != 0 && alpha != 0 ) ||
2133 (colormap == 0 && display->convert_to_8bit != 0))
2134 {
2136 png_get_rowbytes(png_ptr, info_ptr)));
2137 int result;
2138
2139 display->local_row = row;
2140 if (write_16bit != 0)
2141 result = png_safe_execute(image, png_write_image_16bit, display);
2142 else
2143 result = png_safe_execute(image, png_write_image_8bit, display);
2144 display->local_row = NULL;
2145
2146 png_free(png_ptr, row);
2147
2148 /* Skip the 'write_end' on error: */
2149 if (result == 0)
2150 return 0;
2151 }
2152
2153 /* Otherwise this is the case where the input is in a format currently
2154 * supported by the rest of the libpng write code; call it directly.
2155 */
2156 else
2157 {
2159 ptrdiff_t row_bytes = display->row_bytes;
2160 png_uint_32 y = image->height;
2161
2162 for (; y > 0; --y)
2163 {
2164 png_write_row(png_ptr, row);
2165 row += row_bytes;
2166 }
2167 }
2168
2169 png_write_end(png_ptr, info_ptr);
2170 return 1;
2171}
2172
2173
2174static void (PNGCBAPI
2175image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size)
2176{
2177 png_image_write_control *display = png_voidcast(png_image_write_control*,
2178 png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
2179 png_alloc_size_t ob = display->output_bytes;
2180
2181 /* Check for overflow; this should never happen: */
2182 if (size <= ((png_alloc_size_t)-1) - ob)
2183 {
2184 /* I don't think libpng ever does this, but just in case: */
2185 if (size > 0)
2186 {
2187 if (display->memory_bytes >= ob+size) /* writing */
2188 memcpy(display->memory+ob, data, size);
2189
2190 /* Always update the size: */
2191 display->output_bytes = ob+size;
2192 }
2193 }
2194
2195 else
2196 png_error(png_ptr, "png_image_write_to_memory: PNG too big");
2197}
2198
2199static void (PNGCBAPI
2200image_memory_flush)(png_structp png_ptr)
2201{
2203}
2204
2205static int
2206png_image_write_memory(png_voidp argument)
2207{
2208 png_image_write_control *display = png_voidcast(png_image_write_control*,
2209 argument);
2210
2211 /* The rest of the memory-specific init and write_main in an error protected
2212 * environment. This case needs to use callbacks for the write operations
2213 * since libpng has no built in support for writing to memory.
2214 */
2215 png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
2216 image_memory_write, image_memory_flush);
2217
2218 return png_image_write_main(display);
2219}
2220
2221int PNGAPI
2222png_image_write_to_memory(png_imagep image, void *memory,
2223 png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
2224 const void *buffer, png_int_32 row_stride, const void *colormap)
2225{
2226 /* Write the image to the given buffer, or count the bytes if it is NULL */
2227 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2228 {
2229 if (memory_bytes != NULL && buffer != NULL)
2230 {
2231 /* This is to give the caller an easier error detection in the NULL
2232 * case and guard against uninitialized variable problems:
2233 */
2234 if (memory == NULL)
2235 *memory_bytes = 0;
2236
2237 if (png_image_write_init(image) != 0)
2238 {
2239 png_image_write_control display;
2240 int result;
2241
2242 memset(&display, 0, (sizeof display));
2243 display.image = image;
2244 display.buffer = buffer;
2245 display.row_stride = row_stride;
2246 display.colormap = colormap;
2247 display.convert_to_8bit = convert_to_8bit;
2249 display.memory_bytes = *memory_bytes;
2250 display.output_bytes = 0;
2251
2252 result = png_safe_execute(image, png_image_write_memory, &display);
2253 png_image_free(image);
2254
2255 /* write_memory returns true even if we ran out of buffer. */
2256 if (result)
2257 {
2258 /* On out-of-buffer this function returns '0' but still updates
2259 * memory_bytes:
2260 */
2261 if (memory != NULL && display.output_bytes > *memory_bytes)
2262 result = 0;
2263
2264 *memory_bytes = display.output_bytes;
2265 }
2266
2267 return result;
2268 }
2269
2270 else
2271 return 0;
2272 }
2273
2274 else
2275 return png_image_error(image,
2276 "png_image_write_to_memory: invalid argument");
2277 }
2278
2279 else if (image != NULL)
2280 return png_image_error(image,
2281 "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
2282
2283 else
2284 return 0;
2285}
2286
2287#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
2288int PNGAPI
2289png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
2290 const void *buffer, png_int_32 row_stride, const void *colormap)
2291{
2292 /* Write the image to the given (FILE*). */
2293 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2294 {
2295 if (file != NULL && buffer != NULL)
2296 {
2297 if (png_image_write_init(image) != 0)
2298 {
2299 png_image_write_control display;
2300 int result;
2301
2302 /* This is slightly evil, but png_init_io doesn't do anything other
2303 * than this and we haven't changed the standard IO functions so
2304 * this saves a 'safe' function.
2305 */
2306 image->opaque->png_ptr->io_ptr = file;
2307
2308 memset(&display, 0, (sizeof display));
2309 display.image = image;
2310 display.buffer = buffer;
2311 display.row_stride = row_stride;
2312 display.colormap = colormap;
2313 display.convert_to_8bit = convert_to_8bit;
2314
2315 result = png_safe_execute(image, png_image_write_main, &display);
2316 png_image_free(image);
2317 return result;
2318 }
2319
2320 else
2321 return 0;
2322 }
2323
2324 else
2325 return png_image_error(image,
2326 "png_image_write_to_stdio: invalid argument");
2327 }
2328
2329 else if (image != NULL)
2330 return png_image_error(image,
2331 "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
2332
2333 else
2334 return 0;
2335}
2336
2337int PNGAPI
2338png_image_write_to_file(png_imagep image, const char *file_name,
2339 int convert_to_8bit, const void *buffer, png_int_32 row_stride,
2340 const void *colormap)
2341{
2342 /* Write the image to the named file. */
2343 if (image != NULL && image->version == PNG_IMAGE_VERSION)
2344 {
2345 if (file_name != NULL && buffer != NULL)
2346 {
2347 FILE *fp = fopen(file_name, "wb");
2348
2349 if (fp != NULL)
2350 {
2351 if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
2352 row_stride, colormap) != 0)
2353 {
2354 int error; /* from fflush/fclose */
2355
2356 /* Make sure the file is flushed correctly. */
2357 if (fflush(fp) == 0 && ferror(fp) == 0)
2358 {
2359 if (fclose(fp) == 0)
2360 return 1;
2361
2362 error = errno; /* from fclose */
2363 }
2364
2365 else
2366 {
2367 error = errno; /* from fflush or ferror */
2368 (void)fclose(fp);
2369 }
2370
2372 /* The image has already been cleaned up; this is just used to
2373 * set the error (because the original write succeeded).
2374 */
2375 return png_image_error(image, strerror(error));
2376 }
2377
2378 else
2379 {
2380 /* Clean up: just the opened file. */
2381 (void)fclose(fp);
2383 return 0;
2384 }
2385 }
2386
2387 else
2388 return png_image_error(image, strerror(errno));
2389 }
2390
2391 else
2392 return png_image_error(image,
2393 "png_image_write_to_file: invalid argument");
2394 }
2395
2396 else if (image != NULL)
2397 return png_image_error(image,
2398 "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
2399
2400 else
2401 return 0;
2402}
2403#endif /* SIMPLIFIED_WRITE_STDIO */
2404#endif /* SIMPLIFIED_WRITE */
2405#endif /* WRITE */
calc_t calc
Definition: winmain.c:247
#define NULL
Definition: types.h:112
#define Z_SYNC_FLUSH
Definition: zlib.h:107
int deflateEnd(z_streamp strm) DECLSPEC_HIDDEN
Definition: deflate.c:1130
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define check(expected, result)
Definition: dplayx.c:32
method
Definition: dragdrop.c:54
__kernel_time_t time_t
Definition: linux.h:252
__kernel_ptrdiff_t ptrdiff_t
Definition: linux.h:247
GLint level
Definition: gl.h:1546
GLeglImageOES image
Definition: gl.h:2204
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLclampf GLclampf blue
Definition: gl.h:1740
GLsizeiptr size
Definition: glext.h:5919
GLuint buffer
Definition: glext.h:5915
const GLubyte * c
Definition: glext.h:8905
GLenum const GLfloat * params
Definition: glext.h:5645
GLuint64EXT * result
Definition: glext.h:11304
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define up(mutex)
Definition: glue.h:30
_Check_return_ _CRTIMP int __cdecl ferror(_In_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
uint32_t entry
Definition: isohybrid.c:63
JBLOCKROW output_row
Definition: jpegint.h:422
int JSAMPARRAY int int num_rows
Definition: jpegint.h:421
#define c
Definition: ke_i.h:80
if(dx< 0)
Definition: linetemp.h:194
#define red
Definition: linetest.c:67
struct S1 s1
struct S2 s2
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define PNG_COLOR_TYPE_RGB
Definition: image.c:5165
#define PNG_COLOR_TYPE_RGB_ALPHA
Definition: image.c:5168
#define PNG_COLOR_TYPE_PALETTE
Definition: image.c:5166
static char memory[1024 *256]
Definition: process.c:116
static LPCWSTR file_name
Definition: protocol.c:147
static HPALETTE palette
Definition: clipboard.c:1345
const char * strerror(int err)
Definition: compat_str.c:23
int remove
Definition: msacm.c:1366
#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB
Definition: png.h:2935
#define PNG_FORMAT_FLAG_COLOR
Definition: png.h:2776
#define PNG_TRANSFORM_SWAP_ENDIAN
Definition: png.h:839
#define PNG_INFO_cHRM
Definition: png.h:731
#define PNG_IMAGE_VERSION
Definition: png.h:2666
#define PNG_FILTER_SUB
Definition: png.h:1463
#define PNG_TEXT_COMPRESSION_zTXt_WR
Definition: png.h:584
#define PNG_TRANSFORM_INVERT_ALPHA
Definition: png.h:840
#define PNG_FILTER_PAETH
Definition: png.h:1466
#define PNG_INTRAPIXEL_DIFFERENCING
Definition: png.h:680
#define PNG_FILLER_BEFORE
Definition: png.h:1245
#define PNG_TRANSFORM_PACKING
Definition: png.h:832
#define PNG_FORMAT_FLAG_AFIRST
Definition: png.h:2785
#define PNG_HAVE_PLTE
Definition: png.h:642
#define PNG_INFO_gAMA
Definition: png.h:729
#define PNG_GAMMA_LINEAR
Definition: png.h:1147
#define PNG_MAX_PALETTE_LENGTH
Definition: png.h:722
#define PNG_FILTER_NONE
Definition: png.h:1462
png_structrp png_ptr
Definition: png.h:1080
#define PNG_TRANSFORM_SWAP_ALPHA
Definition: png.h:838
#define PNG_FORMAT_FLAG_COLORMAP
Definition: png.h:2778
#define PNG_FILTER_AVG
Definition: png.h:1465
png_uint_32
Definition: png.h:1936
struct png_control * png_controlp
Definition: png.h:2668
#define PNG_INFO_pHYs
Definition: png.h:736
#define PNG_INFO_sPLT
Definition: png.h:742
#define PNG_TRANSFORM_INVERT_MONO
Definition: png.h:835
#define PNG_TEXT_COMPRESSION_zTXt
Definition: png.h:586
png_set_filter_heuristics_fixed
Definition: png.h:1485
#define PNG_IMAGE_FLAG_FAST
Definition: png.h:2940
#define PNG_FLAG_MNG_FILTER_64
Definition: png.h:855
#define PNG_INFO_pCAL
Definition: png.h:739
png_structrp int int num_weights
Definition: png.h:1486
#define PNG_TRANSFORM_PACKSWAP
Definition: png.h:833
#define PNG_TEXT_COMPRESSION_NONE
Definition: png.h:585
#define PNG_TEXT_COMPRESSION_NONE_WR
Definition: png.h:583
#define PNG_INFO_IDAT
Definition: png.h:744
#define PNG_FORMAT_FLAG_BGR
Definition: png.h:2781
#define PNG_FILTER_VALUE_AVG
Definition: png.h:1476
#define PNG_COLOR_MASK_COLOR
Definition: png.h:661
png_const_structrp png_const_inforp png_fixed_point *int_file_gamma png_set_gAMA_fixed
Definition: png.h:2001
#define PNG_INFO_eXIf
Definition: png.h:745
#define PNG_ALL_FILTERS
Definition: png.h:1468
#define PNG_TRANSFORM_STRIP_FILLER_AFTER
Definition: png.h:844
#define PNG_FILTER_VALUE_UP
Definition: png.h:1475
#define PNG_TRANSFORM_BGR
Definition: png.h:837
#define PNG_INFO_tIME
Definition: png.h:738
#define PNG_TRANSFORM_STRIP_FILLER_BEFORE
Definition: png.h:843
#define PNG_INFO_sRGB
Definition: png.h:740
#define PNG_FILTER_TYPE_BASE
Definition: png.h:679
#define PNG_FILLER_AFTER
Definition: png.h:1246
#define PNG_HANDLE_CHUNK_NEVER
Definition: png.h:2343
#define PNG_AFTER_IDAT
Definition: png.h:643
#define PNG_COLOR_MASK_ALPHA
Definition: png.h:662
#define PNG_HANDLE_CHUNK_ALWAYS
Definition: png.h:2345
#define PNG_FORMAT_FLAG_LINEAR
Definition: png.h:2777
#define PNG_HAVE_IHDR
Definition: png.h:641
#define PNG_INFO_sBIT
Definition: png.h:730
#define PNG_sRGB_INTENT_PERCEPTUAL
Definition: png.h:712
png_structrp int heuristic_method
Definition: png.h:1486
#define PNG_INFO_tRNS
Definition: png.h:733
#define PNG_INFO_sCAL
Definition: png.h:743
#define PNG_INFO_bKGD
Definition: png.h:734
#define PNG_FILTER_UP
Definition: png.h:1464
#define PNG_INFO_hIST
Definition: png.h:735
const png_info *PNG_RESTRICT png_const_inforp
Definition: png.h:469
#define PNG_INFO_iCCP
Definition: png.h:741
#define PNG_INFO_PLTE
Definition: png.h:732
#define PNG_FILTER_VALUE_PAETH
Definition: png.h:1477
#define PNG_LIBPNG_VER_STRING
Definition: png.h:281
#define PNG_FORMAT_FLAG_ALPHA
Definition: png.h:2775
#define PNG_NO_FILTERS
Definition: png.h:1461
#define PNG_FILTER_VALUE_NONE
Definition: png.h:1473
png_structrp int int png_const_fixed_point_p filter_weights
Definition: png.h:1487
#define PNG_INTERLACE_NONE
Definition: png.h:684
#define PNG_INFO_oFFs
Definition: png.h:737
#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)
Definition: png.h:2843
png_info *PNG_RESTRICT png_inforp
Definition: png.h:468
#define PNG_COMPRESSION_TYPE_BASE
Definition: png.h:675
#define PNG_FILTER_VALUE_SUB
Definition: png.h:1474
#define PNG_IMAGE_PIXEL_CHANNELS(fmt)
Definition: png.h:2879
#define PNG_HANDLE_CHUNK_AS_DEFAULT
Definition: png.h:2342
png_struct *PNG_RESTRICT png_structrp
Definition: png.h:466
#define PNG_TRANSFORM_SHIFT
Definition: png.h:836
png_const_structrp png_const_inforp info_ptr
Definition: png.h:1937
#define PNG_FUNCTION(type, name, args, attributes)
Definition: pngconf.h:287
const png_byte * png_const_bytep
Definition: pngconf.h:580
const png_uint_16 * png_const_uint_16p
Definition: pngconf.h:586
size_t png_alloc_size_t
Definition: pngconf.h:557
#define PNGAPI
Definition: pngconf.h:261
png_byte * png_bytep
Definition: pngconf.h:579
png_byte ** png_bytepp
Definition: pngconf.h:606
png_uint_16 * png_uint_16p
Definition: pngconf.h:585
#define PNGCBAPI
Definition: pngconf.h:258
const png_fixed_point * png_const_fixed_point_p
Definition: pngconf.h:592
#define PNG_ALLOCATED
Definition: pngconf.h:439
const char * png_const_charp
Definition: pngconf.h:590
#define PNG_RESTRICT
Definition: pngconf.h:445
#define png_debug2(l, m, p1, p2)
Definition: pngdebug.h:151
#define png_debug(l, m)
Definition: pngdebug.h:145
#define png_debug1(l, m, p1)
Definition: pngdebug.h:148
#define PNG_Z_DEFAULT_STRATEGY
Definition: pnglibconf.h:215
#define PNG_TEXT_Z_DEFAULT_COMPRESSION
Definition: pnglibconf.h:205
#define PNG_WRITE_INTERLACING_SUPPORTED
Definition: pnglibconf.h:138
#define PNG_Z_DEFAULT_COMPRESSION
Definition: pnglibconf.h:213
#define PNG_ZBUF_SIZE
Definition: pnglibconf.h:211
#define PNG_TEXT_Z_DEFAULT_STRATEGY
Definition: pnglibconf.h:206
#define PNG_UNUSED(param)
Definition: pngpriv.h:444
#define PNG_HAVE_PNG_SIGNATURE
Definition: pngpriv.h:627
#define PNG_INTERLACE
Definition: pngpriv.h:634
#define PNG_ROWBYTES(pixel_bits, width)
Definition: pngpriv.h:729
#define png_app_error(pp, s)
Definition: pngpriv.h:1819
#define png_app_warning(pp, s)
Definition: pngpriv.h:1818
#define PNG_FLAG_BENIGN_ERRORS_WARN
Definition: pngpriv.h:690
#define PNG_INVERT_ALPHA
Definition: pngpriv.h:652
#define PNG_DIV257(v16)
Definition: pngpriv.h:726
#define PNG_USER_TRANSFORM
Definition: pngpriv.h:653
#define PNG_WROTE_INFO_BEFORE_PLTE
Definition: pngpriv.h:625
#define PNG_SHIFT
Definition: pngpriv.h:636
#define PNG_HAVE_IDAT
Definition: pngpriv.h:617
#define PNG_FLAG_APP_WARNINGS_WARN
Definition: pngpriv.h:691
#define PNG_FILLER
Definition: pngpriv.h:648
#define PNG_WROTE_tIME
Definition: pngpriv.h:624
#define PNG_FLAG_ZSTREAM_INITIALIZED
Definition: pngpriv.h:671
#define PNG_GAMMA_sRGB_INVERSE
Definition: pngpriv.h:897
#define png_voidcast(type, value)
Definition: pngpriv.h:500
#define PNG_INVERT_MONO
Definition: pngpriv.h:638
#define PNG_PACK
Definition: pngpriv.h:635
const png_double * png_const_doublep
Definition: pngpriv.h:380
#define PNG_PACKSWAP
Definition: pngpriv.h:649
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY
Definition: pngpriv.h:670
#define PNG_SWAP_BYTES
Definition: pngpriv.h:637
#define PNG_BGR
Definition: pngpriv.h:633
int This channels
Definition: rdpsnd_libao.c:37
#define errno
Definition: errno.h:18
_CRTIMP struct tm *__cdecl gmtime(const time_t *_Time)
Definition: time.h:415
#define memset(x, y, z)
Definition: compat.h:39
char * name
Definition: compiler.c:66
Definition: fci.c:127
png_uint_32 width
Definition: png.h:753
png_byte color_type
Definition: png.h:755
png_byte bit_depth
Definition: png.h:756
png_byte pixel_depth
Definition: png.h:758
png_byte channels
Definition: png.h:757
size_t rowbytes
Definition: png.h:754
png_byte month
Definition: png.h:600
png_uint_16 year
Definition: png.h:599
png_byte hour
Definition: png.h:602
png_byte second
Definition: png.h:604
png_byte minute
Definition: png.h:603
png_byte day
Definition: png.h:601
Definition: time.h:68
int tm_mon
Definition: time.h:73
int tm_year
Definition: time.h:74
int tm_hour
Definition: time.h:71
int tm_sec
Definition: time.h:69
int tm_mday
Definition: time.h:72
int tm_min
Definition: time.h:70
pass
Definition: typegen.h:25
int * display
Definition: x11stubs.c:12
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
Byte * voidp
Definition: zconf.h:420