blob: 19773ab965bcb13898fcc890cdde1e58f6d339f6 [file] [log] [blame]
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001
Andreas Dilger47a0c421997-05-16 02:46:07 -05002/* pngwrite.c - general routines to write a PNG file
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06004 * libpng 1.0.5h - December 10, 1999
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * 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
Glenn Randers-Pehrsonc9442291999-01-06 21:50:16 -06008 * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 */
Guy Schalnat0d580581995-07-20 02:43:20 -050010
11/* get internal access to png.h */
12#define PNG_INTERNAL
13#include "png.h"
14
Andreas Dilger47a0c421997-05-16 02:46:07 -050015/* 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
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -050018 * after the image data, put it in png_write_end(). I strongly encourage
Andreas Dilger47a0c421997-05-16 02:46:07 -050019 * 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.
23 */
Guy Schalnat0d580581995-07-20 02:43:20 -050024void
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -060025png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -050026{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060027#if defined(PNG_WRITE_sPLT_SUPPORTED)
28 int i;
29#endif
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -060030 png_debug(1, "in png_write_info_before_PLTE\n");
31 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
32 {
Guy Schalnat0d580581995-07-20 02:43:20 -050033 png_write_sig(png_ptr); /* write PNG signature */
34 /* write IHDR information. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060035 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
36 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -060037 info_ptr->filter_type,
38#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
39 info_ptr->interlace_type);
40#else
41 0);
42#endif
Guy Schalnat0d580581995-07-20 02:43:20 -050043 /* the rest of these check to see if the valid field has the appropriate
44 flag set, and if it does, writes the chunk. */
Guy Schalnat51f0eb41995-09-26 05:22:39 -050045#if defined(PNG_WRITE_gAMA_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060046 if (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060047 {
48#ifdef PNG_FIXED_POINT_SUPPORTED
49 png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma);
50#else
51# ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060052 png_write_gAMA(png_ptr, info_ptr->gamma);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060053# endif
54#endif
55 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -050056#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060057#if defined(PNG_WRITE_sRGB_SUPPORTED)
58 if (info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -060059 png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060060#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060061#if defined(PNG_WRITE_iCCP_SUPPORTED)
62 if (info_ptr->valid & PNG_INFO_iCCP)
63 png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_TEXT_COMPRESSION_NONE,
64 info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
65#endif
66#if defined(PNG_WRITE_sPLT_SUPPORTED)
67 if (info_ptr->valid & PNG_INFO_sPLT)
68 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
69 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
70#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -050071#if defined(PNG_WRITE_sBIT_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060072 if (info_ptr->valid & PNG_INFO_sBIT)
73 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -050074#endif
75#if defined(PNG_WRITE_cHRM_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060076 if (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060077 {
78#ifdef PNG_FIXED_POINT_SUPPORTED
79 png_write_cHRM_fixed(png_ptr,
80 info_ptr->int_x_white, info_ptr->int_y_white,
81 info_ptr->int_x_red, info_ptr->int_y_red,
82 info_ptr->int_x_green, info_ptr->int_y_green,
83 info_ptr->int_x_blue, info_ptr->int_y_blue);
84#else
85# ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -050086 png_write_cHRM(png_ptr,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060087 info_ptr->x_white, info_ptr->y_white,
88 info_ptr->x_red, info_ptr->y_red,
89 info_ptr->x_green, info_ptr->y_green,
90 info_ptr->x_blue, info_ptr->y_blue);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060091# endif
92#endif
93 }
94#endif
95#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
96 if (info_ptr->unknown_chunks_num)
97 {
98 png_unknown_chunk *up;
99
100 png_debug(5, "writing extra chunks\n");
101
102 for (up = info_ptr->unknown_chunks;
103 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
104 up++)
105 if (!(up->location & PNG_HAVE_PLTE))
106 png_write_chunk(png_ptr, up->name, up->data, up->size);
107 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500108#endif
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600109 png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
110 }
111}
112
113void
114png_write_info(png_structp png_ptr, png_infop info_ptr)
115{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600116#if defined(PNG_WRITE_TEXT_SUPPORTED)
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600117 int i;
118#endif
119
120 png_debug(1, "in png_write_info\n");
121
122 png_write_info_before_PLTE(png_ptr, info_ptr);
123
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600124 if (info_ptr->valid & PNG_INFO_PLTE)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500125 png_write_PLTE(png_ptr, info_ptr->palette,
126 (png_uint_32)info_ptr->num_palette);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600127 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -0500128 png_error(png_ptr, "Valid palette required for paletted images\n");
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600129
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500130#if defined(PNG_WRITE_tRNS_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600131 if (info_ptr->valid & PNG_INFO_tRNS)
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600132 {
133#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
134 /* invert the alpha channel (in tRNS) */
135 if (png_ptr->transformations & PNG_INVERT_ALPHA &&
136 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
137 {
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600138 int j;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600139 for (j=0; j<(int)info_ptr->num_trans; j++)
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500140 info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600141 }
142#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600143 png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values),
144 info_ptr->num_trans, info_ptr->color_type);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600145 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500146#endif
147#if defined(PNG_WRITE_bKGD_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600148 if (info_ptr->valid & PNG_INFO_bKGD)
149 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500150#endif
151#if defined(PNG_WRITE_hIST_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600152 if (info_ptr->valid & PNG_INFO_hIST)
153 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500154#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500155#if defined(PNG_WRITE_oFFs_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600156 if (info_ptr->valid & PNG_INFO_oFFs)
157 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
158 info_ptr->offset_unit_type);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500159#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500160#if defined(PNG_WRITE_pCAL_SUPPORTED)
161 if (info_ptr->valid & PNG_INFO_pCAL)
162 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
163 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
164 info_ptr->pcal_units, info_ptr->pcal_params);
165#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600166#if defined(PNG_WRITE_sCAL_SUPPORTED)
167 if (info_ptr->valid & PNG_INFO_sCAL)
168 png_write_sCAL_s(png_ptr, info_ptr->scal_unit,
169 info_ptr->scal_s_width, info_ptr->scal_s_height);
170#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500171#if defined(PNG_WRITE_pHYs_SUPPORTED)
172 if (info_ptr->valid & PNG_INFO_pHYs)
173 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
174 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
175#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500176#if defined(PNG_WRITE_tIME_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600177 if (info_ptr->valid & PNG_INFO_tIME)
Guy Schalnate5a37791996-06-05 15:50:50 -0500178 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600179 png_write_tIME(png_ptr, &(info_ptr->mod_time));
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600180 png_ptr->mode |= PNG_WROTE_tIME;
Guy Schalnate5a37791996-06-05 15:50:50 -0500181 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500182#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600183#if defined(PNG_WRITE_TEXT_SUPPORTED)
Guy Schalnate5a37791996-06-05 15:50:50 -0500184 /* Check to see if we need to write text chunks */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500185 for (i = 0; i < info_ptr->num_text; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500186 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500187 png_debug2(2, "Writing header text chunk %d, type %d\n", i,
188 info_ptr->text[i].compression);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600189 /* an internationalized chunk? */
190 if (info_ptr->text[i].lang)
191 {
192#if defined(PNG_WRITE_iTXt_SUPPORTED)
193 /* write international chunk */
194 png_write_iTXt(png_ptr,
195 info_ptr->text[i].compression,
196 info_ptr->text[i].lang,
197 info_ptr->text[i].key,
198 info_ptr->text[i].translated_key,
199 info_ptr->text[i].text);
200#else
201 png_warning(png_ptr, "Unable to write international text\n");
202#endif
203 /* Mark this chunk as written */
204 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
205 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500206 /* If we want a compressed text chunk */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600207 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500208 {
209#if defined(PNG_WRITE_zTXt_SUPPORTED)
210 /* write compressed chunk */
211 png_write_zTXt(png_ptr, info_ptr->text[i].key,
212 info_ptr->text[i].text, info_ptr->text[i].text_length,
213 info_ptr->text[i].compression);
214#else
215 png_warning(png_ptr, "Unable to write compressed text\n");
216#endif
217 /* Mark this chunk as written */
218 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
219 }
220 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
221 {
222#if defined(PNG_WRITE_tEXt_SUPPORTED)
223 /* write uncompressed chunk */
224 png_write_tEXt(png_ptr, info_ptr->text[i].key,
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600225 info_ptr->text[i].text,
226 info_ptr->text[i].text_length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500227#else
228 png_warning(png_ptr, "Unable to write uncompressed text\n");
229#endif
230 /* Mark this chunk as written */
231 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
232 }
233 }
234#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600235#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
236 if (info_ptr->unknown_chunks_num)
237 {
238 png_unknown_chunk *up;
239
240 png_debug(5, "writing extra chunks\n");
241
242 for (up = info_ptr->unknown_chunks;
243 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
244 up++)
245 if ((up->location& PNG_HAVE_PLTE) && !(up->location& PNG_HAVE_IDAT))
246 png_write_chunk(png_ptr, up->name, up->data, up->size);
247 }
248#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500249}
Guy Schalnat0d580581995-07-20 02:43:20 -0500250
Andreas Dilger47a0c421997-05-16 02:46:07 -0500251/* Writes the end of the PNG file. If you don't want to write comments or
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600252 * time information, you can pass NULL for info. If you already wrote these
253 * in png_write_info(), do not write them again here. If you have long
254 * comments, I suggest writing them here, and compressing them.
255 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500256void
257png_write_end(png_structp png_ptr, png_infop info_ptr)
258{
259 png_debug(1, "in png_write_end\n");
260 if (!(png_ptr->mode & PNG_HAVE_IDAT))
261 png_error(png_ptr, "No IDATs written into file");
262
263 /* see if user wants us to write information chunks */
264 if (info_ptr != NULL)
265 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600266#if defined(PNG_WRITE_TEXT_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500267 int i; /* local index variable */
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600268#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500269#if defined(PNG_WRITE_tIME_SUPPORTED)
270 /* check to see if user has supplied a time chunk */
271 if (info_ptr->valid & PNG_INFO_tIME &&
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600272 !(png_ptr->mode & PNG_WROTE_tIME))
Andreas Dilger47a0c421997-05-16 02:46:07 -0500273 png_write_tIME(png_ptr, &(info_ptr->mod_time));
274#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600275#if defined(PNG_WRITE_TEXT_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500276 /* loop through comment chunks */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600277 for (i = 0; i < info_ptr->num_text; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500278 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500279 png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
280 info_ptr->text[i].compression);
281 if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
Guy Schalnat0d580581995-07-20 02:43:20 -0500282 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500283#if defined(PNG_WRITE_zTXt_SUPPORTED)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600284 /* write compressed chunk */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600285 png_write_zTXt(png_ptr, info_ptr->text[i].key,
286 info_ptr->text[i].text, info_ptr->text[i].text_length,
287 info_ptr->text[i].compression);
Guy Schalnate5a37791996-06-05 15:50:50 -0500288#else
289 png_warning(png_ptr, "Unable to write compressed text\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500290#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500291 /* Mark this chunk as written */
292 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
Guy Schalnat0d580581995-07-20 02:43:20 -0500293 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500294 else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
Guy Schalnat0d580581995-07-20 02:43:20 -0500295 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500296#if defined(PNG_WRITE_tEXt_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500297 /* write uncompressed chunk */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600298 png_write_tEXt(png_ptr, info_ptr->text[i].key,
299 info_ptr->text[i].text, info_ptr->text[i].text_length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500300#else
301 png_warning(png_ptr, "Unable to write uncompressed text\n");
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500302#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500303
Andreas Dilger47a0c421997-05-16 02:46:07 -0500304 /* Mark this chunk as written */
305 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
Guy Schalnat0d580581995-07-20 02:43:20 -0500306 }
307 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600308#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600309#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
310 if (info_ptr->unknown_chunks_num)
311 {
312 png_unknown_chunk *up;
313
314 png_debug(5, "writing extra chunks\n");
315
316 for (up = info_ptr->unknown_chunks;
317 up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
318 up++)
319 if (up->location & PNG_HAVE_IDAT)
320 png_write_chunk(png_ptr, up->name, up->data, up->size);
321 }
322#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500323 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500324
325 png_ptr->mode |= PNG_AFTER_IDAT;
326
Andreas Dilger47a0c421997-05-16 02:46:07 -0500327 /* write end of PNG file */
Guy Schalnat0d580581995-07-20 02:43:20 -0500328 png_write_IEND(png_ptr);
329}
330
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500331#if defined(PNG_WRITE_tIME_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500332void
Guy Schalnat6d764711995-12-19 03:22:19 -0600333png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
Guy Schalnat0d580581995-07-20 02:43:20 -0500334{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500335 png_debug(1, "in png_convert_from_struct_tm\n");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600336 ptime->year = (png_uint_16)(1900 + ttime->tm_year);
337 ptime->month = (png_byte)(ttime->tm_mon + 1);
338 ptime->day = (png_byte)ttime->tm_mday;
339 ptime->hour = (png_byte)ttime->tm_hour;
340 ptime->minute = (png_byte)ttime->tm_min;
341 ptime->second = (png_byte)ttime->tm_sec;
Guy Schalnat0d580581995-07-20 02:43:20 -0500342}
343
344void
Guy Schalnat6d764711995-12-19 03:22:19 -0600345png_convert_from_time_t(png_timep ptime, time_t ttime)
Guy Schalnat0d580581995-07-20 02:43:20 -0500346{
347 struct tm *tbuf;
348
Andreas Dilger47a0c421997-05-16 02:46:07 -0500349 png_debug(1, "in png_convert_from_time_t\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500350 tbuf = gmtime(&ttime);
351 png_convert_from_struct_tm(ptime, tbuf);
352}
Guy Schalnat6d764711995-12-19 03:22:19 -0600353#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500354
Andreas Dilger47a0c421997-05-16 02:46:07 -0500355/* Initialize png_ptr structure, and allocate any memory needed */
Guy Schalnate5a37791996-06-05 15:50:50 -0500356png_structp
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -0500357png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600358 png_error_ptr error_fn, png_error_ptr warn_fn)
Guy Schalnat0d580581995-07-20 02:43:20 -0500359{
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500360#ifdef PNG_USER_MEM_SUPPORTED
361 return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
362 warn_fn, NULL, NULL, NULL));
363}
364
365/* Alternate initialize png_ptr structure, and allocate any memory needed */
366png_structp
367png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
368 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
369 png_malloc_ptr malloc_fn, png_free_ptr free_fn)
370{
371#endif /* PNG_USER_MEM_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500372 png_structp png_ptr;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600373#ifdef USE_FAR_KEYWORD
374 jmp_buf jmpbuf;
375#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500376 png_debug(1, "in png_create_write_struct\n");
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500377#ifdef PNG_USER_MEM_SUPPORTED
378 if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
379 (png_malloc_ptr)malloc_fn)) == NULL)
380#else
Guy Schalnate5a37791996-06-05 15:50:50 -0500381 if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500382#endif /* PNG_USER_MEM_SUPPORTED */
Guy Schalnate5a37791996-06-05 15:50:50 -0500383 {
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600384 return ((png_structp)NULL);
Guy Schalnate5a37791996-06-05 15:50:50 -0500385 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600386#ifdef USE_FAR_KEYWORD
387 if (setjmp(jmpbuf))
388#else
Guy Schalnate5a37791996-06-05 15:50:50 -0500389 if (setjmp(png_ptr->jmpbuf))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600390#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500391 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600392 png_free(png_ptr, png_ptr->zbuf);
Guy Schalnate5a37791996-06-05 15:50:50 -0500393 png_destroy_struct(png_ptr);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600394 return ((png_structp)NULL);
Guy Schalnate5a37791996-06-05 15:50:50 -0500395 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600396#ifdef USE_FAR_KEYWORD
397 png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
398#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500399#ifdef PNG_USER_MEM_SUPPORTED
400 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
401#endif /* PNG_USER_MEM_SUPPORTED */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600402 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
Guy Schalnate5a37791996-06-05 15:50:50 -0500403
Andreas Dilger47a0c421997-05-16 02:46:07 -0500404 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
405 * we must recompile any applications that use any older library version.
406 * For versions after libpng 1.0, we will be compatible, so we need
407 * only check the first digit.
408 */
409 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
410 (png_libpng_ver[0] == '0' && user_png_ver[2] < '9'))
Guy Schalnate5a37791996-06-05 15:50:50 -0500411 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500412 png_error(png_ptr,
413 "Incompatible libpng version in application and library");
Guy Schalnate5a37791996-06-05 15:50:50 -0500414 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500415
416 /* initialize zbuf - compression buffer */
417 png_ptr->zbuf_size = PNG_ZBUF_SIZE;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600418 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
419 (png_uint_32)png_ptr->zbuf_size);
Guy Schalnate5a37791996-06-05 15:50:50 -0500420
421 png_set_write_fn(png_ptr, NULL, NULL, NULL);
422
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600423#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
424 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
425 1, NULL, NULL);
426#endif
427
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600428 return ((png_structp)png_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500429}
430
Andreas Dilger47a0c421997-05-16 02:46:07 -0500431/* Initialize png_ptr structure, and allocate any memory needed */
Guy Schalnate5a37791996-06-05 15:50:50 -0500432void
433png_write_init(png_structp png_ptr)
434{
435 jmp_buf tmp_jmp; /* to save current jump buffer */
436
Andreas Dilger47a0c421997-05-16 02:46:07 -0500437 png_debug(1, "in png_write_init\n");
Guy Schalnate5a37791996-06-05 15:50:50 -0500438 /* save jump buffer and error functions */
439 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
440
441 /* reset all variables to 0 */
442 png_memset(png_ptr, 0, sizeof (png_struct));
443
444 /* restore jump buffer */
445 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
446
447 /* initialize zbuf - compression buffer */
448 png_ptr->zbuf_size = PNG_ZBUF_SIZE;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600449 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
450 (png_uint_32)png_ptr->zbuf_size);
Guy Schalnate5a37791996-06-05 15:50:50 -0500451 png_set_write_fn(png_ptr, NULL, NULL, NULL);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500452
453#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
454 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
455 1, NULL, NULL);
456#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500457}
458
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600459/* Write a few rows of image data. If the image is interlaced,
460 * either you will have to write the 7 sub images, or, if you
461 * have called png_set_interlace_handling(), you will have to
462 * "write" the image seven times.
463 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500464void
Guy Schalnat6d764711995-12-19 03:22:19 -0600465png_write_rows(png_structp png_ptr, png_bytepp row,
Guy Schalnat0d580581995-07-20 02:43:20 -0500466 png_uint_32 num_rows)
467{
468 png_uint_32 i; /* row counter */
Guy Schalnat6d764711995-12-19 03:22:19 -0600469 png_bytepp rp; /* row pointer */
Guy Schalnat0d580581995-07-20 02:43:20 -0500470
Andreas Dilger47a0c421997-05-16 02:46:07 -0500471 png_debug(1, "in png_write_rows\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500472 /* loop through the rows */
473 for (i = 0, rp = row; i < num_rows; i++, rp++)
474 {
475 png_write_row(png_ptr, *rp);
476 }
477}
478
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600479/* Write the image. You only need to call this function once, even
480 * if you are writing an interlaced image.
481 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500482void
Guy Schalnat6d764711995-12-19 03:22:19 -0600483png_write_image(png_structp png_ptr, png_bytepp image)
Guy Schalnat0d580581995-07-20 02:43:20 -0500484{
485 png_uint_32 i; /* row index */
486 int pass, num_pass; /* pass variables */
Guy Schalnat6d764711995-12-19 03:22:19 -0600487 png_bytepp rp; /* points to current row */
Guy Schalnat0d580581995-07-20 02:43:20 -0500488
Andreas Dilger47a0c421997-05-16 02:46:07 -0500489 png_debug(1, "in png_write_image\n");
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600490#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500491 /* intialize interlace handling. If image is not interlaced,
492 this will set pass to 1 */
493 num_pass = png_set_interlace_handling(png_ptr);
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600494#else
495 num_pass = 1;
496#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500497 /* loop through passes */
498 for (pass = 0; pass < num_pass; pass++)
499 {
500 /* loop through image */
501 for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
502 {
503 png_write_row(png_ptr, *rp);
504 }
505 }
506}
507
Guy Schalnate5a37791996-06-05 15:50:50 -0500508/* called by user to write a row of image data */
Guy Schalnat0d580581995-07-20 02:43:20 -0500509void
Guy Schalnat6d764711995-12-19 03:22:19 -0600510png_write_row(png_structp png_ptr, png_bytep row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500511{
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600512 png_debug2(1, "in png_write_row (row %ld, pass %d)\n",
513 png_ptr->row_number, png_ptr->pass);
Guy Schalnat0d580581995-07-20 02:43:20 -0500514 /* initialize transformations and other stuff if first time */
Guy Schalnat6d764711995-12-19 03:22:19 -0600515 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
Guy Schalnat0d580581995-07-20 02:43:20 -0500516 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500517 /* check for transforms that have been set but were defined out */
518#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
519 if (png_ptr->transformations & PNG_INVERT_MONO)
520 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined.");
521#endif
522#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
523 if (png_ptr->transformations & PNG_FILLER)
524 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined.");
525#endif
526#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
527 if (png_ptr->transformations & PNG_PACKSWAP)
528 png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined.");
529#endif
530#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
531 if (png_ptr->transformations & PNG_PACK)
532 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined.");
533#endif
534#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
535 if (png_ptr->transformations & PNG_SHIFT)
536 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined.");
537#endif
538#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
539 if (png_ptr->transformations & PNG_BGR)
540 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined.");
541#endif
542#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
543 if (png_ptr->transformations & PNG_SWAP_BYTES)
544 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined.");
545#endif
546
Guy Schalnat0d580581995-07-20 02:43:20 -0500547 png_write_start_row(png_ptr);
548 }
549
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500550#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500551 /* if interlaced and not interested in row, return */
552 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
553 {
554 switch (png_ptr->pass)
555 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600556 case 0:
Guy Schalnat0d580581995-07-20 02:43:20 -0500557 if (png_ptr->row_number & 7)
558 {
559 png_write_finish_row(png_ptr);
560 return;
561 }
562 break;
563 case 1:
564 if ((png_ptr->row_number & 7) || png_ptr->width < 5)
565 {
566 png_write_finish_row(png_ptr);
567 return;
568 }
569 break;
570 case 2:
571 if ((png_ptr->row_number & 7) != 4)
572 {
573 png_write_finish_row(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600574 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500575 }
576 break;
577 case 3:
578 if ((png_ptr->row_number & 3) || png_ptr->width < 3)
579 {
580 png_write_finish_row(png_ptr);
581 return;
582 }
583 break;
584 case 4:
585 if ((png_ptr->row_number & 3) != 2)
586 {
587 png_write_finish_row(png_ptr);
588 return;
589 }
590 break;
591 case 5:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600592 if ((png_ptr->row_number & 1) || png_ptr->width < 2)
Guy Schalnat0d580581995-07-20 02:43:20 -0500593 {
594 png_write_finish_row(png_ptr);
595 return;
596 }
597 break;
598 case 6:
599 if (!(png_ptr->row_number & 1))
600 {
601 png_write_finish_row(png_ptr);
602 return;
603 }
604 break;
605 }
606 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600607#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500608
609 /* set up row info for transformations */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600610 png_ptr->row_info.color_type = png_ptr->color_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500611 png_ptr->row_info.width = png_ptr->usr_width;
612 png_ptr->row_info.channels = png_ptr->usr_channels;
613 png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600614 png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
615 png_ptr->row_info.channels);
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600616
Guy Schalnat0d580581995-07-20 02:43:20 -0500617 png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
618 (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
619
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600620 png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
621 png_debug1(3, "row_info->width = %d\n", png_ptr->row_info.width);
622 png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels);
623 png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
624 png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
625 png_debug1(3, "row_info->rowbytes = %d\n", png_ptr->row_info.rowbytes);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626
627 /* Copy user's row into buffer, leaving room for filter byte. */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600628 png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600629 png_ptr->row_info.rowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -0500630
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500631#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500632 /* handle interlacing */
633 if (png_ptr->interlaced && png_ptr->pass < 6 &&
634 (png_ptr->transformations & PNG_INTERLACE))
635 {
636 png_do_write_interlace(&(png_ptr->row_info),
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600637 png_ptr->row_buf + 1, png_ptr->pass);
Guy Schalnat0d580581995-07-20 02:43:20 -0500638 /* this should always get caught above, but still ... */
639 if (!(png_ptr->row_info.width))
640 {
641 png_write_finish_row(png_ptr);
642 return;
643 }
644 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600645#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500646
647 /* handle other transformations */
648 if (png_ptr->transformations)
649 png_do_write_transformations(png_ptr);
650
Andreas Dilger47a0c421997-05-16 02:46:07 -0500651 /* Find a filter if necessary, filter the row and write it out. */
Guy Schalnate5a37791996-06-05 15:50:50 -0500652 png_write_find_filter(png_ptr, &(png_ptr->row_info));
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600653
654 if (png_ptr->write_row_fn != NULL)
655 (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
Guy Schalnat0d580581995-07-20 02:43:20 -0500656}
657
Guy Schalnat0f716451995-11-28 11:22:13 -0600658#if defined(PNG_WRITE_FLUSH_SUPPORTED)
659/* Set the automatic flush interval or 0 to turn flushing off */
660void
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600661png_set_flush(png_structp png_ptr, int nrows)
Guy Schalnat0f716451995-11-28 11:22:13 -0600662{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500663 png_debug(1, "in png_set_flush\n");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600664 png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
Guy Schalnat0f716451995-11-28 11:22:13 -0600665}
666
667/* flush the current output buffers now */
668void
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600669png_write_flush(png_structp png_ptr)
Guy Schalnat0f716451995-11-28 11:22:13 -0600670{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600671 int wrote_IDAT;
Guy Schalnat0f716451995-11-28 11:22:13 -0600672
Andreas Dilger47a0c421997-05-16 02:46:07 -0500673 png_debug(1, "in png_write_flush\n");
Guy Schalnate5a37791996-06-05 15:50:50 -0500674 /* We have already written out all of the data */
675 if (png_ptr->row_number >= png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600676 return;
Guy Schalnat0f716451995-11-28 11:22:13 -0600677
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600678 do
679 {
680 int ret;
Guy Schalnat0f716451995-11-28 11:22:13 -0600681
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600682 /* compress the data */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600683 ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600684 wrote_IDAT = 0;
Guy Schalnat0f716451995-11-28 11:22:13 -0600685
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600686 /* check for compression errors */
687 if (ret != Z_OK)
688 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500689 if (png_ptr->zstream.msg != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600690 png_error(png_ptr, png_ptr->zstream.msg);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600691 else
692 png_error(png_ptr, "zlib error");
693 }
Guy Schalnat0f716451995-11-28 11:22:13 -0600694
Andreas Dilger47a0c421997-05-16 02:46:07 -0500695 if (!(png_ptr->zstream.avail_out))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600696 {
697 /* write the IDAT and reset the zlib output buffer */
698 png_write_IDAT(png_ptr, png_ptr->zbuf,
699 png_ptr->zbuf_size);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600700 png_ptr->zstream.next_out = png_ptr->zbuf;
701 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600702 wrote_IDAT = 1;
703 }
704 } while(wrote_IDAT == 1);
Guy Schalnat0f716451995-11-28 11:22:13 -0600705
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600706 /* If there is any data left to be output, write it into a new IDAT */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600707 if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600708 {
709 /* write the IDAT and reset the zlib output buffer */
710 png_write_IDAT(png_ptr, png_ptr->zbuf,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600711 png_ptr->zbuf_size - png_ptr->zstream.avail_out);
712 png_ptr->zstream.next_out = png_ptr->zbuf;
713 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600714 }
715 png_ptr->flush_rows = 0;
716 png_flush(png_ptr);
Guy Schalnat0f716451995-11-28 11:22:13 -0600717}
718#endif /* PNG_WRITE_FLUSH_SUPPORTED */
719
Guy Schalnate5a37791996-06-05 15:50:50 -0500720/* free all memory used by the write */
721void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600722png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500723{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600724 png_structp png_ptr = NULL;
725 png_infop info_ptr = NULL;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500726#ifdef PNG_USER_MEM_SUPPORTED
727 png_free_ptr free_fn = NULL;
728#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600729
Andreas Dilger47a0c421997-05-16 02:46:07 -0500730 png_debug(1, "in png_destroy_write_struct\n");
731 if (png_ptr_ptr != NULL)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500732 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600733 png_ptr = *png_ptr_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500734#ifdef PNG_USER_MEM_SUPPORTED
735 free_fn = png_ptr->free_fn;
736#endif
737 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600738
Andreas Dilger47a0c421997-05-16 02:46:07 -0500739 if (info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600740 info_ptr = *info_ptr_ptr;
741
Andreas Dilger47a0c421997-05-16 02:46:07 -0500742 if (info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500743 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600744#if defined(PNG_WRITE_TEXT_SUPPORTED)
745 png_free_text(png_ptr, info_ptr, -1);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600746#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600747#if defined(PNG_WRITE_sCAL_SUPPORTED)
748 png_free_sCAL(png_ptr, info_ptr);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600749#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600750#if defined(PNG_WRITE_pCAL_SUPPORTED)
751 png_free_pCAL(png_ptr, info_ptr);
752#endif
753#if defined(PNG_WRITE_iCCP_SUPPORTED)
754 png_free_iCCP(png_ptr, info_ptr);
755#endif
756#if defined(PNG_WRITE_sPLT_SUPPORTED)
757 png_free_spalette(png_ptr, info_ptr, -1);
758#endif
759#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
760 png_free_unknown_chunk(png_ptr, info_ptr, -1);
761#endif
762
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500763#ifdef PNG_USER_MEM_SUPPORTED
764 png_destroy_struct_2((png_voidp)info_ptr, free_fn);
765#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600766 png_destroy_struct((png_voidp)info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500767#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600768 *info_ptr_ptr = (png_infop)NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -0500769 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600770
Andreas Dilger47a0c421997-05-16 02:46:07 -0500771 if (png_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500772 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600773 png_write_destroy(png_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500774#ifdef PNG_USER_MEM_SUPPORTED
775 png_destroy_struct_2((png_voidp)png_ptr, free_fn);
776#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600777 png_destroy_struct((png_voidp)png_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500778#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600779 *png_ptr_ptr = (png_structp)NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -0500780 }
781}
782
783
Andreas Dilger47a0c421997-05-16 02:46:07 -0500784/* Free any memory used in png_ptr struct (old method) */
Guy Schalnat0d580581995-07-20 02:43:20 -0500785void
Guy Schalnat6d764711995-12-19 03:22:19 -0600786png_write_destroy(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500787{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600788 jmp_buf tmp_jmp; /* save jump buffer */
Guy Schalnate5a37791996-06-05 15:50:50 -0500789 png_error_ptr error_fn;
790 png_error_ptr warning_fn;
791 png_voidp error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500792#ifdef PNG_USER_MEM_SUPPORTED
793 png_free_ptr free_fn;
794#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500795
Andreas Dilger47a0c421997-05-16 02:46:07 -0500796 png_debug(1, "in png_write_destroy\n");
Guy Schalnat0d580581995-07-20 02:43:20 -0500797 /* free any memory zlib uses */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600798 deflateEnd(&png_ptr->zstream);
Guy Schalnate5a37791996-06-05 15:50:50 -0500799
Guy Schalnat0d580581995-07-20 02:43:20 -0500800 /* free our memory. png_free checks NULL for us. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600801 png_free(png_ptr, png_ptr->zbuf);
802 png_free(png_ptr, png_ptr->row_buf);
803 png_free(png_ptr, png_ptr->prev_row);
804 png_free(png_ptr, png_ptr->sub_row);
805 png_free(png_ptr, png_ptr->up_row);
806 png_free(png_ptr, png_ptr->avg_row);
807 png_free(png_ptr, png_ptr->paeth_row);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600808
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600809#if defined(PNG_TIME_RFC1123_SUPPORTED)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600810 png_free(png_ptr, png_ptr->time_buffer);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600811#endif
812
Andreas Dilger47a0c421997-05-16 02:46:07 -0500813#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
814 png_free(png_ptr, png_ptr->prev_filters);
815 png_free(png_ptr, png_ptr->filter_weights);
816 png_free(png_ptr, png_ptr->inv_filter_weights);
817 png_free(png_ptr, png_ptr->filter_costs);
818 png_free(png_ptr, png_ptr->inv_filter_costs);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600819#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500820
Guy Schalnat0d580581995-07-20 02:43:20 -0500821 /* reset structure */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500822 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
Guy Schalnate5a37791996-06-05 15:50:50 -0500823
824 error_fn = png_ptr->error_fn;
825 warning_fn = png_ptr->warning_fn;
826 error_ptr = png_ptr->error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500827#ifdef PNG_USER_MEM_SUPPORTED
828 free_fn = png_ptr->free_fn;
829#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500830
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500831 png_memset(png_ptr, 0, sizeof (png_struct));
Guy Schalnate5a37791996-06-05 15:50:50 -0500832
833 png_ptr->error_fn = error_fn;
834 png_ptr->warning_fn = warning_fn;
835 png_ptr->error_ptr = error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500836#ifdef PNG_USER_MEM_SUPPORTED
837 png_ptr->free_fn = free_fn;
838#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500839
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500840 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
841}
Guy Schalnate5a37791996-06-05 15:50:50 -0500842
Andreas Dilger47a0c421997-05-16 02:46:07 -0500843/* Allow the application to select one or more row filters to use. */
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500844void
Guy Schalnate5a37791996-06-05 15:50:50 -0500845png_set_filter(png_structp png_ptr, int method, int filters)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500846{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500847 png_debug(1, "in png_set_filter\n");
848 /* We allow 'method' only for future expansion of the base filter method. */
849 if (method == PNG_FILTER_TYPE_BASE)
Guy Schalnate5a37791996-06-05 15:50:50 -0500850 {
851 switch (filters & (PNG_ALL_FILTERS | 0x07))
852 {
853 case 5:
854 case 6:
Andreas Dilger47a0c421997-05-16 02:46:07 -0500855 case 7: png_warning(png_ptr, "Unknown row filter for method 0");
856 case PNG_FILTER_VALUE_NONE: png_ptr->do_filter=PNG_FILTER_NONE; break;
857 case PNG_FILTER_VALUE_SUB: png_ptr->do_filter=PNG_FILTER_SUB; break;
858 case PNG_FILTER_VALUE_UP: png_ptr->do_filter=PNG_FILTER_UP; break;
859 case PNG_FILTER_VALUE_AVG: png_ptr->do_filter=PNG_FILTER_AVG; break;
860 case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break;
Guy Schalnate5a37791996-06-05 15:50:50 -0500861 default: png_ptr->do_filter = (png_byte)filters; break;
862 }
863
Andreas Dilger47a0c421997-05-16 02:46:07 -0500864 /* If we have allocated the row_buf, this means we have already started
865 * with the image and we should have allocated all of the filter buffers
866 * that have been selected. If prev_row isn't already allocated, then
867 * it is too late to start using the filters that need it, since we
868 * will be missing the data in the previous row. If an application
869 * wants to start and stop using particular filters during compression,
870 * it should start out with all of the filters, and then add and
871 * remove them after the start of compression.
Guy Schalnate5a37791996-06-05 15:50:50 -0500872 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500873 if (png_ptr->row_buf != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500874 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500875 if (png_ptr->do_filter & PNG_FILTER_SUB && png_ptr->sub_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500876 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500877 png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600878 (png_ptr->rowbytes + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500879 png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
Guy Schalnate5a37791996-06-05 15:50:50 -0500880 }
881
Andreas Dilger47a0c421997-05-16 02:46:07 -0500882 if (png_ptr->do_filter & PNG_FILTER_UP && png_ptr->up_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500883 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500884 if (png_ptr->prev_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500885 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500886 png_warning(png_ptr, "Can't add Up filter after starting");
Guy Schalnate5a37791996-06-05 15:50:50 -0500887 png_ptr->do_filter &= ~PNG_FILTER_UP;
888 }
889 else
890 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500891 png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600892 (png_ptr->rowbytes + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500893 png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
Guy Schalnate5a37791996-06-05 15:50:50 -0500894 }
895 }
896
Andreas Dilger47a0c421997-05-16 02:46:07 -0500897 if (png_ptr->do_filter & PNG_FILTER_AVG && png_ptr->avg_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500898 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500899 if (png_ptr->prev_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500900 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500901 png_warning(png_ptr, "Can't add Average filter after starting");
Guy Schalnate5a37791996-06-05 15:50:50 -0500902 png_ptr->do_filter &= ~PNG_FILTER_AVG;
903 }
904 else
905 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500906 png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600907 (png_ptr->rowbytes + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500908 png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
Guy Schalnate5a37791996-06-05 15:50:50 -0500909 }
910 }
911
Andreas Dilger47a0c421997-05-16 02:46:07 -0500912 if (png_ptr->do_filter & PNG_FILTER_PAETH &&
913 png_ptr->paeth_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500914 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500915 if (png_ptr->prev_row == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500916 {
917 png_warning(png_ptr, "Can't add Paeth filter after starting");
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500918 png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH);
Guy Schalnate5a37791996-06-05 15:50:50 -0500919 }
920 else
921 {
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600922 png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600923 (png_ptr->rowbytes + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500924 png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
Guy Schalnate5a37791996-06-05 15:50:50 -0500925 }
926 }
927
928 if (png_ptr->do_filter == PNG_NO_FILTERS)
929 png_ptr->do_filter = PNG_FILTER_NONE;
930 }
931 }
932 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500933 png_error(png_ptr, "Unknown custom filter method");
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500934}
935
Andreas Dilger47a0c421997-05-16 02:46:07 -0500936/* This allows us to influence the way in which libpng chooses the "best"
937 * filter for the current scanline. While the "minimum-sum-of-absolute-
938 * differences metric is relatively fast and effective, there is some
939 * question as to whether it can be improved upon by trying to keep the
940 * filtered data going to zlib more consistent, hopefully resulting in
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600941 * better compression.
942 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500943#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */
944void
945png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
946 int num_weights, png_doublep filter_weights,
947 png_doublep filter_costs)
948{
949 int i;
950
951 png_debug(1, "in png_set_filter_heuristics\n");
952 if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
953 {
954 png_warning(png_ptr, "Unknown filter heuristic method");
955 return;
956 }
957
958 if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
959 {
960 heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
961 }
962
963 if (num_weights < 0 || filter_weights == NULL ||
964 heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
965 {
966 num_weights = 0;
967 }
968
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500969 png_ptr->num_prev_filters = (png_byte)num_weights;
970 png_ptr->heuristic_method = (png_byte)heuristic_method;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500971
972 if (num_weights > 0)
973 {
974 if (png_ptr->prev_filters == NULL)
975 {
976 png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600977 (png_uint_32)(sizeof(png_byte) * num_weights));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500978
979 /* To make sure that the weighting starts out fairly */
980 for (i = 0; i < num_weights; i++)
981 {
982 png_ptr->prev_filters[i] = 255;
983 }
984 }
985
986 if (png_ptr->filter_weights == NULL)
987 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -0600988 png_ptr->filter_weights = (png_uint_16p) png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600989 (png_uint_32)(sizeof(png_uint_16) * num_weights));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500990
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -0600991 png_ptr->inv_filter_weights = (png_uint_16p) png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600992 (png_uint_32)(sizeof(png_uint_16) * num_weights));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500993
994 for (i = 0; i < num_weights; i++)
995 {
996 png_ptr->inv_filter_weights[i] =
997 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
998 }
999 }
1000
1001 for (i = 0; i < num_weights; i++)
1002 {
1003 if (filter_weights[i] < 0.0)
1004 {
1005 png_ptr->inv_filter_weights[i] =
1006 png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
1007 }
1008 else
1009 {
1010 png_ptr->inv_filter_weights[i] =
1011 (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
1012 png_ptr->filter_weights[i] =
1013 (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
1014 }
1015 }
1016 }
1017
1018 /* If, in the future, there are other filter methods, this would
1019 * need to be based on png_ptr->filter.
1020 */
1021 if (png_ptr->filter_costs == NULL)
1022 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001023 png_ptr->filter_costs = (png_uint_16p) png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001024 (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001025
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001026 png_ptr->inv_filter_costs = (png_uint_16p) png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001027 (png_uint_32)(sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001028
1029 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
1030 {
1031 png_ptr->inv_filter_costs[i] =
1032 png_ptr->filter_costs[i] = PNG_COST_FACTOR;
1033 }
1034 }
1035
1036 /* Here is where we set the relative costs of the different filters. We
1037 * should take the desired compression level into account when setting
1038 * the costs, so that Paeth, for instance, has a high relative cost at low
1039 * compression levels, while it has a lower relative cost at higher
1040 * compression settings. The filter types are in order of increasing
1041 * relative cost, so it would be possible to do this with an algorithm.
1042 */
1043 for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
1044 {
1045 if (filter_costs == NULL || filter_costs[i] < 0.0)
1046 {
1047 png_ptr->inv_filter_costs[i] =
1048 png_ptr->filter_costs[i] = PNG_COST_FACTOR;
1049 }
1050 else if (filter_costs[i] >= 1.0)
1051 {
1052 png_ptr->inv_filter_costs[i] =
1053 (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
1054 png_ptr->filter_costs[i] =
1055 (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
1056 }
1057 }
1058}
1059#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
1060
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001061void
Guy Schalnat6d764711995-12-19 03:22:19 -06001062png_set_compression_level(png_structp png_ptr, int level)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001063{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001064 png_debug(1, "in png_set_compression_level\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001065 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001066 png_ptr->zlib_level = level;
1067}
1068
1069void
Guy Schalnat6d764711995-12-19 03:22:19 -06001070png_set_compression_mem_level(png_structp png_ptr, int mem_level)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001071{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001072 png_debug(1, "in png_set_compression_mem_level\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001073 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001074 png_ptr->zlib_mem_level = mem_level;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001075}
1076
1077void
Guy Schalnat6d764711995-12-19 03:22:19 -06001078png_set_compression_strategy(png_structp png_ptr, int strategy)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001079{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001080 png_debug(1, "in png_set_compression_strategy\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001081 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001082 png_ptr->zlib_strategy = strategy;
1083}
1084
1085void
Guy Schalnat6d764711995-12-19 03:22:19 -06001086png_set_compression_window_bits(png_structp png_ptr, int window_bits)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001087{
Guy Schalnate5a37791996-06-05 15:50:50 -05001088 if (window_bits > 15)
1089 png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001090 else if (window_bits < 8)
1091 png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001092#ifndef WBITS_8_OK
1093 /* avoid libpng bug with 256-byte windows */
1094 if (window_bits == 8)
1095 {
1096 png_warning(png_ptr, "Compression window is being reset to 512");
1097 window_bits=9;
1098 }
1099#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001100 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001101 png_ptr->zlib_window_bits = window_bits;
1102}
1103
1104void
Guy Schalnat6d764711995-12-19 03:22:19 -06001105png_set_compression_method(png_structp png_ptr, int method)
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001106{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001107 png_debug(1, "in png_set_compression_method\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001108 if (method != 8)
1109 png_warning(png_ptr, "Only compression method 8 is supported by PNG");
1110 png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001111 png_ptr->zlib_method = method;
Guy Schalnat0d580581995-07-20 02:43:20 -05001112}
1113
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001114void
1115png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
1116{
1117 png_ptr->write_row_fn = write_row_fn;
1118}
1119
1120#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
1121void
1122png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
1123 write_user_transform_fn)
1124{
1125 png_debug(1, "in png_set_write_user_transform_fn\n");
1126 png_ptr->transformations |= PNG_USER_TRANSFORM;
1127 png_ptr->write_user_transform_fn = write_user_transform_fn;
1128}
1129#endif