2
2
/* pngwrite.c - general routines to write a PNG file
4
* Last changed in libpng 1.2.15 January 5, 2007
5
* For conditions of distribution and use, see copyright notice in png.h
6
* Copyright (c) 1998-2007 Glenn Randers-Pehrson
4
* Last changed in libpng 1.2.41 [December 3, 2009]
5
* Copyright (c) 1998-2009 Glenn Randers-Pehrson
7
6
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8
7
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
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
11
/* get internal access to png.h */
14
/* Get internal access to png.h */
12
15
#define PNG_INTERNAL
16
#define PNG_NO_PEDANTIC_WARNINGS
14
18
#ifdef PNG_WRITE_SUPPORTED
26
30
png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
28
png_debug(1, "in png_write_info_before_PLTE\n");
32
png_debug(1, "in png_write_info_before_PLTE");
29
34
if (png_ptr == NULL || info_ptr == NULL)
31
36
if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
33
png_write_sig(png_ptr); /* write PNG signature */
34
#if defined(PNG_MNG_FEATURES_SUPPORTED)
35
if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
38
/* Write PNG signature */
39
png_write_sig(png_ptr);
40
#ifdef PNG_MNG_FEATURES_SUPPORTED
41
if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted))
37
png_warning(png_ptr,"MNG features are not allowed in a PNG datastream");
38
png_ptr->mng_features_permitted=0;
43
png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
44
png_ptr->mng_features_permitted = 0;
41
/* write IHDR information. */
47
/* Write IHDR information. */
42
48
png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
43
49
info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
44
50
info_ptr->filter_type,
45
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
51
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
46
52
info_ptr->interlace_type);
50
/* the rest of these check to see if the valid field has the appropriate
51
flag set, and if it does, writes the chunk. */
52
#if defined(PNG_WRITE_gAMA_SUPPORTED)
56
/* The rest of these check to see if the valid field has the appropriate
57
* flag set, and if it does, writes the chunk.
59
#ifdef PNG_WRITE_gAMA_SUPPORTED
53
60
if (info_ptr->valid & PNG_INFO_gAMA)
55
62
# ifdef PNG_FLOATING_POINT_SUPPORTED
64
#if defined(PNG_WRITE_sRGB_SUPPORTED)
71
#ifdef PNG_WRITE_sRGB_SUPPORTED
65
72
if (info_ptr->valid & PNG_INFO_sRGB)
66
73
png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
68
#if defined(PNG_WRITE_iCCP_SUPPORTED)
75
#ifdef PNG_WRITE_iCCP_SUPPORTED
69
76
if (info_ptr->valid & PNG_INFO_iCCP)
70
77
png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
71
78
info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
73
#if defined(PNG_WRITE_sBIT_SUPPORTED)
80
#ifdef PNG_WRITE_sBIT_SUPPORTED
74
81
if (info_ptr->valid & PNG_INFO_sBIT)
75
82
png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
77
#if defined(PNG_WRITE_cHRM_SUPPORTED)
84
#ifdef PNG_WRITE_cHRM_SUPPORTED
78
85
if (info_ptr->valid & PNG_INFO_cHRM)
80
87
#ifdef PNG_FLOATING_POINT_SUPPORTED
97
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
104
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
98
105
if (info_ptr->unknown_chunks_num)
100
png_unknown_chunk *up;
102
png_debug(5, "writing extra chunks\n");
104
for (up = info_ptr->unknown_chunks;
105
up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
108
int keep=png_handle_as_unknown(png_ptr, up->name);
107
png_unknown_chunk *up;
109
png_debug(5, "writing extra chunks");
111
for (up = info_ptr->unknown_chunks;
112
up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
115
int keep = png_handle_as_unknown(png_ptr, up->name);
109
116
if (keep != PNG_HANDLE_CHUNK_NEVER &&
110
117
up->location && !(up->location & PNG_HAVE_PLTE) &&
111
118
!(up->location & PNG_HAVE_IDAT) &&
112
119
((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
113
120
(png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
123
png_warning(png_ptr, "Writing zero-length unknown chunk");
115
124
png_write_chunk(png_ptr, up->name, up->data, up->size);
120
129
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
141
150
else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
142
151
png_error(png_ptr, "Valid palette required for paletted images");
144
#if defined(PNG_WRITE_tRNS_SUPPORTED)
153
#ifdef PNG_WRITE_tRNS_SUPPORTED
145
154
if (info_ptr->valid & PNG_INFO_tRNS)
156
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
157
/* Invert the alpha channel (in tRNS) */
158
if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
159
info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
147
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
148
/* invert the alpha channel (in tRNS) */
149
if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
150
info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
153
for (j=0; j<(int)info_ptr->num_trans; j++)
154
info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
162
for (j = 0; j<(int)info_ptr->num_trans; j++)
163
info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
157
166
png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
158
167
info_ptr->num_trans, info_ptr->color_type);
161
#if defined(PNG_WRITE_bKGD_SUPPORTED)
170
#ifdef PNG_WRITE_bKGD_SUPPORTED
162
171
if (info_ptr->valid & PNG_INFO_bKGD)
163
172
png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
165
#if defined(PNG_WRITE_hIST_SUPPORTED)
174
#ifdef PNG_WRITE_hIST_SUPPORTED
166
175
if (info_ptr->valid & PNG_INFO_hIST)
167
176
png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
169
#if defined(PNG_WRITE_oFFs_SUPPORTED)
178
#ifdef PNG_WRITE_oFFs_SUPPORTED
170
179
if (info_ptr->valid & PNG_INFO_oFFs)
171
180
png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
172
181
info_ptr->offset_unit_type);
174
#if defined(PNG_WRITE_pCAL_SUPPORTED)
183
#ifdef PNG_WRITE_pCAL_SUPPORTED
175
184
if (info_ptr->valid & PNG_INFO_pCAL)
176
185
png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
177
186
info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
178
187
info_ptr->pcal_units, info_ptr->pcal_params);
180
#if defined(PNG_WRITE_sCAL_SUPPORTED)
190
#ifdef PNG_sCAL_SUPPORTED
181
191
if (info_ptr->valid & PNG_INFO_sCAL)
182
#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
192
#ifdef PNG_WRITE_sCAL_SUPPORTED
193
#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
183
194
png_write_sCAL(png_ptr, (int)info_ptr->scal_unit,
184
195
info_ptr->scal_pixel_width, info_ptr->scal_pixel_height);
196
#else /* !FLOATING_POINT */
186
197
#ifdef PNG_FIXED_POINT_SUPPORTED
187
198
png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
188
199
info_ptr->scal_s_width, info_ptr->scal_s_height);
200
#endif /* FIXED_POINT */
201
#endif /* FLOATING_POINT */
202
#else /* !WRITE_sCAL */
190
203
png_warning(png_ptr,
191
204
"png_write_sCAL not supported; sCAL chunk not written.");
195
#if defined(PNG_WRITE_pHYs_SUPPORTED)
205
#endif /* WRITE_sCAL */
208
#ifdef PNG_WRITE_pHYs_SUPPORTED
196
209
if (info_ptr->valid & PNG_INFO_pHYs)
197
210
png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
198
211
info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
200
#if defined(PNG_WRITE_tIME_SUPPORTED)
214
#ifdef PNG_WRITE_tIME_SUPPORTED
201
215
if (info_ptr->valid & PNG_INFO_tIME)
203
217
png_write_tIME(png_ptr, &(info_ptr->mod_time));
204
218
png_ptr->mode |= PNG_WROTE_tIME;
207
#if defined(PNG_WRITE_sPLT_SUPPORTED)
222
#ifdef PNG_WRITE_sPLT_SUPPORTED
208
223
if (info_ptr->valid & PNG_INFO_sPLT)
209
224
for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
210
225
png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
212
#if defined(PNG_WRITE_TEXT_SUPPORTED)
228
#ifdef PNG_WRITE_TEXT_SUPPORTED
213
229
/* Check to see if we need to write text chunks */
214
230
for (i = 0; i < info_ptr->num_text; i++)
216
png_debug2(2, "Writing header text chunk %d, type %d\n", i,
232
png_debug2(2, "Writing header text chunk %d, type %d", i,
217
233
info_ptr->text[i].compression);
218
/* an internationalized chunk? */
234
/* An internationalized chunk? */
219
235
if (info_ptr->text[i].compression > 0)
221
#if defined(PNG_WRITE_iTXt_SUPPORTED)
222
/* write international chunk */
237
#ifdef PNG_WRITE_iTXt_SUPPORTED
238
/* Write international chunk */
223
239
png_write_iTXt(png_ptr,
224
240
info_ptr->text[i].compression,
225
241
info_ptr->text[i].key,
249
265
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
251
#if defined(PNG_WRITE_tEXt_SUPPORTED)
252
/* write uncompressed chunk */
267
#ifdef PNG_WRITE_tEXt_SUPPORTED
268
/* Write uncompressed chunk */
253
269
png_write_tEXt(png_ptr, info_ptr->text[i].key,
254
270
info_ptr->text[i].text,
272
/* Mark this chunk as written */
273
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
257
276
png_warning(png_ptr, "Unable to write uncompressed text");
259
/* Mark this chunk as written */
260
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
264
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
282
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
265
283
if (info_ptr->unknown_chunks_num)
267
png_unknown_chunk *up;
269
png_debug(5, "writing extra chunks\n");
271
for (up = info_ptr->unknown_chunks;
272
up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
275
int keep=png_handle_as_unknown(png_ptr, up->name);
285
png_unknown_chunk *up;
287
png_debug(5, "writing extra chunks");
289
for (up = info_ptr->unknown_chunks;
290
up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
293
int keep = png_handle_as_unknown(png_ptr, up->name);
276
294
if (keep != PNG_HANDLE_CHUNK_NEVER &&
277
295
up->location && (up->location & PNG_HAVE_PLTE) &&
278
296
!(up->location & PNG_HAVE_IDAT) &&
295
313
png_write_end(png_structp png_ptr, png_infop info_ptr)
297
png_debug(1, "in png_write_end\n");
315
png_debug(1, "in png_write_end");
298
317
if (png_ptr == NULL)
300
319
if (!(png_ptr->mode & PNG_HAVE_IDAT))
301
320
png_error(png_ptr, "No IDATs written into file");
303
/* see if user wants us to write information chunks */
322
/* See if user wants us to write information chunks */
304
323
if (info_ptr != NULL)
306
#if defined(PNG_WRITE_TEXT_SUPPORTED)
325
#ifdef PNG_WRITE_TEXT_SUPPORTED
307
326
int i; /* local index variable */
309
#if defined(PNG_WRITE_tIME_SUPPORTED)
310
/* check to see if user has supplied a time chunk */
328
#ifdef PNG_WRITE_tIME_SUPPORTED
329
/* Check to see if user has supplied a time chunk */
311
330
if ((info_ptr->valid & PNG_INFO_tIME) &&
312
331
!(png_ptr->mode & PNG_WROTE_tIME))
313
332
png_write_tIME(png_ptr, &(info_ptr->mod_time));
315
#if defined(PNG_WRITE_TEXT_SUPPORTED)
316
/* loop through comment chunks */
334
#ifdef PNG_WRITE_TEXT_SUPPORTED
335
/* Loop through comment chunks */
317
336
for (i = 0; i < info_ptr->num_text; i++)
319
png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
338
png_debug2(2, "Writing trailer text chunk %d, type %d", i,
320
339
info_ptr->text[i].compression);
321
/* an internationalized chunk? */
340
/* An internationalized chunk? */
322
341
if (info_ptr->text[i].compression > 0)
324
#if defined(PNG_WRITE_iTXt_SUPPORTED)
325
/* write international chunk */
326
png_write_iTXt(png_ptr,
327
info_ptr->text[i].compression,
328
info_ptr->text[i].key,
329
info_ptr->text[i].lang,
330
info_ptr->text[i].lang_key,
331
info_ptr->text[i].text);
343
#ifdef PNG_WRITE_iTXt_SUPPORTED
344
/* Write international chunk */
345
png_write_iTXt(png_ptr,
346
info_ptr->text[i].compression,
347
info_ptr->text[i].key,
348
info_ptr->text[i].lang,
349
info_ptr->text[i].lang_key,
350
info_ptr->text[i].text);
333
png_warning(png_ptr, "Unable to write international text");
352
png_warning(png_ptr, "Unable to write international text");
335
/* Mark this chunk as written */
336
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
354
/* Mark this chunk as written */
355
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
338
357
else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
340
#if defined(PNG_WRITE_zTXt_SUPPORTED)
341
/* write compressed chunk */
359
#ifdef PNG_WRITE_zTXt_SUPPORTED
360
/* Write compressed chunk */
342
361
png_write_zTXt(png_ptr, info_ptr->text[i].key,
343
362
info_ptr->text[i].text, 0,
344
363
info_ptr->text[i].compression);
383
402
png_write_chunk(png_ptr, up->name, up->data, up->size);
390
409
png_ptr->mode |= PNG_AFTER_IDAT;
392
/* write end of PNG file */
411
/* Write end of PNG file */
393
412
png_write_IEND(png_ptr);
413
/* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
414
* and restored again in libpng-1.2.30, may cause some applications that
415
* do not set png_ptr->output_flush_fn to crash. If your application
416
* experiences a problem, please try building libpng with
417
* PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
418
* png-mng-implement at lists.sf.net . This kludge will be removed
421
#if defined(PNG_WRITE_FLUSH_SUPPORTED) && \
422
defined(PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED)
396
#if defined(PNG_WRITE_tIME_SUPPORTED)
397
#if !defined(_WIN32_WCE)
398
/* "time.h" functions are not supported on WindowsCE */
427
#ifdef PNG_CONVERT_tIME_SUPPORTED
428
/* "tm" structure is not supported on WindowsCE */
400
430
png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
402
png_debug(1, "in png_convert_from_struct_tm\n");
432
png_debug(1, "in png_convert_from_struct_tm");
403
434
ptime->year = (png_uint_16)(1900 + ttime->tm_year);
404
435
ptime->month = (png_byte)(ttime->tm_mon + 1);
405
436
ptime->day = (png_byte)ttime->tm_mday;
515
559
png_warning(png_ptr, msg);
517
561
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
520
564
png_error(png_ptr,
521
565
"Incompatible libpng version in application and library");
525
/* initialize zbuf - compression buffer */
569
/* Initialize zbuf - compression buffer */
526
570
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
527
571
png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
528
(png_uint_32)png_ptr->zbuf_size);
572
(png_uint_32)png_ptr->zbuf_size);
530
574
png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
531
575
png_flush_ptr_NULL);
533
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
577
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
534
578
png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
535
579
1, png_doublep_NULL, png_doublep_NULL);
538
582
#ifdef PNG_SETJMP_SUPPORTED
539
/* Applications that neglect to set up their own setjmp() and then encounter
540
a png_error() will longjmp here. Since the jmpbuf is then meaningless we
541
abort instead of returning. */
583
/* Applications that neglect to set up their own setjmp() and then
584
* encounter a png_error() will longjmp here. Since the jmpbuf is
585
* then meaningless we abort instead of returning.
542
587
#ifdef USE_FAR_KEYWORD
543
588
if (setjmp(jmpbuf))
545
png_memcpy(png_ptr->jmpbuf,jmpbuf,png_sizeof(jmp_buf));
590
png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
547
592
if (setjmp(png_ptr->jmpbuf))
567
612
png_size_t png_struct_size, png_size_t png_info_size)
569
614
/* We only come here via pre-1.0.12-compiled applications */
570
if(png_ptr == NULL) return;
571
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
572
if(png_sizeof(png_struct) > png_struct_size ||
615
if (png_ptr == NULL) return;
616
#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
617
if (png_sizeof(png_struct) > png_struct_size ||
573
618
png_sizeof(png_info) > png_info_size)
576
png_ptr->warning_fn=NULL;
621
png_ptr->warning_fn = NULL;
577
622
if (user_png_ver)
579
png_snprintf(msg, 80,
580
"Application was compiled with png.h from libpng-%.20s",
582
png_warning(png_ptr, msg);
624
png_snprintf(msg, 80,
625
"Application was compiled with png.h from libpng-%.20s",
627
png_warning(png_ptr, msg);
584
629
png_snprintf(msg, 80,
585
630
"Application is running with png.c from libpng-%.20s",
587
632
png_warning(png_ptr, msg);
590
if(png_sizeof(png_struct) > png_struct_size)
592
png_ptr->error_fn=NULL;
593
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
597
"The png struct allocated by the application for writing is too small.");
599
if(png_sizeof(png_info) > png_info_size)
601
png_ptr->error_fn=NULL;
602
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
606
"The info struct allocated by the application for writing is too small.");
635
if (png_sizeof(png_struct) > png_struct_size)
637
png_ptr->error_fn = NULL;
638
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
642
"The png struct allocated by the application for writing is too small.");
644
if (png_sizeof(png_info) > png_info_size)
646
png_ptr->error_fn = NULL;
647
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
651
"The info struct allocated by the application for writing is too small.");
608
653
png_write_init_3(&png_ptr, user_png_ver, png_struct_size);
610
655
#endif /* PNG_1_0_X || PNG_1_2_X */
629
if (user_png_ver[i] != png_libpng_ver[i])
674
if (user_png_ver[i] != png_libpng_ver[i])
631
676
#ifdef PNG_LEGACY_SUPPORTED
632
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
677
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
634
png_ptr->warning_fn=NULL;
636
"Application uses deprecated png_write_init() and should be recompiled.");
679
png_ptr->warning_fn = NULL;
681
"Application uses deprecated png_write_init() and should be recompiled.");
640
684
} while (png_libpng_ver[i++]);
642
png_debug(1, "in png_write_init_3\n");
686
png_debug(1, "in png_write_init_3");
644
688
#ifdef PNG_SETJMP_SUPPORTED
645
/* save jump buffer and error functions */
646
png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof (jmp_buf));
689
/* Save jump buffer and error functions */
690
png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
649
693
if (png_sizeof(png_struct) > png_struct_size)
651
png_destroy_struct(png_ptr);
652
png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
656
/* reset all variables to 0 */
657
png_memset(png_ptr, 0, png_sizeof (png_struct));
659
/* added at libpng-1.2.6 */
695
png_destroy_struct(png_ptr);
696
png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
700
/* Reset all variables to 0 */
701
png_memset(png_ptr, 0, png_sizeof(png_struct));
703
/* Added at libpng-1.2.6 */
660
704
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
661
png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
662
png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
705
png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
706
png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
665
709
#ifdef PNG_SETJMP_SUPPORTED
666
/* restore jump buffer */
667
png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof (jmp_buf));
710
/* Restore jump buffer */
711
png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
670
714
png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL,
671
715
png_flush_ptr_NULL);
673
/* initialize zbuf - compression buffer */
717
/* Initialize zbuf - compression buffer */
674
718
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
675
719
png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
676
(png_uint_32)png_ptr->zbuf_size);
678
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
720
(png_uint_32)png_ptr->zbuf_size);
721
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
679
722
png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
680
723
1, png_doublep_NULL, png_doublep_NULL);
718
761
if (png_ptr == NULL)
721
png_debug(1, "in png_write_image\n");
722
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
723
/* intialize interlace handling. If image is not interlaced,
724
this will set pass to 1 */
764
png_debug(1, "in png_write_image");
766
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
767
/* Initialize interlace handling. If image is not interlaced,
768
* this will set pass to 1
725
770
num_pass = png_set_interlace_handling(png_ptr);
729
/* loop through passes */
774
/* Loop through passes */
730
775
for (pass = 0; pass < num_pass; pass++)
732
/* loop through image */
777
/* Loop through image */
733
778
for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
735
780
png_write_row(png_ptr, *rp);
740
/* called by user to write a row of image data */
785
/* Called by user to write a row of image data */
742
787
png_write_row(png_structp png_ptr, png_bytep row)
744
789
if (png_ptr == NULL)
746
png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
792
png_debug2(1, "in png_write_row (row %ld, pass %d)",
747
793
png_ptr->row_number, png_ptr->pass);
749
/* initialize transformations and other stuff if first time */
795
/* Initialize transformations and other stuff if first time */
750
796
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
752
/* make sure we wrote the header info */
753
if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
755
"png_write_info was never called before png_write_row.");
798
/* Make sure we wrote the header info */
799
if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
801
"png_write_info was never called before png_write_row.");
757
/* check for transforms that have been set but were defined out */
803
/* Check for transforms that have been set but were defined out */
758
804
#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
759
if (png_ptr->transformations & PNG_INVERT_MONO)
760
png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
805
if (png_ptr->transformations & PNG_INVERT_MONO)
806
png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
762
808
#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
763
if (png_ptr->transformations & PNG_FILLER)
764
png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
809
if (png_ptr->transformations & PNG_FILLER)
810
png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
766
812
#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
767
if (png_ptr->transformations & PNG_PACKSWAP)
768
png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
813
if (png_ptr->transformations & PNG_PACKSWAP)
814
png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
770
816
#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
771
if (png_ptr->transformations & PNG_PACK)
772
png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
817
if (png_ptr->transformations & PNG_PACK)
818
png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
774
820
#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
775
if (png_ptr->transformations & PNG_SHIFT)
776
png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
821
if (png_ptr->transformations & PNG_SHIFT)
822
png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
778
824
#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
779
if (png_ptr->transformations & PNG_BGR)
780
png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
825
if (png_ptr->transformations & PNG_BGR)
826
png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
782
828
#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
783
if (png_ptr->transformations & PNG_SWAP_BYTES)
784
png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
829
if (png_ptr->transformations & PNG_SWAP_BYTES)
830
png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
787
833
png_write_start_row(png_ptr);
790
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
791
/* if interlaced and not interested in row, return */
836
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
837
/* If interlaced and not interested in row, return */
792
838
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
794
840
switch (png_ptr->pass)
857
903
png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
858
904
png_ptr->row_info.width);
860
png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
861
png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width);
862
png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
863
png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
864
png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
865
png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes);
906
png_debug1(3, "row_info->color_type = %d", png_ptr->row_info.color_type);
907
png_debug1(3, "row_info->width = %lu", png_ptr->row_info.width);
908
png_debug1(3, "row_info->channels = %d", png_ptr->row_info.channels);
909
png_debug1(3, "row_info->bit_depth = %d", png_ptr->row_info.bit_depth);
910
png_debug1(3, "row_info->pixel_depth = %d", png_ptr->row_info.pixel_depth);
911
png_debug1(3, "row_info->rowbytes = %lu", png_ptr->row_info.rowbytes);
867
913
/* Copy user's row into buffer, leaving room for filter byte. */
868
914
png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
869
915
png_ptr->row_info.rowbytes);
871
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
872
/* handle interlacing */
917
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
918
/* Handle interlacing */
873
919
if (png_ptr->interlaced && png_ptr->pass < 6 &&
874
920
(png_ptr->transformations & PNG_INTERLACE))
876
922
png_do_write_interlace(&(png_ptr->row_info),
877
923
png_ptr->row_buf + 1, png_ptr->pass);
878
/* this should always get caught above, but still ... */
924
/* This should always get caught above, but still ... */
879
925
if (!(png_ptr->row_info.width))
881
927
png_write_finish_row(png_ptr);
913
959
(*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
916
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
962
#ifdef PNG_WRITE_FLUSH_SUPPORTED
917
963
/* Set the automatic flush interval or 0 to turn flushing off */
919
965
png_set_flush(png_structp png_ptr, int nrows)
921
png_debug(1, "in png_set_flush\n");
967
png_debug(1, "in png_set_flush");
922
969
if (png_ptr == NULL)
924
971
png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
927
/* flush the current output buffers now */
974
/* Flush the current output buffers now */
929
976
png_write_flush(png_structp png_ptr)
933
png_debug(1, "in png_write_flush\n");
980
png_debug(1, "in png_write_flush");
934
982
if (png_ptr == NULL)
936
984
/* We have already written out all of the data */
937
985
if (png_ptr->row_number >= png_ptr->num_rows)
944
/* compress the data */
992
/* Compress the data */
945
993
ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
948
/* check for compression errors */
996
/* Check for compression errors */
951
999
if (png_ptr->zstream.msg != NULL)
1052
#ifdef PNG_USER_MEM_SUPPORTED
1053
if (png_ptr != NULL)
1055
free_fn = png_ptr->free_fn;
1056
mem_ptr = png_ptr->mem_ptr;
1003
1060
if (info_ptr_ptr != NULL)
1004
1061
info_ptr = *info_ptr_ptr;
1006
1063
if (info_ptr != NULL)
1008
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
1010
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
1011
if (png_ptr->num_chunk_list)
1065
if (png_ptr != NULL)
1013
png_free(png_ptr, png_ptr->chunk_list);
1014
png_ptr->chunk_list=NULL;
1015
png_ptr->num_chunk_list=0;
1067
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
1069
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
1070
if (png_ptr->num_chunk_list)
1072
png_free(png_ptr, png_ptr->chunk_list);
1073
png_ptr->chunk_list = NULL;
1074
png_ptr->num_chunk_list = 0;
1019
1079
#ifdef PNG_USER_MEM_SUPPORTED
1020
1080
png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
1053
1113
png_free_ptr free_fn;
1056
png_debug(1, "in png_write_destroy\n");
1057
/* free any memory zlib uses */
1116
png_debug(1, "in png_write_destroy");
1118
/* Free any memory zlib uses */
1058
1119
deflateEnd(&png_ptr->zstream);
1060
/* free our memory. png_free checks NULL for us. */
1121
/* Free our memory. png_free checks NULL for us. */
1061
1122
png_free(png_ptr, png_ptr->zbuf);
1062
1123
png_free(png_ptr, png_ptr->row_buf);
1124
#ifdef PNG_WRITE_FILTER_SUPPORTED
1063
1125
png_free(png_ptr, png_ptr->prev_row);
1064
1126
png_free(png_ptr, png_ptr->sub_row);
1065
1127
png_free(png_ptr, png_ptr->up_row);
1066
1128
png_free(png_ptr, png_ptr->avg_row);
1067
1129
png_free(png_ptr, png_ptr->paeth_row);
1069
#if defined(PNG_TIME_RFC1123_SUPPORTED)
1132
#ifdef PNG_TIME_RFC1123_SUPPORTED
1070
1133
png_free(png_ptr, png_ptr->time_buffer);
1073
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1136
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
1074
1137
png_free(png_ptr, png_ptr->prev_filters);
1075
1138
png_free(png_ptr, png_ptr->filter_weights);
1076
1139
png_free(png_ptr, png_ptr->inv_filter_weights);
1121
1185
switch (filters & (PNG_ALL_FILTERS | 0x07))
1123
#ifndef PNG_NO_WRITE_FILTER
1187
#ifdef PNG_WRITE_FILTER_SUPPORTED
1126
1190
case 7: png_warning(png_ptr, "Unknown row filter for method 0");
1127
#endif /* PNG_NO_WRITE_FILTER */
1191
#endif /* PNG_WRITE_FILTER_SUPPORTED */
1128
1192
case PNG_FILTER_VALUE_NONE:
1129
png_ptr->do_filter=PNG_FILTER_NONE; break;
1130
#ifndef PNG_NO_WRITE_FILTER
1193
png_ptr->do_filter = PNG_FILTER_NONE; break;
1194
#ifdef PNG_WRITE_FILTER_SUPPORTED
1131
1195
case PNG_FILTER_VALUE_SUB:
1132
png_ptr->do_filter=PNG_FILTER_SUB; break;
1196
png_ptr->do_filter = PNG_FILTER_SUB; break;
1133
1197
case PNG_FILTER_VALUE_UP:
1134
png_ptr->do_filter=PNG_FILTER_UP; break;
1198
png_ptr->do_filter = PNG_FILTER_UP; break;
1135
1199
case PNG_FILTER_VALUE_AVG:
1136
png_ptr->do_filter=PNG_FILTER_AVG; break;
1200
png_ptr->do_filter = PNG_FILTER_AVG; break;
1137
1201
case PNG_FILTER_VALUE_PAETH:
1138
png_ptr->do_filter=PNG_FILTER_PAETH; break;
1202
png_ptr->do_filter = PNG_FILTER_PAETH; break;
1139
1203
default: png_ptr->do_filter = (png_byte)filters; break;
1141
1205
default: png_warning(png_ptr, "Unknown row filter for method 0");
1142
#endif /* PNG_NO_WRITE_FILTER */
1206
#endif /* PNG_WRITE_FILTER_SUPPORTED */
1145
1209
/* If we have allocated the row_buf, this means we have already started
1430
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1500
#ifdef PNG_INFO_IMAGE_SUPPORTED
1432
1502
png_write_png(png_structp png_ptr, png_infop info_ptr,
1433
1503
int transforms, voidp params)
1435
1505
if (png_ptr == NULL || info_ptr == NULL)
1437
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
1438
/* invert the alpha channel from opacity to transparency */
1439
if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
1440
png_set_invert_alpha(png_ptr);
1443
1508
/* Write the file header information. */
1444
1509
png_write_info(png_ptr, info_ptr);
1446
1511
/* ------ these transformations don't touch the info structure ------- */
1448
#if defined(PNG_WRITE_INVERT_SUPPORTED)
1449
/* invert monochrome pixels */
1513
#ifdef PNG_WRITE_INVERT_SUPPORTED
1514
/* Invert monochrome pixels */
1450
1515
if (transforms & PNG_TRANSFORM_INVERT_MONO)
1451
png_set_invert_mono(png_ptr);
1516
png_set_invert_mono(png_ptr);
1454
#if defined(PNG_WRITE_SHIFT_SUPPORTED)
1519
#ifdef PNG_WRITE_SHIFT_SUPPORTED
1455
1520
/* Shift the pixels up to a legal bit depth and fill in
1456
1521
* as appropriate to correctly scale the image.
1458
1523
if ((transforms & PNG_TRANSFORM_SHIFT)
1459
1524
&& (info_ptr->valid & PNG_INFO_sBIT))
1460
png_set_shift(png_ptr, &info_ptr->sig_bit);
1525
png_set_shift(png_ptr, &info_ptr->sig_bit);
1463
#if defined(PNG_WRITE_PACK_SUPPORTED)
1464
/* pack pixels into bytes */
1528
#ifdef PNG_WRITE_PACK_SUPPORTED
1529
/* Pack pixels into bytes */
1465
1530
if (transforms & PNG_TRANSFORM_PACKING)
1466
1531
png_set_packing(png_ptr);
1469
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
1470
/* swap location of alpha bytes from ARGB to RGBA */
1534
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
1535
/* Swap location of alpha bytes from ARGB to RGBA */
1471
1536
if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
1472
png_set_swap_alpha(png_ptr);
1475
#if defined(PNG_WRITE_FILLER_SUPPORTED)
1476
/* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
1477
* RGB (4 channels -> 3 channels). The second parameter is not used.
1479
if (transforms & PNG_TRANSFORM_STRIP_FILLER)
1480
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1483
#if defined(PNG_WRITE_BGR_SUPPORTED)
1484
/* flip BGR pixels to RGB */
1537
png_set_swap_alpha(png_ptr);
1540
#ifdef PNG_WRITE_FILLER_SUPPORTED
1541
/* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */
1542
if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
1543
png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
1544
else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
1545
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
1548
#ifdef PNG_WRITE_BGR_SUPPORTED
1549
/* Flip BGR pixels to RGB */
1485
1550
if (transforms & PNG_TRANSFORM_BGR)
1486
png_set_bgr(png_ptr);
1551
png_set_bgr(png_ptr);
1489
#if defined(PNG_WRITE_SWAP_SUPPORTED)
1490
/* swap bytes of 16-bit files to most significant byte first */
1554
#ifdef PNG_WRITE_SWAP_SUPPORTED
1555
/* Swap bytes of 16-bit files to most significant byte first */
1491
1556
if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
1492
png_set_swap(png_ptr);
1557
png_set_swap(png_ptr);
1495
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
1496
/* swap bits of 1, 2, 4 bit packed pixel formats */
1560
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
1561
/* Swap bits of 1, 2, 4 bit packed pixel formats */
1497
1562
if (transforms & PNG_TRANSFORM_PACKSWAP)
1498
png_set_packswap(png_ptr);
1563
png_set_packswap(png_ptr);
1566
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
1567
/* Invert the alpha channel from opacity to transparency */
1568
if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
1569
png_set_invert_alpha(png_ptr);
1501
1572
/* ----------------------- end of transformations ------------------- */
1503
/* write the bits */
1574
/* Write the bits */
1504
1575
if (info_ptr->valid & PNG_INFO_IDAT)
1505
1576
png_write_image(png_ptr, info_ptr->row_pointers);
1507
1578
/* It is REQUIRED to call this to finish writing the rest of the file */
1508
1579
png_write_end(png_ptr, info_ptr);
1510
transforms = transforms; /* quiet compiler warnings */
1581
transforms = transforms; /* Quiet compiler warnings */
1511
1582
params = params;