blob: 50ea96b7c513e51a9c5bffbb885d6df242acf115 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
2/* pngwrite.c - general routines to write a png file
3
Guy Schalnat51f0eb41995-09-26 05:22:39 -05004 libpng 1.0 beta 2 - version 0.81
Guy Schalnat0d580581995-07-20 02:43:20 -05005 For conditions of distribution and use, see copyright notice in png.h
6 Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
Guy Schalnat51f0eb41995-09-26 05:22:39 -05007 August 24, 1995
Guy Schalnat0d580581995-07-20 02:43:20 -05008 */
9
10/* get internal access to png.h */
11#define PNG_INTERNAL
12#include "png.h"
13
14/* Writes all the png information. This is the suggested way to use
15 the library. If you have a new chunk to add, make a function to
16 write it, and put it in the correct location here. If you want
17 the chunk written after the image data, put it in png_write_end().
18 I strongly encurage you to supply a PNG_INFO_ flag, and check
19 info->valid before writing the chunk, as that will keep the code
20 from breaking if you want to just write a plain png file.
21 If you have long comments, I suggest writing them in png_write_end(),
22 and compressing them. */
23void
24png_write_info(png_struct *png_ptr, png_info *info)
25{
26 png_write_sig(png_ptr); /* write PNG signature */
27 /* write IHDR information. */
28 png_write_IHDR(png_ptr, info->width, info->height, info->bit_depth,
29 info->color_type, info->compression_type, info->filter_type,
30 info->interlace_type);
31 /* the rest of these check to see if the valid field has the appropriate
32 flag set, and if it does, writes the chunk. */
Guy Schalnat51f0eb41995-09-26 05:22:39 -050033#if defined(PNG_WRITE_gAMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050034 if (info->valid & PNG_INFO_gAMA)
35 png_write_gAMA(png_ptr, info->gamma);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050036#endif
37#if defined(PNG_WRITE_sBIT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050038 if (info->valid & PNG_INFO_sBIT)
39 png_write_sBIT(png_ptr, &(info->sig_bit), info->color_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050040#endif
41#if defined(PNG_WRITE_cHRM_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050042 if (info->valid & PNG_INFO_cHRM)
43 png_write_cHRM(png_ptr,
44 info->x_white, info->y_white,
45 info->x_red, info->y_red,
46 info->x_green, info->y_green,
47 info->x_blue, info->y_blue);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050048#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050049 if (info->valid & PNG_INFO_PLTE)
50 png_write_PLTE(png_ptr, info->palette, info->num_palette);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050051#if defined(PNG_WRITE_tRNS_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050052 if (info->valid & PNG_INFO_tRNS)
53 png_write_tRNS(png_ptr, info->trans, &(info->trans_values),
54 info->num_trans, info->color_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050055#endif
56#if defined(PNG_WRITE_bKGD_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050057 if (info->valid & PNG_INFO_bKGD)
58 png_write_bKGD(png_ptr, &(info->background), info->color_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050059#endif
Guy Schalnat0f716451995-11-28 11:22:13 -060060
Guy Schalnat51f0eb41995-09-26 05:22:39 -050061#if defined(PNG_WRITE_hIST_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050062 if (info->valid & PNG_INFO_hIST)
63 png_write_hIST(png_ptr, info->hist, info->num_palette);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050064#endif
Guy Schalnat0f716451995-11-28 11:22:13 -060065
Guy Schalnat51f0eb41995-09-26 05:22:39 -050066#if defined(PNG_WRITE_pHYs_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050067 if (info->valid & PNG_INFO_pHYs)
68 png_write_pHYs(png_ptr, info->x_pixels_per_unit,
69 info->y_pixels_per_unit, info->phys_unit_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050070#endif
Guy Schalnat0f716451995-11-28 11:22:13 -060071
Guy Schalnat51f0eb41995-09-26 05:22:39 -050072#if defined(PNG_WRITE_oFFs_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050073 if (info->valid & PNG_INFO_oFFs)
74 png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
75 info->offset_unit_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050076#endif
Guy Schalnat0f716451995-11-28 11:22:13 -060077
Guy Schalnat51f0eb41995-09-26 05:22:39 -050078#if defined(PNG_WRITE_tIME_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050079 if (info->valid & PNG_INFO_tIME)
80 png_write_tIME(png_ptr, &(info->mod_time));
81 /* Check to see if we need to write text chunks */
Guy Schalnat51f0eb41995-09-26 05:22:39 -050082#endif
Guy Schalnat0f716451995-11-28 11:22:13 -060083
Guy Schalnat51f0eb41995-09-26 05:22:39 -050084#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -050085 if (info->num_text)
86 {
87 int i; /* local counter */
88
89 /* loop through the text chunks */
90 for (i = 0; i < info->num_text; i++)
91 {
Guy Schalnat0f716451995-11-28 11:22:13 -060092 if (strlen(info->text[i].key) > 80)
93 {
94 (*(png_ptr->warning_fn))(png_ptr,"tEXt keyword more than 80 chars");
95 continue;
96 }
97
Guy Schalnat0d580581995-07-20 02:43:20 -050098 /* if chunk is compressed */
99 if (info->text[i].compression >= 0)
100 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500101#if defined(PNG_WRITE_zTXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500102 /* write compressed chunk */
103 png_write_zTXt(png_ptr, info->text[i].key,
104 info->text[i].text, info->text[i].text_length,
105 info->text[i].compression);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500106#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500107 }
108 else
109 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500110#if defined(PNG_WRITE_tEXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500111 /* write uncompressed chunk */
112 png_write_tEXt(png_ptr, info->text[i].key,
113 info->text[i].text, info->text[i].text_length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500114#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500115 }
116 }
117 }
Guy Schalnat0f716451995-11-28 11:22:13 -0600118#endif /* PNG_WRITE_tEXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */
119 png_ptr->mode = PNG_HAVE_IHDR;
Guy Schalnat0d580581995-07-20 02:43:20 -0500120}
121
122/* writes the end of the png file. If you don't want to write comments or
123 time information, you can pass NULL for info. If you already wrote these
124 in png_write_info(), do not write them again here. If you have long
125 comments, I suggest writing them here, and compressing them. */
126void
127png_write_end(png_struct *png_ptr, png_info *info)
128{
Guy Schalnat0f716451995-11-28 11:22:13 -0600129 if (info && png_ptr->mode == PNG_AFTER_IEND)
130 return;
131
Guy Schalnat0d580581995-07-20 02:43:20 -0500132 /* see if user wants us to write information chunks */
133 if (info)
134 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500135#if defined(PNG_WRITE_tIME_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500136 /* check to see if user has supplied a time chunk */
137 if (info->valid & PNG_INFO_tIME)
138 png_write_tIME(png_ptr, &(info->mod_time));
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500139#endif
Guy Schalnat0f716451995-11-28 11:22:13 -0600140
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500141#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500142 /* check to see if we need to write comment chunks */
143 if (info->num_text)
144 {
145 int i; /* local index variable */
146
147 /* loop through comment chunks */
148 for (i = 0; i < info->num_text; i++)
149 {
150 /* check to see if comment is to be compressed */
151 if (info->text[i].compression >= 0)
152 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500153#if defined(PNG_WRITE_zTXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500154 /* write compressed chunk */
155 png_write_zTXt(png_ptr, info->text[i].key,
156 info->text[i].text, info->text[i].text_length,
157 info->text[i].compression);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500158#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500159 }
160 else
161 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500162#if defined(PNG_WRITE_tEXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500163 /* write uncompressed chunk */
164 png_write_tEXt(png_ptr, info->text[i].key,
165 info->text[i].text, info->text[i].text_length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500166#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500167 }
168 }
169 }
Guy Schalnat0f716451995-11-28 11:22:13 -0600170#endif /* PNG_WRITE_tEXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500171 }
172 /* write end of png file */
173 png_write_IEND(png_ptr);
Guy Schalnat0f716451995-11-28 11:22:13 -0600174
175 png_ptr->mode = PNG_AFTER_IEND;
Guy Schalnat0d580581995-07-20 02:43:20 -0500176}
177
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500178#if defined(PNG_WRITE_tIME_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500179void
180png_convert_from_struct_tm(png_time *ptime, struct tm *ttime)
181{
182 ptime->year = 1900 + ttime->tm_year;
183 ptime->month = ttime->tm_mon + 1;
184 ptime->day = ttime->tm_mday;
185 ptime->hour = ttime->tm_hour;
186 ptime->minute = ttime->tm_min;
187 ptime->second = ttime->tm_sec;
188}
189
190void
191png_convert_from_time_t(png_time *ptime, time_t ttime)
192{
193 struct tm *tbuf;
194
195 tbuf = gmtime(&ttime);
196 png_convert_from_struct_tm(ptime, tbuf);
197}
Guy Schalnat0f716451995-11-28 11:22:13 -0600198#endif /* PNG_WRITE_tIME_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500199
200/* initialize png structure, and allocate any memory needed */
201void
202png_write_init(png_struct *png_ptr)
203{
204 jmp_buf tmp_jmp; /* to save current jump buffer */
205
206 /* save jump buffer */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500207 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
Guy Schalnat0d580581995-07-20 02:43:20 -0500208 /* reset all variables to 0 */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500209 png_memset(png_ptr, 0, sizeof (png_struct));
Guy Schalnat0d580581995-07-20 02:43:20 -0500210 /* restore jump buffer */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500211 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
Guy Schalnat0d580581995-07-20 02:43:20 -0500212
213 /* initialize zbuf - compression buffer */
214 png_ptr->zbuf_size = PNG_ZBUF_SIZE;
215 png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500216}
217
218/* write a few rows of image data. If the image is interlaced,
219 either you will have to write the 7 sub images, or, if you
220 have called png_set_interlace_handling(), you will have to
221 "write" the image seven times */
222void
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500223png_write_rows(png_struct *png_ptr, png_bytef **row,
Guy Schalnat0d580581995-07-20 02:43:20 -0500224 png_uint_32 num_rows)
225{
226 png_uint_32 i; /* row counter */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500227 png_bytef **rp; /* row pointer */
Guy Schalnat0d580581995-07-20 02:43:20 -0500228
229 /* loop through the rows */
230 for (i = 0, rp = row; i < num_rows; i++, rp++)
231 {
232 png_write_row(png_ptr, *rp);
233 }
234}
235
236/* write the image. You only need to call this function once, even
237 if you are writing an interlaced image. */
238void
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500239png_write_image(png_struct *png_ptr, png_bytef **image)
Guy Schalnat0d580581995-07-20 02:43:20 -0500240{
241 png_uint_32 i; /* row index */
242 int pass, num_pass; /* pass variables */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500243 png_bytef **rp; /* points to current row */
Guy Schalnat0d580581995-07-20 02:43:20 -0500244
245 /* intialize interlace handling. If image is not interlaced,
246 this will set pass to 1 */
247 num_pass = png_set_interlace_handling(png_ptr);
248 /* loop through passes */
249 for (pass = 0; pass < num_pass; pass++)
250 {
251 /* loop through image */
252 for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
253 {
254 png_write_row(png_ptr, *rp);
255 }
256 }
257}
258
259/* write a row of image data */
260void
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500261png_write_row(png_struct *png_ptr, png_bytef *row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500262{
263 /* initialize transformations and other stuff if first time */
Guy Schalnat0f716451995-11-28 11:22:13 -0600264 if (png_ptr->mode < PNG_HAVE_IDAT)
Guy Schalnat0d580581995-07-20 02:43:20 -0500265 {
266 png_write_start_row(png_ptr);
267 }
268
Guy Schalnat0f716451995-11-28 11:22:13 -0600269 png_ptr->mode = PNG_HAVE_IDAT;
270
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500271#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500272 /* if interlaced and not interested in row, return */
273 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
274 {
275 switch (png_ptr->pass)
276 {
277 case 0:
278 if (png_ptr->row_number & 7)
279 {
280 png_write_finish_row(png_ptr);
281 return;
282 }
283 break;
284 case 1:
285 if ((png_ptr->row_number & 7) || png_ptr->width < 5)
286 {
287 png_write_finish_row(png_ptr);
288 return;
289 }
290 break;
291 case 2:
292 if ((png_ptr->row_number & 7) != 4)
293 {
294 png_write_finish_row(png_ptr);
295 return;
296 }
297 break;
298 case 3:
299 if ((png_ptr->row_number & 3) || png_ptr->width < 3)
300 {
301 png_write_finish_row(png_ptr);
302 return;
303 }
304 break;
305 case 4:
306 if ((png_ptr->row_number & 3) != 2)
307 {
308 png_write_finish_row(png_ptr);
309 return;
310 }
311 break;
312 case 5:
313 if ((png_ptr->row_number & 1) || png_ptr->width < 2)
314 {
315 png_write_finish_row(png_ptr);
316 return;
317 }
318 break;
319 case 6:
320 if (!(png_ptr->row_number & 1))
321 {
322 png_write_finish_row(png_ptr);
323 return;
324 }
325 break;
326 }
327 }
Guy Schalnat0f716451995-11-28 11:22:13 -0600328#endif /* PNG_WRITE_INTERLACE_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500329
330 /* set up row info for transformations */
331 png_ptr->row_info.color_type = png_ptr->color_type;
332 png_ptr->row_info.width = png_ptr->usr_width;
333 png_ptr->row_info.channels = png_ptr->usr_channels;
334 png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
335 png_ptr->row_info.pixel_depth = png_ptr->row_info.bit_depth *
336 png_ptr->row_info.channels;
337 png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
338 (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
339
340 /* copy users row into buffer, leaving room for filter byte */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500341 png_memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -0500342
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500343#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500344 /* handle interlacing */
345 if (png_ptr->interlaced && png_ptr->pass < 6 &&
346 (png_ptr->transformations & PNG_INTERLACE))
347 {
348 png_do_write_interlace(&(png_ptr->row_info),
349 png_ptr->row_buf + 1, png_ptr->pass);
350 /* this should always get caught above, but still ... */
351 if (!(png_ptr->row_info.width))
352 {
353 png_write_finish_row(png_ptr);
354 return;
355 }
356 }
Guy Schalnat0f716451995-11-28 11:22:13 -0600357#endif /* PNG_WRITE_INTERLACE_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500358
359 /* handle other transformations */
360 if (png_ptr->transformations)
361 png_do_write_transformations(png_ptr);
362
363 /* filter rows that have been proved to help */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500364 if (png_ptr->do_filter)
Guy Schalnat0d580581995-07-20 02:43:20 -0500365 {
366 /* save row to previous row */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500367 png_memcpy(png_ptr->save_row, png_ptr->row_buf,
Guy Schalnat0d580581995-07-20 02:43:20 -0500368 (png_size_t)png_ptr->row_info.rowbytes + 1);
369
370 /* filter row */
371 png_write_filter_row(&(png_ptr->row_info), png_ptr->row_buf,
372 png_ptr->prev_row);
373
374 /* trade saved pointer and prev pointer so next row references are correctly */
375 { /* scope limiter */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500376 png_bytef *tptr;
Guy Schalnat0d580581995-07-20 02:43:20 -0500377
378 tptr = png_ptr->prev_row;
379 png_ptr->prev_row = png_ptr->save_row;
380 png_ptr->save_row = tptr;
381 }
382 }
383 else
384 /* set filter row to "none" */
385 png_ptr->row_buf[0] = 0;
386
387 /* set up the zlib input buffer */
388 png_ptr->zstream->next_in = png_ptr->row_buf;
389 png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
Guy Schalnat0f716451995-11-28 11:22:13 -0600390
Guy Schalnat0d580581995-07-20 02:43:20 -0500391 /* repeat until we have compressed all the data */
392 do
393 {
394 int ret; /* return of zlib */
395
396 /* compress the data */
397 ret = deflate(png_ptr->zstream, Z_NO_FLUSH);
398 /* check for compression errors */
399 if (ret != Z_OK)
400 {
401 if (png_ptr->zstream->msg)
Guy Schalnat0f716451995-11-28 11:22:13 -0600402 (*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
Guy Schalnat0d580581995-07-20 02:43:20 -0500403 else
Guy Schalnat0f716451995-11-28 11:22:13 -0600404 (*(png_ptr->error_fn))(png_ptr, "zlib error");
Guy Schalnat0d580581995-07-20 02:43:20 -0500405 }
406
407 /* see if it is time to write another IDAT */
408 if (!png_ptr->zstream->avail_out)
409 {
410 /* write the IDAT and reset the zlib output buffer */
411 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
412 png_ptr->zstream->next_out = png_ptr->zbuf;
413 png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
414 }
415 /* repeat until all data has been compressed */
416 } while (png_ptr->zstream->avail_in);
417
418 /* finish row - updates counters and flushes zlib if last row */
419 png_write_finish_row(png_ptr);
Guy Schalnat0f716451995-11-28 11:22:13 -0600420
421#if defined(PNG_WRITE_FLUSH_SUPPORTED)
422 png_ptr->flush_rows++;
423
424 if (png_ptr->flush_dist > 0 &&
425 png_ptr->flush_rows >= png_ptr->flush_dist)
426 {
427 png_write_flush(png_ptr);
428 }
429#endif /* PNG_WRITE_FLUSH_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500430}
431
Guy Schalnat0f716451995-11-28 11:22:13 -0600432#if defined(PNG_WRITE_FLUSH_SUPPORTED)
433/* Set the automatic flush interval or 0 to turn flushing off */
434void
435png_set_flush(png_struct *png_ptr, int nrows)
436{
437 png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
438}
439
440/* flush the current output buffers now */
441void
442png_write_flush(png_struct *png_ptr)
443{
444 char wrote_IDAT;
445
446 if (png_ptr->mode != PNG_HAVE_IDAT)
447 return;
448
449 do
450 {
451 int ret;
452
453 /* compress the data */
454 ret = deflate(png_ptr->zstream, Z_SYNC_FLUSH);
455 wrote_IDAT = 0;
456
457 /* check for compression errors */
458 if (ret != Z_OK)
459 {
460 if (png_ptr->zstream->msg)
461 (*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
462 else
463 (*(png_ptr->error_fn))(png_ptr, "zlib error");
464 }
465
466 if (!png_ptr->zstream->avail_out)
467 {
468 /* write the IDAT and reset the zlib output buffer */
469 png_write_IDAT(png_ptr, png_ptr->zbuf,
470 png_ptr->zbuf_size);
471 png_ptr->zstream->next_out = png_ptr->zbuf;
472 png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
473 wrote_IDAT = 1;
474 }
475 } while(wrote_IDAT == 1);
476
477 /* If there is any data left to be output, write it into a new IDAT */
478 if (png_ptr->zbuf_size != png_ptr->zstream->avail_out)
479 {
480 /* write the IDAT and reset the zlib output buffer */
481 png_write_IDAT(png_ptr, png_ptr->zbuf,
482 png_ptr->zbuf_size - png_ptr->zstream->avail_out);
483 png_ptr->zstream->next_out = png_ptr->zbuf;
484 png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
485 }
486 png_ptr->flush_rows = 0;
487 (*(png_ptr->output_flush_fn))(png_ptr);
488}
489#endif /* PNG_WRITE_FLUSH_SUPPORTED */
490
Guy Schalnat0d580581995-07-20 02:43:20 -0500491/* free any memory used in png struct */
492void
493png_write_destroy(png_struct *png_ptr)
494{
495 jmp_buf tmp_jmp; /* save jump buffer */
496
497 /* free any memory zlib uses */
498 deflateEnd(png_ptr->zstream);
499 /* free our memory. png_free checks NULL for us. */
500 png_large_free(png_ptr, png_ptr->zbuf);
501 png_large_free(png_ptr, png_ptr->row_buf);
502 png_large_free(png_ptr, png_ptr->prev_row);
503 png_large_free(png_ptr, png_ptr->save_row);
504 /* reset structure */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500505 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
506 png_memset(png_ptr, 0, sizeof (png_struct));
507 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
508}
Guy Schalnat0f716451995-11-28 11:22:13 -0600509
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500510void
511png_set_filtering(png_struct *png_ptr, int filter)
512{
513 png_ptr->do_custom_filter = 1;
514 png_ptr->do_filter = filter;
515}
516
517void
518png_set_compression_level(png_struct *png_ptr, int level)
519{
520 png_ptr->zlib_custom_level = 1;
521 png_ptr->zlib_level = level;
522}
523
524void
525png_set_compression_mem_level(png_struct *png_ptr, int mem_level)
526{
527 png_ptr->zlib_custom_mem_level = 1;
528 png_ptr->zlib_mem_level = mem_level;
529}
530
531void
532png_set_compression_strategy(png_struct *png_ptr, int strategy)
533{
534 png_ptr->zlib_custom_strategy = 1;
535 png_ptr->zlib_strategy = strategy;
536}
537
538void
539png_set_compression_window_bits(png_struct *png_ptr, int window_bits)
540{
541 png_ptr->zlib_custom_window_bits = 1;
542 png_ptr->zlib_window_bits = window_bits;
543}
544
545void
546png_set_compression_method(png_struct *png_ptr, int method)
547{
548 png_ptr->zlib_custom_method = 1;
549 png_ptr->zlib_method = method;
Guy Schalnat0d580581995-07-20 02:43:20 -0500550}
551