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