2 /* pngwrite.c - general routines to write a PNG file
4 * libpng 1.0.3 - January 14, 1999
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
8 * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
11 /* get internal access to png.h */
15 /* Writes all the PNG information. This is the suggested way to use the
16 * library. If you have a new chunk to add, make a function to write it,
17 * and put it in the correct location here. If you want the chunk written
18 * after the image data, put it in png_write_end(). I strongly encourage
19 * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
20 * the chunk, as that will keep the code from breaking if you want to just
21 * write a plain PNG file. If you have long comments, I suggest writing
22 * them in png_write_end(), and compressing them.
25 png_write_info(png_structp png_ptr
, png_infop info_ptr
)
27 #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
31 png_debug(1, "in png_write_info\n");
32 png_write_sig(png_ptr
); /* write PNG signature */
33 /* write IHDR information. */
34 png_write_IHDR(png_ptr
, info_ptr
->width
, info_ptr
->height
,
35 info_ptr
->bit_depth
, info_ptr
->color_type
, info_ptr
->compression_type
,
36 info_ptr
->filter_type
,
37 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
38 info_ptr
->interlace_type
);
42 /* the rest of these check to see if the valid field has the appropriate
43 flag set, and if it does, writes the chunk. */
44 #if defined(PNG_WRITE_gAMA_SUPPORTED)
45 if (info_ptr
->valid
& PNG_INFO_gAMA
)
46 png_write_gAMA(png_ptr
, info_ptr
->gamma
);
48 #if defined(PNG_WRITE_sRGB_SUPPORTED)
49 if (info_ptr
->valid
& PNG_INFO_sRGB
)
50 png_write_sRGB(png_ptr
, (int)info_ptr
->srgb_intent
);
52 #if defined(PNG_WRITE_sBIT_SUPPORTED)
53 if (info_ptr
->valid
& PNG_INFO_sBIT
)
54 png_write_sBIT(png_ptr
, &(info_ptr
->sig_bit
), info_ptr
->color_type
);
56 #if defined(PNG_WRITE_cHRM_SUPPORTED)
57 if (info_ptr
->valid
& PNG_INFO_cHRM
)
58 png_write_cHRM(png_ptr
,
59 info_ptr
->x_white
, info_ptr
->y_white
,
60 info_ptr
->x_red
, info_ptr
->y_red
,
61 info_ptr
->x_green
, info_ptr
->y_green
,
62 info_ptr
->x_blue
, info_ptr
->y_blue
);
64 if (info_ptr
->valid
& PNG_INFO_PLTE
)
65 png_write_PLTE(png_ptr
, info_ptr
->palette
,
66 (png_uint_32
)info_ptr
->num_palette
);
67 else if (info_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
68 png_error(png_ptr
, "Valid palette required for paletted images\n");
70 #if defined(PNG_WRITE_tRNS_SUPPORTED)
71 if (info_ptr
->valid
& PNG_INFO_tRNS
)
73 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
74 /* invert the alpha channel (in tRNS) */
75 if (png_ptr
->transformations
& PNG_INVERT_ALPHA
&&
76 info_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
)
79 for (j
=0; j
<(int)info_ptr
->num_trans
; j
++)
80 info_ptr
->trans
[j
] = 255 - info_ptr
->trans
[j
];
83 png_write_tRNS(png_ptr
, info_ptr
->trans
, &(info_ptr
->trans_values
),
84 info_ptr
->num_trans
, info_ptr
->color_type
);
87 #if defined(PNG_WRITE_bKGD_SUPPORTED)
88 if (info_ptr
->valid
& PNG_INFO_bKGD
)
89 png_write_bKGD(png_ptr
, &(info_ptr
->background
), info_ptr
->color_type
);
91 #if defined(PNG_WRITE_hIST_SUPPORTED)
92 if (info_ptr
->valid
& PNG_INFO_hIST
)
93 png_write_hIST(png_ptr
, info_ptr
->hist
, info_ptr
->num_palette
);
95 #if defined(PNG_WRITE_oFFs_SUPPORTED)
96 if (info_ptr
->valid
& PNG_INFO_oFFs
)
97 png_write_oFFs(png_ptr
, info_ptr
->x_offset
, info_ptr
->y_offset
,
98 info_ptr
->offset_unit_type
);
100 #if defined(PNG_WRITE_pCAL_SUPPORTED)
101 if (info_ptr
->valid
& PNG_INFO_pCAL
)
102 png_write_pCAL(png_ptr
, info_ptr
->pcal_purpose
, info_ptr
->pcal_X0
,
103 info_ptr
->pcal_X1
, info_ptr
->pcal_type
, info_ptr
->pcal_nparams
,
104 info_ptr
->pcal_units
, info_ptr
->pcal_params
);
106 #if defined(PNG_WRITE_pHYs_SUPPORTED)
107 if (info_ptr
->valid
& PNG_INFO_pHYs
)
108 png_write_pHYs(png_ptr
, info_ptr
->x_pixels_per_unit
,
109 info_ptr
->y_pixels_per_unit
, info_ptr
->phys_unit_type
);
111 #if defined(PNG_WRITE_tIME_SUPPORTED)
112 if (info_ptr
->valid
& PNG_INFO_tIME
)
114 png_write_tIME(png_ptr
, &(info_ptr
->mod_time
));
115 png_ptr
->flags
|= PNG_FLAG_WROTE_tIME
;
118 #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
119 /* Check to see if we need to write text chunks */
120 for (i
= 0; i
< info_ptr
->num_text
; i
++)
122 png_debug2(2, "Writing header text chunk %d, type %d\n", i
,
123 info_ptr
->text
[i
].compression
);
124 /* If we want a compressed text chunk */
125 if (info_ptr
->text
[i
].compression
>= PNG_TEXT_COMPRESSION_zTXt
)
127 #if defined(PNG_WRITE_zTXt_SUPPORTED)
128 /* write compressed chunk */
129 png_write_zTXt(png_ptr
, info_ptr
->text
[i
].key
,
130 info_ptr
->text
[i
].text
, info_ptr
->text
[i
].text_length
,
131 info_ptr
->text
[i
].compression
);
133 png_warning(png_ptr
, "Unable to write compressed text\n");
135 /* Mark this chunk as written */
136 info_ptr
->text
[i
].compression
= PNG_TEXT_COMPRESSION_zTXt_WR
;
138 else if (info_ptr
->text
[i
].compression
== PNG_TEXT_COMPRESSION_NONE
)
140 #if defined(PNG_WRITE_tEXt_SUPPORTED)
141 /* write uncompressed chunk */
142 png_write_tEXt(png_ptr
, info_ptr
->text
[i
].key
,
143 info_ptr
->text
[i
].text
, info_ptr
->text
[i
].text_length
);
145 png_warning(png_ptr
, "Unable to write uncompressed text\n");
147 /* Mark this chunk as written */
148 info_ptr
->text
[i
].compression
= PNG_TEXT_COMPRESSION_NONE_WR
;
154 /* Writes the end of the PNG file. If you don't want to write comments or
155 * time information, you can pass NULL for info. If you already wrote these
156 * in png_write_info(), do not write them again here. If you have long
157 * comments, I suggest writing them here, and compressing them.
160 png_write_end(png_structp png_ptr
, png_infop info_ptr
)
162 png_debug(1, "in png_write_end\n");
163 if (!(png_ptr
->mode
& PNG_HAVE_IDAT
))
164 png_error(png_ptr
, "No IDATs written into file");
166 /* see if user wants us to write information chunks */
167 if (info_ptr
!= NULL
)
169 #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
170 int i
; /* local index variable */
172 #if defined(PNG_WRITE_tIME_SUPPORTED)
173 /* check to see if user has supplied a time chunk */
174 if (info_ptr
->valid
& PNG_INFO_tIME
&&
175 !(png_ptr
->flags
& PNG_FLAG_WROTE_tIME
))
176 png_write_tIME(png_ptr
, &(info_ptr
->mod_time
));
178 #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
179 /* loop through comment chunks */
180 for (i
= 0; i
< info_ptr
->num_text
; i
++)
182 png_debug2(2, "Writing trailer text chunk %d, type %d\n", i
,
183 info_ptr
->text
[i
].compression
);
184 if (info_ptr
->text
[i
].compression
>= PNG_TEXT_COMPRESSION_zTXt
)
186 #if defined(PNG_WRITE_zTXt_SUPPORTED)
187 /* write compressed chunk */
188 png_write_zTXt(png_ptr
, info_ptr
->text
[i
].key
,
189 info_ptr
->text
[i
].text
, info_ptr
->text
[i
].text_length
,
190 info_ptr
->text
[i
].compression
);
192 png_warning(png_ptr
, "Unable to write compressed text\n");
194 /* Mark this chunk as written */
195 info_ptr
->text
[i
].compression
= PNG_TEXT_COMPRESSION_zTXt_WR
;
197 else if (info_ptr
->text
[i
].compression
== PNG_TEXT_COMPRESSION_NONE
)
199 #if defined(PNG_WRITE_tEXt_SUPPORTED)
200 /* write uncompressed chunk */
201 png_write_tEXt(png_ptr
, info_ptr
->text
[i
].key
,
202 info_ptr
->text
[i
].text
, info_ptr
->text
[i
].text_length
);
204 png_warning(png_ptr
, "Unable to write uncompressed text\n");
207 /* Mark this chunk as written */
208 info_ptr
->text
[i
].compression
= PNG_TEXT_COMPRESSION_NONE_WR
;
214 png_ptr
->mode
|= PNG_AFTER_IDAT
;
216 /* write end of PNG file */
217 png_write_IEND(png_ptr
);
220 #if defined(PNG_WRITE_tIME_SUPPORTED)
222 png_convert_from_struct_tm(png_timep ptime
, struct tm FAR
* ttime
)
224 png_debug(1, "in png_convert_from_struct_tm\n");
225 ptime
->year
= (png_uint_16
)(1900 + ttime
->tm_year
);
226 ptime
->month
= (png_byte
)(ttime
->tm_mon
+ 1);
227 ptime
->day
= (png_byte
)ttime
->tm_mday
;
228 ptime
->hour
= (png_byte
)ttime
->tm_hour
;
229 ptime
->minute
= (png_byte
)ttime
->tm_min
;
230 ptime
->second
= (png_byte
)ttime
->tm_sec
;
234 png_convert_from_time_t(png_timep ptime
, time_t ttime
)
238 png_debug(1, "in png_convert_from_time_t\n");
239 tbuf
= gmtime(&ttime
);
240 png_convert_from_struct_tm(ptime
, tbuf
);
244 /* Initialize png_ptr structure, and allocate any memory needed */
246 png_create_write_struct(png_const_charp user_png_ver
, png_voidp error_ptr
,
247 png_error_ptr error_fn
, png_error_ptr warn_fn
)
249 #ifdef PNG_USER_MEM_SUPPORTED
250 return (png_create_write_struct_2(user_png_ver
, error_ptr
, error_fn
,
251 warn_fn
, NULL
, NULL
, NULL
));
254 /* Alternate initialize png_ptr structure, and allocate any memory needed */
256 png_create_write_struct_2(png_const_charp user_png_ver
, png_voidp error_ptr
,
257 png_error_ptr error_fn
, png_error_ptr warn_fn
, png_voidp mem_ptr
,
258 png_malloc_ptr malloc_fn
, png_free_ptr free_fn
)
260 #endif /* PNG_USER_MEM_SUPPORTED */
262 #ifdef USE_FAR_KEYWORD
265 png_debug(1, "in png_create_write_struct\n");
266 #ifdef PNG_USER_MEM_SUPPORTED
267 if ((png_ptr
= (png_structp
)png_create_struct_2(PNG_STRUCT_PNG
,
268 (png_malloc_ptr
)malloc_fn
)) == NULL
)
270 if ((png_ptr
= (png_structp
)png_create_struct(PNG_STRUCT_PNG
)) == NULL
)
271 #endif /* PNG_USER_MEM_SUPPORTED */
273 return ((png_structp
)NULL
);
275 #ifdef USE_FAR_KEYWORD
278 if (setjmp(png_ptr
->jmpbuf
))
281 png_free(png_ptr
, png_ptr
->zbuf
);
282 png_destroy_struct(png_ptr
);
283 return ((png_structp
)NULL
);
285 #ifdef USE_FAR_KEYWORD
286 png_memcpy(png_ptr
->jmpbuf
,jmpbuf
,sizeof(jmp_buf));
288 #ifdef PNG_USER_MEM_SUPPORTED
289 png_set_mem_fn(png_ptr
, mem_ptr
, malloc_fn
, free_fn
);
290 #endif /* PNG_USER_MEM_SUPPORTED */
291 png_set_error_fn(png_ptr
, error_ptr
, error_fn
, warn_fn
);
293 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
294 * we must recompile any applications that use any older library version.
295 * For versions after libpng 1.0, we will be compatible, so we need
296 * only check the first digit.
298 if (user_png_ver
== NULL
|| user_png_ver
[0] != png_libpng_ver
[0] ||
299 (png_libpng_ver
[0] == '0' && user_png_ver
[2] < '9'))
302 "Incompatible libpng version in application and library");
305 /* initialize zbuf - compression buffer */
306 png_ptr
->zbuf_size
= PNG_ZBUF_SIZE
;
307 png_ptr
->zbuf
= (png_bytep
)png_malloc(png_ptr
,
308 (png_uint_32
)png_ptr
->zbuf_size
);
310 png_set_write_fn(png_ptr
, NULL
, NULL
, NULL
);
312 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
313 png_set_filter_heuristics(png_ptr
, PNG_FILTER_HEURISTIC_DEFAULT
,
317 return ((png_structp
)png_ptr
);
320 /* Initialize png_ptr structure, and allocate any memory needed */
322 png_write_init(png_structp png_ptr
)
324 jmp_buf tmp_jmp
; /* to save current jump buffer */
326 png_debug(1, "in png_write_init\n");
327 /* save jump buffer and error functions */
328 png_memcpy(tmp_jmp
, png_ptr
->jmpbuf
, sizeof (jmp_buf));
330 /* reset all variables to 0 */
331 png_memset(png_ptr
, 0, sizeof (png_struct
));
333 /* restore jump buffer */
334 png_memcpy(png_ptr
->jmpbuf
, tmp_jmp
, sizeof (jmp_buf));
336 /* initialize zbuf - compression buffer */
337 png_ptr
->zbuf_size
= PNG_ZBUF_SIZE
;
338 png_ptr
->zbuf
= (png_bytep
)png_malloc(png_ptr
,
339 (png_uint_32
)png_ptr
->zbuf_size
);
340 png_set_write_fn(png_ptr
, NULL
, NULL
, NULL
);
342 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
343 png_set_filter_heuristics(png_ptr
, PNG_FILTER_HEURISTIC_DEFAULT
,
348 /* Write a few rows of image data. If the image is interlaced,
349 * either you will have to write the 7 sub images, or, if you
350 * have called png_set_interlace_handling(), you will have to
351 * "write" the image seven times.
354 png_write_rows(png_structp png_ptr
, png_bytepp row
,
355 png_uint_32 num_rows
)
357 png_uint_32 i
; /* row counter */
358 png_bytepp rp
; /* row pointer */
360 png_debug(1, "in png_write_rows\n");
361 /* loop through the rows */
362 for (i
= 0, rp
= row
; i
< num_rows
; i
++, rp
++)
364 png_write_row(png_ptr
, *rp
);
368 /* Write the image. You only need to call this function once, even
369 * if you are writing an interlaced image.
372 png_write_image(png_structp png_ptr
, png_bytepp image
)
374 png_uint_32 i
; /* row index */
375 int pass
, num_pass
; /* pass variables */
376 png_bytepp rp
; /* points to current row */
378 png_debug(1, "in png_write_image\n");
379 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
380 /* intialize interlace handling. If image is not interlaced,
381 this will set pass to 1 */
382 num_pass
= png_set_interlace_handling(png_ptr
);
386 /* loop through passes */
387 for (pass
= 0; pass
< num_pass
; pass
++)
389 /* loop through image */
390 for (i
= 0, rp
= image
; i
< png_ptr
->height
; i
++, rp
++)
392 png_write_row(png_ptr
, *rp
);
397 /* called by user to write a row of image data */
399 png_write_row(png_structp png_ptr
, png_bytep row
)
401 png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
402 png_ptr
->row_number
, png_ptr
->pass
);
403 /* initialize transformations and other stuff if first time */
404 if (png_ptr
->row_number
== 0 && png_ptr
->pass
== 0)
406 /* check for transforms that have been set but were defined out */
407 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
408 if (png_ptr
->transformations
& PNG_INVERT_MONO
)
409 png_warning(png_ptr
, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
411 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
412 if (png_ptr
->transformations
& PNG_FILLER
)
413 png_warning(png_ptr
, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
415 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
416 if (png_ptr
->transformations
& PNG_PACKSWAP
)
417 png_warning(png_ptr
, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
419 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
420 if (png_ptr
->transformations
& PNG_PACK
)
421 png_warning(png_ptr
, "PNG_WRITE_PACK_SUPPORTED is not defined.");
423 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
424 if (png_ptr
->transformations
& PNG_SHIFT
)
425 png_warning(png_ptr
, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
427 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
428 if (png_ptr
->transformations
& PNG_BGR
)
429 png_warning(png_ptr
, "PNG_WRITE_BGR_SUPPORTED is not defined.");
431 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
432 if (png_ptr
->transformations
& PNG_SWAP_BYTES
)
433 png_warning(png_ptr
, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
436 png_write_start_row(png_ptr
);
439 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
440 /* if interlaced and not interested in row, return */
441 if (png_ptr
->interlaced
&& (png_ptr
->transformations
& PNG_INTERLACE
))
443 switch (png_ptr
->pass
)
446 if (png_ptr
->row_number
& 7)
448 png_write_finish_row(png_ptr
);
453 if ((png_ptr
->row_number
& 7) || png_ptr
->width
< 5)
455 png_write_finish_row(png_ptr
);
460 if ((png_ptr
->row_number
& 7) != 4)
462 png_write_finish_row(png_ptr
);
467 if ((png_ptr
->row_number
& 3) || png_ptr
->width
< 3)
469 png_write_finish_row(png_ptr
);
474 if ((png_ptr
->row_number
& 3) != 2)
476 png_write_finish_row(png_ptr
);
481 if ((png_ptr
->row_number
& 1) || png_ptr
->width
< 2)
483 png_write_finish_row(png_ptr
);
488 if (!(png_ptr
->row_number
& 1))
490 png_write_finish_row(png_ptr
);
498 /* set up row info for transformations */
499 png_ptr
->row_info
.color_type
= png_ptr
->color_type
;
500 png_ptr
->row_info
.width
= png_ptr
->usr_width
;
501 png_ptr
->row_info
.channels
= png_ptr
->usr_channels
;
502 png_ptr
->row_info
.bit_depth
= png_ptr
->usr_bit_depth
;
503 png_ptr
->row_info
.pixel_depth
= (png_byte
)(png_ptr
->row_info
.bit_depth
*
504 png_ptr
->row_info
.channels
);
506 png_ptr
->row_info
.rowbytes
= ((png_ptr
->row_info
.width
*
507 (png_uint_32
)png_ptr
->row_info
.pixel_depth
+ 7) >> 3);
509 png_debug1(3, "row_info->color_type = %d\n", png_ptr
->row_info
.color_type
);
510 png_debug1(3, "row_info->width = %d\n", png_ptr
->row_info
.width
);
511 png_debug1(3, "row_info->channels = %d\n", png_ptr
->row_info
.channels
);
512 png_debug1(3, "row_info->bit_depth = %d\n", png_ptr
->row_info
.bit_depth
);
513 png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr
->row_info
.pixel_depth
);
514 png_debug1(3, "row_info->rowbytes = %d\n", png_ptr
->row_info
.rowbytes
);
516 /* Copy user's row into buffer, leaving room for filter byte. */
517 png_memcpy_check(png_ptr
, png_ptr
->row_buf
+ 1, row
,
518 png_ptr
->row_info
.rowbytes
);
520 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
521 /* handle interlacing */
522 if (png_ptr
->interlaced
&& png_ptr
->pass
< 6 &&
523 (png_ptr
->transformations
& PNG_INTERLACE
))
525 png_do_write_interlace(&(png_ptr
->row_info
),
526 png_ptr
->row_buf
+ 1, png_ptr
->pass
);
527 /* this should always get caught above, but still ... */
528 if (!(png_ptr
->row_info
.width
))
530 png_write_finish_row(png_ptr
);
536 /* handle other transformations */
537 if (png_ptr
->transformations
)
538 png_do_write_transformations(png_ptr
);
540 /* Find a filter if necessary, filter the row and write it out. */
541 png_write_find_filter(png_ptr
, &(png_ptr
->row_info
));
543 if (png_ptr
->write_row_fn
!= NULL
)
544 (*(png_ptr
->write_row_fn
))(png_ptr
, png_ptr
->row_number
, png_ptr
->pass
);
547 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
548 /* Set the automatic flush interval or 0 to turn flushing off */
550 png_set_flush(png_structp png_ptr
, int nrows
)
552 png_debug(1, "in png_set_flush\n");
553 png_ptr
->flush_dist
= (nrows
< 0 ? 0 : nrows
);
556 /* flush the current output buffers now */
558 png_write_flush(png_structp png_ptr
)
562 png_debug(1, "in png_write_flush\n");
563 /* We have already written out all of the data */
564 if (png_ptr
->row_number
>= png_ptr
->num_rows
)
571 /* compress the data */
572 ret
= deflate(&png_ptr
->zstream
, Z_SYNC_FLUSH
);
575 /* check for compression errors */
578 if (png_ptr
->zstream
.msg
!= NULL
)
579 png_error(png_ptr
, png_ptr
->zstream
.msg
);
581 png_error(png_ptr
, "zlib error");
584 if (!(png_ptr
->zstream
.avail_out
))
586 /* write the IDAT and reset the zlib output buffer */
587 png_write_IDAT(png_ptr
, png_ptr
->zbuf
,
589 png_ptr
->zstream
.next_out
= png_ptr
->zbuf
;
590 png_ptr
->zstream
.avail_out
= (uInt
)png_ptr
->zbuf_size
;
593 } while(wrote_IDAT
== 1);
595 /* If there is any data left to be output, write it into a new IDAT */
596 if (png_ptr
->zbuf_size
!= png_ptr
->zstream
.avail_out
)
598 /* write the IDAT and reset the zlib output buffer */
599 png_write_IDAT(png_ptr
, png_ptr
->zbuf
,
600 png_ptr
->zbuf_size
- png_ptr
->zstream
.avail_out
);
601 png_ptr
->zstream
.next_out
= png_ptr
->zbuf
;
602 png_ptr
->zstream
.avail_out
= (uInt
)png_ptr
->zbuf_size
;
604 png_ptr
->flush_rows
= 0;
607 #endif /* PNG_WRITE_FLUSH_SUPPORTED */
609 /* free all memory used by the write */
611 png_destroy_write_struct(png_structpp png_ptr_ptr
, png_infopp info_ptr_ptr
)
613 png_structp png_ptr
= NULL
;
614 png_infop info_ptr
= NULL
;
615 #ifdef PNG_USER_MEM_SUPPORTED
616 png_free_ptr free_fn
= NULL
;
619 png_debug(1, "in png_destroy_write_struct\n");
620 if (png_ptr_ptr
!= NULL
)
622 png_ptr
= *png_ptr_ptr
;
623 #ifdef PNG_USER_MEM_SUPPORTED
624 free_fn
= png_ptr
->free_fn
;
628 if (info_ptr_ptr
!= NULL
)
629 info_ptr
= *info_ptr_ptr
;
631 if (info_ptr
!= NULL
)
633 #ifdef PNG_WRITE_tEXt_SUPPORTED
634 png_free(png_ptr
, info_ptr
->text
);
636 #if defined(PNG_READ_pCAL_SUPPORTED)
637 png_free(png_ptr
, info_ptr
->pcal_purpose
);
638 png_free(png_ptr
, info_ptr
->pcal_units
);
639 if (info_ptr
->pcal_params
!= NULL
)
642 for (i
= 0; i
< (int)info_ptr
->pcal_nparams
; i
++)
644 png_free(png_ptr
, info_ptr
->pcal_params
[i
]);
646 png_free(png_ptr
, info_ptr
->pcal_params
);
649 #ifdef PNG_USER_MEM_SUPPORTED
650 png_destroy_struct_2((png_voidp
)info_ptr
, free_fn
);
652 png_destroy_struct((png_voidp
)info_ptr
);
654 *info_ptr_ptr
= (png_infop
)NULL
;
659 png_write_destroy(png_ptr
);
660 #ifdef PNG_USER_MEM_SUPPORTED
661 png_destroy_struct_2((png_voidp
)png_ptr
, free_fn
);
663 png_destroy_struct((png_voidp
)png_ptr
);
665 *png_ptr_ptr
= (png_structp
)NULL
;
670 /* Free any memory used in png_ptr struct (old method) */
672 png_write_destroy(png_structp png_ptr
)
674 jmp_buf tmp_jmp
; /* save jump buffer */
675 png_error_ptr error_fn
;
676 png_error_ptr warning_fn
;
678 #ifdef PNG_USER_MEM_SUPPORTED
679 png_free_ptr free_fn
;
682 png_debug(1, "in png_write_destroy\n");
683 /* free any memory zlib uses */
684 deflateEnd(&png_ptr
->zstream
);
686 /* free our memory. png_free checks NULL for us. */
687 png_free(png_ptr
, png_ptr
->zbuf
);
688 png_free(png_ptr
, png_ptr
->row_buf
);
689 png_free(png_ptr
, png_ptr
->prev_row
);
690 png_free(png_ptr
, png_ptr
->sub_row
);
691 png_free(png_ptr
, png_ptr
->up_row
);
692 png_free(png_ptr
, png_ptr
->avg_row
);
693 png_free(png_ptr
, png_ptr
->paeth_row
);
694 #if defined(PNG_TIME_RFC1123_SUPPORTED)
695 png_free(png_ptr
, png_ptr
->time_buffer
);
696 #endif /* PNG_TIME_RFC1123_SUPPORTED */
697 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
698 png_free(png_ptr
, png_ptr
->prev_filters
);
699 png_free(png_ptr
, png_ptr
->filter_weights
);
700 png_free(png_ptr
, png_ptr
->inv_filter_weights
);
701 png_free(png_ptr
, png_ptr
->filter_costs
);
702 png_free(png_ptr
, png_ptr
->inv_filter_costs
);
703 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
705 /* reset structure */
706 png_memcpy(tmp_jmp
, png_ptr
->jmpbuf
, sizeof (jmp_buf));
708 error_fn
= png_ptr
->error_fn
;
709 warning_fn
= png_ptr
->warning_fn
;
710 error_ptr
= png_ptr
->error_ptr
;
711 #ifdef PNG_USER_MEM_SUPPORTED
712 free_fn
= png_ptr
->free_fn
;
715 png_memset(png_ptr
, 0, sizeof (png_struct
));
717 png_ptr
->error_fn
= error_fn
;
718 png_ptr
->warning_fn
= warning_fn
;
719 png_ptr
->error_ptr
= error_ptr
;
720 #ifdef PNG_USER_MEM_SUPPORTED
721 png_ptr
->free_fn
= free_fn
;
724 png_memcpy(png_ptr
->jmpbuf
, tmp_jmp
, sizeof (jmp_buf));
727 /* Allow the application to select one or more row filters to use. */
729 png_set_filter(png_structp png_ptr
, int method
, int filters
)
731 png_debug(1, "in png_set_filter\n");
732 /* We allow 'method' only for future expansion of the base filter method. */
733 if (method
== PNG_FILTER_TYPE_BASE
)
735 switch (filters
& (PNG_ALL_FILTERS
| 0x07))
739 case 7: png_warning(png_ptr
, "Unknown row filter for method 0");
740 case PNG_FILTER_VALUE_NONE
: png_ptr
->do_filter
=PNG_FILTER_NONE
; break;
741 case PNG_FILTER_VALUE_SUB
: png_ptr
->do_filter
=PNG_FILTER_SUB
; break;
742 case PNG_FILTER_VALUE_UP
: png_ptr
->do_filter
=PNG_FILTER_UP
; break;
743 case PNG_FILTER_VALUE_AVG
: png_ptr
->do_filter
=PNG_FILTER_AVG
; break;
744 case PNG_FILTER_VALUE_PAETH
: png_ptr
->do_filter
=PNG_FILTER_PAETH
;break;
745 default: png_ptr
->do_filter
= (png_byte
)filters
; break;
748 /* If we have allocated the row_buf, this means we have already started
749 * with the image and we should have allocated all of the filter buffers
750 * that have been selected. If prev_row isn't already allocated, then
751 * it is too late to start using the filters that need it, since we
752 * will be missing the data in the previous row. If an application
753 * wants to start and stop using particular filters during compression,
754 * it should start out with all of the filters, and then add and
755 * remove them after the start of compression.
757 if (png_ptr
->row_buf
!= NULL
)
759 if (png_ptr
->do_filter
& PNG_FILTER_SUB
&& png_ptr
->sub_row
== NULL
)
761 png_ptr
->sub_row
= (png_bytep
)png_malloc(png_ptr
,
762 (png_ptr
->rowbytes
+ 1));
763 png_ptr
->sub_row
[0] = PNG_FILTER_VALUE_SUB
;
766 if (png_ptr
->do_filter
& PNG_FILTER_UP
&& png_ptr
->up_row
== NULL
)
768 if (png_ptr
->prev_row
== NULL
)
770 png_warning(png_ptr
, "Can't add Up filter after starting");
771 png_ptr
->do_filter
&= ~PNG_FILTER_UP
;
775 png_ptr
->up_row
= (png_bytep
)png_malloc(png_ptr
,
776 (png_ptr
->rowbytes
+ 1));
777 png_ptr
->up_row
[0] = PNG_FILTER_VALUE_UP
;
781 if (png_ptr
->do_filter
& PNG_FILTER_AVG
&& png_ptr
->avg_row
== NULL
)
783 if (png_ptr
->prev_row
== NULL
)
785 png_warning(png_ptr
, "Can't add Average filter after starting");
786 png_ptr
->do_filter
&= ~PNG_FILTER_AVG
;
790 png_ptr
->avg_row
= (png_bytep
)png_malloc(png_ptr
,
791 (png_ptr
->rowbytes
+ 1));
792 png_ptr
->avg_row
[0] = PNG_FILTER_VALUE_AVG
;
796 if (png_ptr
->do_filter
& PNG_FILTER_PAETH
&&
797 png_ptr
->paeth_row
== NULL
)
799 if (png_ptr
->prev_row
== NULL
)
801 png_warning(png_ptr
, "Can't add Paeth filter after starting");
802 png_ptr
->do_filter
&= ~PNG_FILTER_PAETH
;
806 png_ptr
->paeth_row
= (png_bytep
)png_malloc(png_ptr
,
807 (png_ptr
->rowbytes
+ 1));
808 png_ptr
->paeth_row
[0] = PNG_FILTER_VALUE_PAETH
;
812 if (png_ptr
->do_filter
== PNG_NO_FILTERS
)
813 png_ptr
->do_filter
= PNG_FILTER_NONE
;
817 png_error(png_ptr
, "Unknown custom filter method");
820 /* This allows us to influence the way in which libpng chooses the "best"
821 * filter for the current scanline. While the "minimum-sum-of-absolute-
822 * differences metric is relatively fast and effective, there is some
823 * question as to whether it can be improved upon by trying to keep the
824 * filtered data going to zlib more consistent, hopefully resulting in
825 * better compression.
827 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */
829 png_set_filter_heuristics(png_structp png_ptr
, int heuristic_method
,
830 int num_weights
, png_doublep filter_weights
,
831 png_doublep filter_costs
)
835 png_debug(1, "in png_set_filter_heuristics\n");
836 if (heuristic_method
>= PNG_FILTER_HEURISTIC_LAST
)
838 png_warning(png_ptr
, "Unknown filter heuristic method");
842 if (heuristic_method
== PNG_FILTER_HEURISTIC_DEFAULT
)
844 heuristic_method
= PNG_FILTER_HEURISTIC_UNWEIGHTED
;
847 if (num_weights
< 0 || filter_weights
== NULL
||
848 heuristic_method
== PNG_FILTER_HEURISTIC_UNWEIGHTED
)
853 png_ptr
->num_prev_filters
= num_weights
;
854 png_ptr
->heuristic_method
= heuristic_method
;
858 if (png_ptr
->prev_filters
== NULL
)
860 png_ptr
->prev_filters
= (png_bytep
)png_malloc(png_ptr
,
861 (png_uint_32
)(sizeof(png_byte
) * num_weights
));
863 /* To make sure that the weighting starts out fairly */
864 for (i
= 0; i
< num_weights
; i
++)
866 png_ptr
->prev_filters
[i
] = 255;
870 if (png_ptr
->filter_weights
== NULL
)
872 png_ptr
->filter_weights
= (png_uint_16p
) png_malloc(png_ptr
,
873 (png_uint_32
)(sizeof(png_uint_16
) * num_weights
));
875 png_ptr
->inv_filter_weights
= (png_uint_16p
) png_malloc(png_ptr
,
876 (png_uint_32
)(sizeof(png_uint_16
) * num_weights
));
878 for (i
= 0; i
< num_weights
; i
++)
880 png_ptr
->inv_filter_weights
[i
] =
881 png_ptr
->filter_weights
[i
] = PNG_WEIGHT_FACTOR
;
885 for (i
= 0; i
< num_weights
; i
++)
887 if (filter_weights
[i
] < 0.0)
889 png_ptr
->inv_filter_weights
[i
] =
890 png_ptr
->filter_weights
[i
] = PNG_WEIGHT_FACTOR
;
894 png_ptr
->inv_filter_weights
[i
] =
895 (png_uint_16
)((double)PNG_WEIGHT_FACTOR
*filter_weights
[i
]+0.5);
896 png_ptr
->filter_weights
[i
] =
897 (png_uint_16
)((double)PNG_WEIGHT_FACTOR
/filter_weights
[i
]+0.5);
902 /* If, in the future, there are other filter methods, this would
903 * need to be based on png_ptr->filter.
905 if (png_ptr
->filter_costs
== NULL
)
907 png_ptr
->filter_costs
= (png_uint_16p
) png_malloc(png_ptr
,
908 (png_uint_32
)(sizeof(png_uint_16
) * PNG_FILTER_VALUE_LAST
));
910 png_ptr
->inv_filter_costs
= (png_uint_16p
) png_malloc(png_ptr
,
911 (png_uint_32
)(sizeof(png_uint_16
) * PNG_FILTER_VALUE_LAST
));
913 for (i
= 0; i
< PNG_FILTER_VALUE_LAST
; i
++)
915 png_ptr
->inv_filter_costs
[i
] =
916 png_ptr
->filter_costs
[i
] = PNG_COST_FACTOR
;
920 /* Here is where we set the relative costs of the different filters. We
921 * should take the desired compression level into account when setting
922 * the costs, so that Paeth, for instance, has a high relative cost at low
923 * compression levels, while it has a lower relative cost at higher
924 * compression settings. The filter types are in order of increasing
925 * relative cost, so it would be possible to do this with an algorithm.
927 for (i
= 0; i
< PNG_FILTER_VALUE_LAST
; i
++)
929 if (filter_costs
== NULL
|| filter_costs
[i
] < 0.0)
931 png_ptr
->inv_filter_costs
[i
] =
932 png_ptr
->filter_costs
[i
] = PNG_COST_FACTOR
;
934 else if (filter_costs
[i
] >= 1.0)
936 png_ptr
->inv_filter_costs
[i
] =
937 (png_uint_16
)((double)PNG_COST_FACTOR
/ filter_costs
[i
] + 0.5);
938 png_ptr
->filter_costs
[i
] =
939 (png_uint_16
)((double)PNG_COST_FACTOR
* filter_costs
[i
] + 0.5);
943 #endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
946 png_set_compression_level(png_structp png_ptr
, int level
)
948 png_debug(1, "in png_set_compression_level\n");
949 png_ptr
->flags
|= PNG_FLAG_ZLIB_CUSTOM_LEVEL
;
950 png_ptr
->zlib_level
= level
;
954 png_set_compression_mem_level(png_structp png_ptr
, int mem_level
)
956 png_debug(1, "in png_set_compression_mem_level\n");
957 png_ptr
->flags
|= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL
;
958 png_ptr
->zlib_mem_level
= mem_level
;
962 png_set_compression_strategy(png_structp png_ptr
, int strategy
)
964 png_debug(1, "in png_set_compression_strategy\n");
965 png_ptr
->flags
|= PNG_FLAG_ZLIB_CUSTOM_STRATEGY
;
966 png_ptr
->zlib_strategy
= strategy
;
970 png_set_compression_window_bits(png_structp png_ptr
, int window_bits
)
972 if (window_bits
> 15)
973 png_warning(png_ptr
, "Only compression windows <= 32k supported by PNG");
974 png_ptr
->flags
|= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS
;
975 png_ptr
->zlib_window_bits
= window_bits
;
979 png_set_compression_method(png_structp png_ptr
, int method
)
981 png_debug(1, "in png_set_compression_method\n");
983 png_warning(png_ptr
, "Only compression method 8 is supported by PNG");
984 png_ptr
->flags
|= PNG_FLAG_ZLIB_CUSTOM_METHOD
;
985 png_ptr
->zlib_method
= method
;
989 png_set_write_status_fn(png_structp png_ptr
, png_write_status_ptr write_row_fn
)
991 png_ptr
->write_row_fn
= write_row_fn
;
994 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
996 png_set_write_user_transform_fn(png_structp png_ptr
, png_user_transform_ptr
997 write_user_transform_fn
)
999 png_debug(1, "in png_set_write_user_transform_fn\n");
1000 png_ptr
->transformations
|= PNG_USER_TRANSFORM
;
1001 png_ptr
->write_user_transform_fn
= write_user_transform_fn
;