1 |
1 |
2 /* pngwrite.c - general routines to write a PNG file |
2 /* pngwrite.c - general routines to write a PNG file |
3 * |
3 * |
4 * Last changed in libpng 1.2.37 [June 4, 2009] |
4 * Last changed in libpng 1.4.0 [January 3, 2010] |
5 * Copyright (c) 1998-2009 Glenn Randers-Pehrson |
5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson |
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 * |
8 * |
9 * This code is released under the libpng license. |
9 * This code is released under the libpng license. |
10 * For conditions of distribution and use, see the disclaimer |
10 * For conditions of distribution and use, see the disclaimer |
11 * and license in png.h |
11 * and license in png.h |
12 */ |
12 */ |
13 |
13 |
14 /* Get internal access to png.h */ |
14 /* Get internal access to png.h */ |
15 #define PNG_INTERNAL |
15 #define PNG_NO_PEDANTIC_WARNINGS |
16 #include "png.h" |
16 #include "png.h" |
17 #ifdef PNG_WRITE_SUPPORTED |
17 #ifdef PNG_WRITE_SUPPORTED |
|
18 #include "pngpriv.h" |
18 |
19 |
19 /* Writes all the PNG information. This is the suggested way to use the |
20 /* Writes all the PNG information. This is the suggested way to use the |
20 * library. If you have a new chunk to add, make a function to write it, |
21 * library. If you have a new chunk to add, make a function to write it, |
21 * and put it in the correct location here. If you want the chunk written |
22 * and put it in the correct location here. If you want the chunk written |
22 * after the image data, put it in png_write_end(). I strongly encourage |
23 * after the image data, put it in png_write_end(). I strongly encourage |
27 */ |
28 */ |
28 void PNGAPI |
29 void PNGAPI |
29 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) |
30 png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) |
30 { |
31 { |
31 png_debug(1, "in png_write_info_before_PLTE"); |
32 png_debug(1, "in png_write_info_before_PLTE"); |
|
33 |
32 if (png_ptr == NULL || info_ptr == NULL) |
34 if (png_ptr == NULL || info_ptr == NULL) |
33 return; |
35 return; |
34 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) |
36 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) |
35 { |
37 { |
36 png_write_sig(png_ptr); /* Write PNG signature */ |
38 /* Write PNG signature */ |
37 #if defined(PNG_MNG_FEATURES_SUPPORTED) |
39 png_write_sig(png_ptr); |
|
40 #ifdef PNG_MNG_FEATURES_SUPPORTED |
38 if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) |
41 if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) |
39 { |
42 { |
40 png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); |
43 png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); |
41 png_ptr->mng_features_permitted=0; |
44 png_ptr->mng_features_permitted = 0; |
42 } |
45 } |
43 #endif |
46 #endif |
44 /* Write IHDR information. */ |
47 /* Write IHDR information. */ |
45 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, |
48 png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, |
46 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, |
49 info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, |
47 info_ptr->filter_type, |
50 info_ptr->filter_type, |
48 #if defined(PNG_WRITE_INTERLACING_SUPPORTED) |
51 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
49 info_ptr->interlace_type); |
52 info_ptr->interlace_type); |
50 #else |
53 #else |
51 0); |
54 0); |
52 #endif |
55 #endif |
53 /* The rest of these check to see if the valid field has the appropriate |
56 /* The rest of these check to see if the valid field has the appropriate |
54 * flag set, and if it does, writes the chunk. |
57 * flag set, and if it does, writes the chunk. |
55 */ |
58 */ |
56 #if defined(PNG_WRITE_gAMA_SUPPORTED) |
59 #ifdef PNG_WRITE_gAMA_SUPPORTED |
57 if (info_ptr->valid & PNG_INFO_gAMA) |
60 if (info_ptr->valid & PNG_INFO_gAMA) |
58 { |
61 { |
59 # ifdef PNG_FLOATING_POINT_SUPPORTED |
62 # ifdef PNG_FLOATING_POINT_SUPPORTED |
60 png_write_gAMA(png_ptr, info_ptr->gamma); |
63 png_write_gAMA(png_ptr, info_ptr->gamma); |
61 #else |
64 #else |
63 png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); |
66 png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); |
64 # endif |
67 # endif |
65 #endif |
68 #endif |
66 } |
69 } |
67 #endif |
70 #endif |
68 #if defined(PNG_WRITE_sRGB_SUPPORTED) |
71 #ifdef PNG_WRITE_sRGB_SUPPORTED |
69 if (info_ptr->valid & PNG_INFO_sRGB) |
72 if (info_ptr->valid & PNG_INFO_sRGB) |
70 png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); |
73 png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); |
71 #endif |
74 #endif |
72 #if defined(PNG_WRITE_iCCP_SUPPORTED) |
75 #ifdef PNG_WRITE_iCCP_SUPPORTED |
73 if (info_ptr->valid & PNG_INFO_iCCP) |
76 if (info_ptr->valid & PNG_INFO_iCCP) |
74 png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, |
77 png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, |
75 info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); |
78 info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); |
76 #endif |
79 #endif |
77 #if defined(PNG_WRITE_sBIT_SUPPORTED) |
80 #ifdef PNG_WRITE_sBIT_SUPPORTED |
78 if (info_ptr->valid & PNG_INFO_sBIT) |
81 if (info_ptr->valid & PNG_INFO_sBIT) |
79 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); |
82 png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); |
80 #endif |
83 #endif |
81 #if defined(PNG_WRITE_cHRM_SUPPORTED) |
84 #ifdef PNG_WRITE_cHRM_SUPPORTED |
82 if (info_ptr->valid & PNG_INFO_cHRM) |
85 if (info_ptr->valid & PNG_INFO_cHRM) |
83 { |
86 { |
84 #ifdef PNG_FLOATING_POINT_SUPPORTED |
87 #ifdef PNG_FLOATING_POINT_SUPPORTED |
85 png_write_cHRM(png_ptr, |
88 png_write_cHRM(png_ptr, |
86 info_ptr->x_white, info_ptr->y_white, |
89 info_ptr->x_white, info_ptr->y_white, |
145 png_write_PLTE(png_ptr, info_ptr->palette, |
148 png_write_PLTE(png_ptr, info_ptr->palette, |
146 (png_uint_32)info_ptr->num_palette); |
149 (png_uint_32)info_ptr->num_palette); |
147 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
150 else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
148 png_error(png_ptr, "Valid palette required for paletted images"); |
151 png_error(png_ptr, "Valid palette required for paletted images"); |
149 |
152 |
150 #if defined(PNG_WRITE_tRNS_SUPPORTED) |
153 #ifdef PNG_WRITE_tRNS_SUPPORTED |
151 if (info_ptr->valid & PNG_INFO_tRNS) |
154 if (info_ptr->valid & PNG_INFO_tRNS) |
152 { |
155 { |
153 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) |
156 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED |
154 /* Invert the alpha channel (in tRNS) */ |
157 /* Invert the alpha channel (in tRNS) */ |
155 if ((png_ptr->transformations & PNG_INVERT_ALPHA) && |
158 if ((png_ptr->transformations & PNG_INVERT_ALPHA) && |
156 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
159 info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
157 { |
160 { |
158 int j; |
161 int j; |
159 for (j=0; j<(int)info_ptr->num_trans; j++) |
162 for (j = 0; j<(int)info_ptr->num_trans; j++) |
160 info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); |
163 info_ptr->trans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]); |
161 } |
164 } |
162 #endif |
165 #endif |
163 png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), |
166 png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), |
164 info_ptr->num_trans, info_ptr->color_type); |
167 info_ptr->num_trans, info_ptr->color_type); |
165 } |
168 } |
166 #endif |
169 #endif |
167 #if defined(PNG_WRITE_bKGD_SUPPORTED) |
170 #ifdef PNG_WRITE_bKGD_SUPPORTED |
168 if (info_ptr->valid & PNG_INFO_bKGD) |
171 if (info_ptr->valid & PNG_INFO_bKGD) |
169 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); |
172 png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); |
170 #endif |
173 #endif |
171 #if defined(PNG_WRITE_hIST_SUPPORTED) |
174 #ifdef PNG_WRITE_hIST_SUPPORTED |
172 if (info_ptr->valid & PNG_INFO_hIST) |
175 if (info_ptr->valid & PNG_INFO_hIST) |
173 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); |
176 png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); |
174 #endif |
177 #endif |
175 #if defined(PNG_WRITE_oFFs_SUPPORTED) |
178 #ifdef PNG_WRITE_oFFs_SUPPORTED |
176 if (info_ptr->valid & PNG_INFO_oFFs) |
179 if (info_ptr->valid & PNG_INFO_oFFs) |
177 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, |
180 png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, |
178 info_ptr->offset_unit_type); |
181 info_ptr->offset_unit_type); |
179 #endif |
182 #endif |
180 #if defined(PNG_WRITE_pCAL_SUPPORTED) |
183 #ifdef PNG_WRITE_pCAL_SUPPORTED |
181 if (info_ptr->valid & PNG_INFO_pCAL) |
184 if (info_ptr->valid & PNG_INFO_pCAL) |
182 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, |
185 png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, |
183 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, |
186 info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, |
184 info_ptr->pcal_units, info_ptr->pcal_params); |
187 info_ptr->pcal_units, info_ptr->pcal_params); |
185 #endif |
188 #endif |
186 |
189 |
187 #if defined(PNG_sCAL_SUPPORTED) |
190 #ifdef PNG_sCAL_SUPPORTED |
188 if (info_ptr->valid & PNG_INFO_sCAL) |
191 if (info_ptr->valid & PNG_INFO_sCAL) |
189 #if defined(PNG_WRITE_sCAL_SUPPORTED) |
192 #ifdef PNG_WRITE_sCAL_SUPPORTED |
190 #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) |
193 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) |
191 png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, |
194 png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, |
192 info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); |
195 info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); |
193 #else /* !FLOATING_POINT */ |
196 #else /* !FLOATING_POINT */ |
194 #ifdef PNG_FIXED_POINT_SUPPORTED |
197 #ifdef PNG_FIXED_POINT_SUPPORTED |
195 png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, |
198 png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, |
196 info_ptr->scal_s_width, info_ptr->scal_s_height); |
199 info_ptr->scal_s_width, info_ptr->scal_s_height); |
197 #endif /* FIXED_POINT */ |
200 #endif /* FIXED_POINT */ |
198 #endif /* FLOATING_POINT */ |
201 #endif /* FLOATING_POINT */ |
199 #else /* !WRITE_sCAL */ |
202 #else /* !WRITE_sCAL */ |
200 png_warning(png_ptr, |
203 png_warning(png_ptr, |
201 "png_write_sCAL not supported; sCAL chunk not written."); |
204 "png_write_sCAL not supported; sCAL chunk not written"); |
202 #endif /* WRITE_sCAL */ |
205 #endif /* WRITE_sCAL */ |
203 #endif /* sCAL */ |
206 #endif /* sCAL */ |
204 |
207 |
205 #if defined(PNG_WRITE_pHYs_SUPPORTED) |
208 #ifdef PNG_WRITE_pHYs_SUPPORTED |
206 if (info_ptr->valid & PNG_INFO_pHYs) |
209 if (info_ptr->valid & PNG_INFO_pHYs) |
207 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, |
210 png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, |
208 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); |
211 info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); |
209 #endif /* pHYs */ |
212 #endif /* pHYs */ |
210 |
213 |
211 #if defined(PNG_WRITE_tIME_SUPPORTED) |
214 #ifdef PNG_WRITE_tIME_SUPPORTED |
212 if (info_ptr->valid & PNG_INFO_tIME) |
215 if (info_ptr->valid & PNG_INFO_tIME) |
213 { |
216 { |
214 png_write_tIME(png_ptr, &(info_ptr->mod_time)); |
217 png_write_tIME(png_ptr, &(info_ptr->mod_time)); |
215 png_ptr->mode |= PNG_WROTE_tIME; |
218 png_ptr->mode |= PNG_WROTE_tIME; |
216 } |
219 } |
217 #endif /* tIME */ |
220 #endif /* tIME */ |
218 |
221 |
219 #if defined(PNG_WRITE_sPLT_SUPPORTED) |
222 #ifdef PNG_WRITE_sPLT_SUPPORTED |
220 if (info_ptr->valid & PNG_INFO_sPLT) |
223 if (info_ptr->valid & PNG_INFO_sPLT) |
221 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) |
224 for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) |
222 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); |
225 png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); |
223 #endif /* sPLT */ |
226 #endif /* sPLT */ |
224 |
227 |
225 #if defined(PNG_WRITE_TEXT_SUPPORTED) |
228 #ifdef PNG_WRITE_TEXT_SUPPORTED |
226 /* Check to see if we need to write text chunks */ |
229 /* Check to see if we need to write text chunks */ |
227 for (i = 0; i < info_ptr->num_text; i++) |
230 for (i = 0; i < info_ptr->num_text; i++) |
228 { |
231 { |
229 png_debug2(2, "Writing header text chunk %d, type %d", i, |
232 png_debug2(2, "Writing header text chunk %d, type %d", i, |
230 info_ptr->text[i].compression); |
233 info_ptr->text[i].compression); |
231 /* An internationalized chunk? */ |
234 /* An internationalized chunk? */ |
232 if (info_ptr->text[i].compression > 0) |
235 if (info_ptr->text[i].compression > 0) |
233 { |
236 { |
234 #if defined(PNG_WRITE_iTXt_SUPPORTED) |
237 #ifdef PNG_WRITE_iTXt_SUPPORTED |
235 /* Write international chunk */ |
238 /* Write international chunk */ |
236 png_write_iTXt(png_ptr, |
239 png_write_iTXt(png_ptr, |
237 info_ptr->text[i].compression, |
240 info_ptr->text[i].compression, |
238 info_ptr->text[i].key, |
241 info_ptr->text[i].key, |
239 info_ptr->text[i].lang, |
242 info_ptr->text[i].lang, |
308 */ |
311 */ |
309 void PNGAPI |
312 void PNGAPI |
310 png_write_end(png_structp png_ptr, png_infop info_ptr) |
313 png_write_end(png_structp png_ptr, png_infop info_ptr) |
311 { |
314 { |
312 png_debug(1, "in png_write_end"); |
315 png_debug(1, "in png_write_end"); |
|
316 |
313 if (png_ptr == NULL) |
317 if (png_ptr == NULL) |
314 return; |
318 return; |
315 if (!(png_ptr->mode & PNG_HAVE_IDAT)) |
319 if (!(png_ptr->mode & PNG_HAVE_IDAT)) |
316 png_error(png_ptr, "No IDATs written into file"); |
320 png_error(png_ptr, "No IDATs written into file"); |
317 |
321 |
318 /* See if user wants us to write information chunks */ |
322 /* See if user wants us to write information chunks */ |
319 if (info_ptr != NULL) |
323 if (info_ptr != NULL) |
320 { |
324 { |
321 #if defined(PNG_WRITE_TEXT_SUPPORTED) |
325 #ifdef PNG_WRITE_TEXT_SUPPORTED |
322 int i; /* Local index variable */ |
326 int i; /* local index variable */ |
323 #endif |
327 #endif |
324 #if defined(PNG_WRITE_tIME_SUPPORTED) |
328 #ifdef PNG_WRITE_tIME_SUPPORTED |
325 /* Check to see if user has supplied a time chunk */ |
329 /* Check to see if user has supplied a time chunk */ |
326 if ((info_ptr->valid & PNG_INFO_tIME) && |
330 if ((info_ptr->valid & PNG_INFO_tIME) && |
327 !(png_ptr->mode & PNG_WROTE_tIME)) |
331 !(png_ptr->mode & PNG_WROTE_tIME)) |
328 png_write_tIME(png_ptr, &(info_ptr->mod_time)); |
332 png_write_tIME(png_ptr, &(info_ptr->mod_time)); |
329 #endif |
333 #endif |
330 #if defined(PNG_WRITE_TEXT_SUPPORTED) |
334 #ifdef PNG_WRITE_TEXT_SUPPORTED |
331 /* Loop through comment chunks */ |
335 /* Loop through comment chunks */ |
332 for (i = 0; i < info_ptr->num_text; i++) |
336 for (i = 0; i < info_ptr->num_text; i++) |
333 { |
337 { |
334 png_debug2(2, "Writing trailer text chunk %d, type %d", i, |
338 png_debug2(2, "Writing trailer text chunk %d, type %d", i, |
335 info_ptr->text[i].compression); |
339 info_ptr->text[i].compression); |
336 /* An internationalized chunk? */ |
340 /* An internationalized chunk? */ |
337 if (info_ptr->text[i].compression > 0) |
341 if (info_ptr->text[i].compression > 0) |
338 { |
342 { |
339 #if defined(PNG_WRITE_iTXt_SUPPORTED) |
343 #ifdef PNG_WRITE_iTXt_SUPPORTED |
340 /* Write international chunk */ |
344 /* Write international chunk */ |
341 png_write_iTXt(png_ptr, |
345 png_write_iTXt(png_ptr, |
342 info_ptr->text[i].compression, |
346 info_ptr->text[i].compression, |
343 info_ptr->text[i].key, |
347 info_ptr->text[i].key, |
344 info_ptr->text[i].lang, |
348 info_ptr->text[i].lang, |
345 info_ptr->text[i].lang_key, |
349 info_ptr->text[i].lang_key, |
346 info_ptr->text[i].text); |
350 info_ptr->text[i].text); |
347 #else |
351 #else |
348 png_warning(png_ptr, "Unable to write international text"); |
352 png_warning(png_ptr, "Unable to write international text"); |
349 #endif |
353 #endif |
350 /* Mark this chunk as written */ |
354 /* Mark this chunk as written */ |
351 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; |
355 info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; |
352 } |
356 } |
353 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) |
357 else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) |
354 { |
358 { |
355 #if defined(PNG_WRITE_zTXt_SUPPORTED) |
359 #ifdef PNG_WRITE_zTXt_SUPPORTED |
356 /* Write compressed chunk */ |
360 /* Write compressed chunk */ |
357 png_write_zTXt(png_ptr, info_ptr->text[i].key, |
361 png_write_zTXt(png_ptr, info_ptr->text[i].key, |
358 info_ptr->text[i].text, 0, |
362 info_ptr->text[i].text, 0, |
359 info_ptr->text[i].compression); |
363 info_ptr->text[i].compression); |
360 #else |
364 #else |
409 /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, |
413 /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, |
410 * and restored again in libpng-1.2.30, may cause some applications that |
414 * and restored again in libpng-1.2.30, may cause some applications that |
411 * do not set png_ptr->output_flush_fn to crash. If your application |
415 * do not set png_ptr->output_flush_fn to crash. If your application |
412 * experiences a problem, please try building libpng with |
416 * experiences a problem, please try building libpng with |
413 * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to |
417 * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to |
414 * png-mng-implement at lists.sf.net . This kludge will be removed |
418 * png-mng-implement at lists.sf.net . |
415 * from libpng-1.4.0. |
|
416 */ |
419 */ |
417 #if defined(PNG_WRITE_FLUSH_SUPPORTED) && \ |
420 #ifdef PNG_WRITE_FLUSH_SUPPORTED |
418 defined(PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED) |
421 # ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED |
419 png_flush(png_ptr); |
422 png_flush(png_ptr); |
420 #endif |
423 # endif |
421 } |
424 #endif |
422 |
425 } |
423 #if defined(PNG_WRITE_tIME_SUPPORTED) |
426 |
424 #if !defined(_WIN32_WCE) |
427 #ifdef PNG_CONVERT_tIME_SUPPORTED |
425 /* "time.h" functions are not supported on WindowsCE */ |
428 /* "tm" structure is not supported on WindowsCE */ |
426 void PNGAPI |
429 void PNGAPI |
427 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) |
430 png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) |
428 { |
431 { |
429 png_debug(1, "in png_convert_from_struct_tm"); |
432 png_debug(1, "in png_convert_from_struct_tm"); |
|
433 |
430 ptime->year = (png_uint_16)(1900 + ttime->tm_year); |
434 ptime->year = (png_uint_16)(1900 + ttime->tm_year); |
431 ptime->month = (png_byte)(ttime->tm_mon + 1); |
435 ptime->month = (png_byte)(ttime->tm_mon + 1); |
432 ptime->day = (png_byte)ttime->tm_mday; |
436 ptime->day = (png_byte)ttime->tm_mday; |
433 ptime->hour = (png_byte)ttime->tm_hour; |
437 ptime->hour = (png_byte)ttime->tm_hour; |
434 ptime->minute = (png_byte)ttime->tm_min; |
438 ptime->minute = (png_byte)ttime->tm_min; |
439 png_convert_from_time_t(png_timep ptime, time_t ttime) |
443 png_convert_from_time_t(png_timep ptime, time_t ttime) |
440 { |
444 { |
441 struct tm *tbuf; |
445 struct tm *tbuf; |
442 |
446 |
443 png_debug(1, "in png_convert_from_time_t"); |
447 png_debug(1, "in png_convert_from_time_t"); |
|
448 |
444 tbuf = gmtime(&ttime); |
449 tbuf = gmtime(&ttime); |
445 png_convert_from_struct_tm(ptime, tbuf); |
450 png_convert_from_struct_tm(ptime, tbuf); |
446 } |
451 } |
447 #endif |
|
448 #endif |
452 #endif |
449 |
453 |
450 /* Initialize png_ptr structure, and allocate any memory needed */ |
454 /* Initialize png_ptr structure, and allocate any memory needed */ |
451 png_structp PNGAPI |
455 png_structp PNGAPI |
452 png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, |
456 png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, |
453 png_error_ptr error_fn, png_error_ptr warn_fn) |
457 png_error_ptr error_fn, png_error_ptr warn_fn) |
454 { |
458 { |
455 #ifdef PNG_USER_MEM_SUPPORTED |
459 #ifdef PNG_USER_MEM_SUPPORTED |
456 return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, |
460 return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, |
457 warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); |
461 warn_fn, NULL, NULL, NULL)); |
458 } |
462 } |
459 |
463 |
460 /* Alternate initialize png_ptr structure, and allocate any memory needed */ |
464 /* Alternate initialize png_ptr structure, and allocate any memory needed */ |
461 png_structp PNGAPI |
465 png_structp PNGAPI |
462 png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, |
466 png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, |
463 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, |
467 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, |
464 png_malloc_ptr malloc_fn, png_free_ptr free_fn) |
468 png_malloc_ptr malloc_fn, png_free_ptr free_fn) |
465 { |
469 { |
466 #endif /* PNG_USER_MEM_SUPPORTED */ |
470 #endif /* PNG_USER_MEM_SUPPORTED */ |
|
471 volatile int png_cleanup_needed = 0; |
467 #ifdef PNG_SETJMP_SUPPORTED |
472 #ifdef PNG_SETJMP_SUPPORTED |
468 volatile |
473 volatile |
469 #endif |
474 #endif |
470 png_structp png_ptr; |
475 png_structp png_ptr; |
471 #ifdef PNG_SETJMP_SUPPORTED |
476 #ifdef PNG_SETJMP_SUPPORTED |
472 #ifdef USE_FAR_KEYWORD |
477 #ifdef USE_FAR_KEYWORD |
473 jmp_buf jmpbuf; |
478 jmp_buf jmpbuf; |
474 #endif |
479 #endif |
475 #endif |
480 #endif |
476 int i; |
481 int i; |
|
482 |
477 png_debug(1, "in png_create_write_struct"); |
483 png_debug(1, "in png_create_write_struct"); |
|
484 |
478 #ifdef PNG_USER_MEM_SUPPORTED |
485 #ifdef PNG_USER_MEM_SUPPORTED |
479 png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, |
486 png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, |
480 (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); |
487 (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); |
481 #else |
488 #else |
482 png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); |
489 png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); |
484 if (png_ptr == NULL) |
491 if (png_ptr == NULL) |
485 return (NULL); |
492 return (NULL); |
486 |
493 |
487 /* Added at libpng-1.2.6 */ |
494 /* Added at libpng-1.2.6 */ |
488 #ifdef PNG_SET_USER_LIMITS_SUPPORTED |
495 #ifdef PNG_SET_USER_LIMITS_SUPPORTED |
489 png_ptr->user_width_max=PNG_USER_WIDTH_MAX; |
496 png_ptr->user_width_max = PNG_USER_WIDTH_MAX; |
490 png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; |
497 png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; |
491 #endif |
498 #endif |
492 |
499 |
493 #ifdef PNG_SETJMP_SUPPORTED |
500 #ifdef PNG_SETJMP_SUPPORTED |
|
501 /* Applications that neglect to set up their own setjmp() and then |
|
502 encounter a png_error() will longjmp here. Since the jmpbuf is |
|
503 then meaningless we abort instead of returning. */ |
494 #ifdef USE_FAR_KEYWORD |
504 #ifdef USE_FAR_KEYWORD |
495 if (setjmp(jmpbuf)) |
505 if (setjmp(jmpbuf)) |
496 #else |
506 #else |
497 if (setjmp(png_ptr->jmpbuf)) |
507 if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ |
498 #endif |
508 #endif |
499 { |
|
500 png_free(png_ptr, png_ptr->zbuf); |
|
501 png_ptr->zbuf=NULL; |
|
502 png_destroy_struct(png_ptr); |
|
503 return (NULL); |
|
504 } |
|
505 #ifdef USE_FAR_KEYWORD |
509 #ifdef USE_FAR_KEYWORD |
506 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); |
510 png_memcpy(png_jmpbuf(png_ptr), jmpbuf, png_sizeof(jmp_buf)); |
507 #endif |
511 #endif |
|
512 PNG_ABORT(); |
508 #endif |
513 #endif |
509 |
514 |
510 #ifdef PNG_USER_MEM_SUPPORTED |
515 #ifdef PNG_USER_MEM_SUPPORTED |
511 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); |
516 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); |
512 #endif /* PNG_USER_MEM_SUPPORTED */ |
517 #endif /* PNG_USER_MEM_SUPPORTED */ |
513 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); |
518 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); |
514 |
519 |
515 if (user_png_ver) |
520 if (user_png_ver) |
516 { |
521 { |
517 i=0; |
522 i = 0; |
518 do |
523 do |
519 { |
524 { |
520 if (user_png_ver[i] != png_libpng_ver[i]) |
525 if (user_png_ver[i] != png_libpng_ver[i]) |
521 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; |
526 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; |
522 } while (png_libpng_ver[i++]); |
527 } while (png_libpng_ver[i++]); |
523 } |
528 } |
524 |
529 |
525 if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) |
530 if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) |
526 { |
531 { |
527 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so |
532 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so |
531 */ |
536 */ |
532 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || |
537 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || |
533 (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || |
538 (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || |
534 (user_png_ver[0] == '0' && user_png_ver[2] < '9')) |
539 (user_png_ver[0] == '0' && user_png_ver[2] < '9')) |
535 { |
540 { |
536 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) |
541 #ifdef PNG_STDIO_SUPPORTED |
537 char msg[80]; |
542 char msg[80]; |
538 if (user_png_ver) |
543 if (user_png_ver) |
539 { |
544 { |
540 png_snprintf(msg, 80, |
545 png_snprintf(msg, 80, |
541 "Application was compiled with png.h from libpng-%.20s", |
546 "Application was compiled with png.h from libpng-%.20s", |
542 user_png_ver); |
547 user_png_ver); |
543 png_warning(png_ptr, msg); |
548 png_warning(png_ptr, msg); |
544 } |
549 } |
545 png_snprintf(msg, 80, |
550 png_snprintf(msg, 80, |
546 "Application is running with png.c from libpng-%.20s", |
551 "Application is running with png.c from libpng-%.20s", |
547 png_libpng_ver); |
552 png_libpng_ver); |
548 png_warning(png_ptr, msg); |
553 png_warning(png_ptr, msg); |
549 #endif |
554 #endif |
550 #ifdef PNG_ERROR_NUMBERS_SUPPORTED |
555 #ifdef PNG_ERROR_NUMBERS_SUPPORTED |
551 png_ptr->flags=0; |
556 png_ptr->flags = 0; |
552 #endif |
557 #endif |
553 png_error(png_ptr, |
558 png_warning(png_ptr, |
554 "Incompatible libpng version in application and library"); |
559 "Incompatible libpng version in application and library"); |
|
560 png_cleanup_needed = 1; |
555 } |
561 } |
556 } |
562 } |
557 |
563 |
558 /* Initialize zbuf - compression buffer */ |
564 /* Initialize zbuf - compression buffer */ |
559 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
565 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
560 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, |
566 if (!png_cleanup_needed) |
561 (png_uint_32)png_ptr->zbuf_size); |
567 { |
562 |
568 png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, |
563 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, |
569 png_ptr->zbuf_size); |
564 png_flush_ptr_NULL); |
570 if (png_ptr->zbuf == NULL) |
565 |
571 png_cleanup_needed = 1; |
566 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) |
572 } |
|
573 if (png_cleanup_needed) |
|
574 { |
|
575 /* Clean up PNG structure and deallocate any memory. */ |
|
576 png_free(png_ptr, png_ptr->zbuf); |
|
577 png_ptr->zbuf = NULL; |
|
578 #ifdef PNG_USER_MEM_SUPPORTED |
|
579 png_destroy_struct_2((png_voidp)png_ptr, |
|
580 (png_free_ptr)free_fn, (png_voidp)mem_ptr); |
|
581 #else |
|
582 png_destroy_struct((png_voidp)png_ptr); |
|
583 #endif |
|
584 return (NULL); |
|
585 } |
|
586 |
|
587 png_set_write_fn(png_ptr, NULL, NULL, NULL); |
|
588 |
|
589 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED |
567 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, |
590 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, |
568 1, png_doublep_NULL, png_doublep_NULL); |
591 1, NULL, NULL); |
569 #endif |
592 #endif |
570 |
593 |
571 #ifdef PNG_SETJMP_SUPPORTED |
|
572 /* Applications that neglect to set up their own setjmp() and then encounter |
|
573 a png_error() will longjmp here. Since the jmpbuf is then meaningless we |
|
574 abort instead of returning. */ |
|
575 #ifdef USE_FAR_KEYWORD |
|
576 if (setjmp(jmpbuf)) |
|
577 PNG_ABORT(); |
|
578 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); |
|
579 #else |
|
580 if (setjmp(png_ptr->jmpbuf)) |
|
581 PNG_ABORT(); |
|
582 #endif |
|
583 #endif |
|
584 return (png_ptr); |
594 return (png_ptr); |
585 } |
595 } |
586 |
596 |
587 /* Initialize png_ptr structure, and allocate any memory needed */ |
|
588 #if defined(PNG_1_0_X) || defined(PNG_1_2_X) |
|
589 /* Deprecated. */ |
|
590 #undef png_write_init |
|
591 void PNGAPI |
|
592 png_write_init(png_structp png_ptr) |
|
593 { |
|
594 /* We only come here via pre-1.0.7-compiled applications */ |
|
595 png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); |
|
596 } |
|
597 |
|
598 void PNGAPI |
|
599 png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, |
|
600 png_size_t png_struct_size, png_size_t png_info_size) |
|
601 { |
|
602 /* We only come here via pre-1.0.12-compiled applications */ |
|
603 if (png_ptr == NULL) return; |
|
604 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) |
|
605 if (png_sizeof(png_struct) > png_struct_size || |
|
606 png_sizeof(png_info) > png_info_size) |
|
607 { |
|
608 char msg[80]; |
|
609 png_ptr->warning_fn=NULL; |
|
610 if (user_png_ver) |
|
611 { |
|
612 png_snprintf(msg, 80, |
|
613 "Application was compiled with png.h from libpng-%.20s", |
|
614 user_png_ver); |
|
615 png_warning(png_ptr, msg); |
|
616 } |
|
617 png_snprintf(msg, 80, |
|
618 "Application is running with png.c from libpng-%.20s", |
|
619 png_libpng_ver); |
|
620 png_warning(png_ptr, msg); |
|
621 } |
|
622 #endif |
|
623 if (png_sizeof(png_struct) > png_struct_size) |
|
624 { |
|
625 png_ptr->error_fn=NULL; |
|
626 #ifdef PNG_ERROR_NUMBERS_SUPPORTED |
|
627 png_ptr->flags=0; |
|
628 #endif |
|
629 png_error(png_ptr, |
|
630 "The png struct allocated by the application for writing is too small."); |
|
631 } |
|
632 if (png_sizeof(png_info) > png_info_size) |
|
633 { |
|
634 png_ptr->error_fn=NULL; |
|
635 #ifdef PNG_ERROR_NUMBERS_SUPPORTED |
|
636 png_ptr->flags=0; |
|
637 #endif |
|
638 png_error(png_ptr, |
|
639 "The info struct allocated by the application for writing is too small."); |
|
640 } |
|
641 png_write_init_3(&png_ptr, user_png_ver, png_struct_size); |
|
642 } |
|
643 #endif /* PNG_1_0_X || PNG_1_2_X */ |
|
644 |
|
645 |
|
646 void PNGAPI |
|
647 png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, |
|
648 png_size_t png_struct_size) |
|
649 { |
|
650 png_structp png_ptr=*ptr_ptr; |
|
651 #ifdef PNG_SETJMP_SUPPORTED |
|
652 jmp_buf tmp_jmp; /* To save current jump buffer */ |
|
653 #endif |
|
654 |
|
655 int i = 0; |
|
656 |
|
657 if (png_ptr == NULL) |
|
658 return; |
|
659 |
|
660 do |
|
661 { |
|
662 if (user_png_ver[i] != png_libpng_ver[i]) |
|
663 { |
|
664 #ifdef PNG_LEGACY_SUPPORTED |
|
665 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; |
|
666 #else |
|
667 png_ptr->warning_fn=NULL; |
|
668 png_warning(png_ptr, |
|
669 "Application uses deprecated png_write_init() and should be recompiled."); |
|
670 break; |
|
671 #endif |
|
672 } |
|
673 } while (png_libpng_ver[i++]); |
|
674 |
|
675 png_debug(1, "in png_write_init_3"); |
|
676 |
|
677 #ifdef PNG_SETJMP_SUPPORTED |
|
678 /* Save jump buffer and error functions */ |
|
679 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); |
|
680 #endif |
|
681 |
|
682 if (png_sizeof(png_struct) > png_struct_size) |
|
683 { |
|
684 png_destroy_struct(png_ptr); |
|
685 png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); |
|
686 *ptr_ptr = png_ptr; |
|
687 } |
|
688 |
|
689 /* Reset all variables to 0 */ |
|
690 png_memset(png_ptr, 0, png_sizeof(png_struct)); |
|
691 |
|
692 /* Added at libpng-1.2.6 */ |
|
693 #ifdef PNG_SET_USER_LIMITS_SUPPORTED |
|
694 png_ptr->user_width_max=PNG_USER_WIDTH_MAX; |
|
695 png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; |
|
696 #endif |
|
697 |
|
698 #ifdef PNG_SETJMP_SUPPORTED |
|
699 /* Restore jump buffer */ |
|
700 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); |
|
701 #endif |
|
702 |
|
703 png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, |
|
704 png_flush_ptr_NULL); |
|
705 |
|
706 /* Initialize zbuf - compression buffer */ |
|
707 png_ptr->zbuf_size = PNG_ZBUF_SIZE; |
|
708 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, |
|
709 (png_uint_32)png_ptr->zbuf_size); |
|
710 |
|
711 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) |
|
712 png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, |
|
713 1, png_doublep_NULL, png_doublep_NULL); |
|
714 #endif |
|
715 } |
|
716 |
597 |
717 /* Write a few rows of image data. If the image is interlaced, |
598 /* Write a few rows of image data. If the image is interlaced, |
718 * either you will have to write the 7 sub images, or, if you |
599 * either you will have to write the 7 sub images, or, if you |
719 * have called png_set_interlace_handling(), you will have to |
600 * have called png_set_interlace_handling(), you will have to |
720 * "write" the image seven times. |
601 * "write" the image seven times. |
721 */ |
602 */ |
722 void PNGAPI |
603 void PNGAPI |
723 png_write_rows(png_structp png_ptr, png_bytepp row, |
604 png_write_rows(png_structp png_ptr, png_bytepp row, |
724 png_uint_32 num_rows) |
605 png_uint_32 num_rows) |
725 { |
606 { |
726 png_uint_32 i; /* Row counter */ |
607 png_uint_32 i; /* row counter */ |
727 png_bytepp rp; /* Row pointer */ |
608 png_bytepp rp; /* row pointer */ |
728 |
609 |
729 png_debug(1, "in png_write_rows"); |
610 png_debug(1, "in png_write_rows"); |
730 |
611 |
731 if (png_ptr == NULL) |
612 if (png_ptr == NULL) |
732 return; |
613 return; |
775 void PNGAPI |
657 void PNGAPI |
776 png_write_row(png_structp png_ptr, png_bytep row) |
658 png_write_row(png_structp png_ptr, png_bytep row) |
777 { |
659 { |
778 if (png_ptr == NULL) |
660 if (png_ptr == NULL) |
779 return; |
661 return; |
|
662 |
780 png_debug2(1, "in png_write_row (row %ld, pass %d)", |
663 png_debug2(1, "in png_write_row (row %ld, pass %d)", |
781 png_ptr->row_number, png_ptr->pass); |
664 png_ptr->row_number, png_ptr->pass); |
782 |
665 |
783 /* Initialize transformations and other stuff if first time */ |
666 /* Initialize transformations and other stuff if first time */ |
784 if (png_ptr->row_number == 0 && png_ptr->pass == 0) |
667 if (png_ptr->row_number == 0 && png_ptr->pass == 0) |
785 { |
668 { |
786 /* Make sure we wrote the header info */ |
669 /* Make sure we wrote the header info */ |
787 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) |
670 if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) |
788 png_error(png_ptr, |
671 png_error(png_ptr, |
789 "png_write_info was never called before png_write_row."); |
672 "png_write_info was never called before png_write_row"); |
790 |
673 |
791 /* Check for transforms that have been set but were defined out */ |
674 /* Check for transforms that have been set but were defined out */ |
792 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) |
675 #if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) |
793 if (png_ptr->transformations & PNG_INVERT_MONO) |
676 if (png_ptr->transformations & PNG_INVERT_MONO) |
794 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); |
677 png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); |
795 #endif |
678 #endif |
796 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) |
679 #if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) |
797 if (png_ptr->transformations & PNG_FILLER) |
680 if (png_ptr->transformations & PNG_FILLER) |
798 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); |
681 png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); |
799 #endif |
682 #endif |
800 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) |
683 #if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) |
801 if (png_ptr->transformations & PNG_PACKSWAP) |
684 if (png_ptr->transformations & PNG_PACKSWAP) |
802 png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); |
685 png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); |
803 #endif |
686 #endif |
804 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) |
687 #if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) |
805 if (png_ptr->transformations & PNG_PACK) |
688 if (png_ptr->transformations & PNG_PACK) |
806 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); |
689 png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); |
807 #endif |
690 #endif |
808 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) |
691 #if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) |
809 if (png_ptr->transformations & PNG_SHIFT) |
692 if (png_ptr->transformations & PNG_SHIFT) |
810 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); |
693 png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); |
811 #endif |
694 #endif |
812 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) |
695 #if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) |
813 if (png_ptr->transformations & PNG_BGR) |
696 if (png_ptr->transformations & PNG_BGR) |
814 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); |
697 png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); |
815 #endif |
698 #endif |
816 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) |
699 #if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) |
817 if (png_ptr->transformations & PNG_SWAP_BYTES) |
700 if (png_ptr->transformations & PNG_SWAP_BYTES) |
818 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); |
701 png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); |
819 #endif |
702 #endif |
820 |
703 |
821 png_write_start_row(png_ptr); |
704 png_write_start_row(png_ptr); |
822 } |
705 } |
823 |
706 |
824 #if defined(PNG_WRITE_INTERLACING_SUPPORTED) |
707 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
825 /* If interlaced and not interested in row, return */ |
708 /* If interlaced and not interested in row, return */ |
826 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) |
709 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) |
827 { |
710 { |
828 switch (png_ptr->pass) |
711 switch (png_ptr->pass) |
829 { |
712 { |
1097 #ifdef PNG_USER_MEM_SUPPORTED |
981 #ifdef PNG_USER_MEM_SUPPORTED |
1098 png_free_ptr free_fn; |
982 png_free_ptr free_fn; |
1099 #endif |
983 #endif |
1100 |
984 |
1101 png_debug(1, "in png_write_destroy"); |
985 png_debug(1, "in png_write_destroy"); |
|
986 |
1102 /* Free any memory zlib uses */ |
987 /* Free any memory zlib uses */ |
1103 deflateEnd(&png_ptr->zstream); |
988 deflateEnd(&png_ptr->zstream); |
1104 |
989 |
1105 /* Free our memory. png_free checks NULL for us. */ |
990 /* Free our memory. png_free checks NULL for us. */ |
1106 png_free(png_ptr, png_ptr->zbuf); |
991 png_free(png_ptr, png_ptr->zbuf); |
1107 png_free(png_ptr, png_ptr->row_buf); |
992 png_free(png_ptr, png_ptr->row_buf); |
1108 #ifndef PNG_NO_WRITE_FILTER |
993 #ifdef PNG_WRITE_FILTER_SUPPORTED |
1109 png_free(png_ptr, png_ptr->prev_row); |
994 png_free(png_ptr, png_ptr->prev_row); |
1110 png_free(png_ptr, png_ptr->sub_row); |
995 png_free(png_ptr, png_ptr->sub_row); |
1111 png_free(png_ptr, png_ptr->up_row); |
996 png_free(png_ptr, png_ptr->up_row); |
1112 png_free(png_ptr, png_ptr->avg_row); |
997 png_free(png_ptr, png_ptr->avg_row); |
1113 png_free(png_ptr, png_ptr->paeth_row); |
998 png_free(png_ptr, png_ptr->paeth_row); |
1114 #endif |
999 #endif |
1115 |
1000 |
1116 #if defined(PNG_TIME_RFC1123_SUPPORTED) |
1001 #ifdef PNG_TIME_RFC1123_SUPPORTED |
1117 png_free(png_ptr, png_ptr->time_buffer); |
1002 png_free(png_ptr, png_ptr->time_buffer); |
1118 #endif |
1003 #endif |
1119 |
1004 |
1120 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) |
1005 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED |
1121 png_free(png_ptr, png_ptr->prev_filters); |
1006 png_free(png_ptr, png_ptr->prev_filters); |
1122 png_free(png_ptr, png_ptr->filter_weights); |
1007 png_free(png_ptr, png_ptr->filter_weights); |
1123 png_free(png_ptr, png_ptr->inv_filter_weights); |
1008 png_free(png_ptr, png_ptr->inv_filter_weights); |
1124 png_free(png_ptr, png_ptr->filter_costs); |
1009 png_free(png_ptr, png_ptr->filter_costs); |
1125 png_free(png_ptr, png_ptr->inv_filter_costs); |
1010 png_free(png_ptr, png_ptr->inv_filter_costs); |
1154 /* Allow the application to select one or more row filters to use. */ |
1039 /* Allow the application to select one or more row filters to use. */ |
1155 void PNGAPI |
1040 void PNGAPI |
1156 png_set_filter(png_structp png_ptr, int method, int filters) |
1041 png_set_filter(png_structp png_ptr, int method, int filters) |
1157 { |
1042 { |
1158 png_debug(1, "in png_set_filter"); |
1043 png_debug(1, "in png_set_filter"); |
1159 if (png_ptr == NULL) |
1044 |
1160 return; |
1045 if (png_ptr == NULL) |
1161 #if defined(PNG_MNG_FEATURES_SUPPORTED) |
1046 return; |
|
1047 #ifdef PNG_MNG_FEATURES_SUPPORTED |
1162 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && |
1048 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && |
1163 (method == PNG_INTRAPIXEL_DIFFERENCING)) |
1049 (method == PNG_INTRAPIXEL_DIFFERENCING)) |
1164 method = PNG_FILTER_TYPE_BASE; |
1050 method = PNG_FILTER_TYPE_BASE; |
1165 #endif |
1051 #endif |
1166 if (method == PNG_FILTER_TYPE_BASE) |
1052 if (method == PNG_FILTER_TYPE_BASE) |
1167 { |
1053 { |
1168 switch (filters & (PNG_ALL_FILTERS | 0x07)) |
1054 switch (filters & (PNG_ALL_FILTERS | 0x07)) |
1169 { |
1055 { |
1170 #ifndef PNG_NO_WRITE_FILTER |
1056 #ifdef PNG_WRITE_FILTER_SUPPORTED |
1171 case 5: |
1057 case 5: |
1172 case 6: |
1058 case 6: |
1173 case 7: png_warning(png_ptr, "Unknown row filter for method 0"); |
1059 case 7: png_warning(png_ptr, "Unknown row filter for method 0"); |
1174 #endif /* PNG_NO_WRITE_FILTER */ |
1060 #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
1175 case PNG_FILTER_VALUE_NONE: |
1061 case PNG_FILTER_VALUE_NONE: |
1176 png_ptr->do_filter=PNG_FILTER_NONE; break; |
1062 png_ptr->do_filter = PNG_FILTER_NONE; break; |
1177 #ifndef PNG_NO_WRITE_FILTER |
1063 #ifdef PNG_WRITE_FILTER_SUPPORTED |
1178 case PNG_FILTER_VALUE_SUB: |
1064 case PNG_FILTER_VALUE_SUB: |
1179 png_ptr->do_filter=PNG_FILTER_SUB; break; |
1065 png_ptr->do_filter = PNG_FILTER_SUB; break; |
1180 case PNG_FILTER_VALUE_UP: |
1066 case PNG_FILTER_VALUE_UP: |
1181 png_ptr->do_filter=PNG_FILTER_UP; break; |
1067 png_ptr->do_filter = PNG_FILTER_UP; break; |
1182 case PNG_FILTER_VALUE_AVG: |
1068 case PNG_FILTER_VALUE_AVG: |
1183 png_ptr->do_filter=PNG_FILTER_AVG; break; |
1069 png_ptr->do_filter = PNG_FILTER_AVG; break; |
1184 case PNG_FILTER_VALUE_PAETH: |
1070 case PNG_FILTER_VALUE_PAETH: |
1185 png_ptr->do_filter=PNG_FILTER_PAETH; break; |
1071 png_ptr->do_filter = PNG_FILTER_PAETH; break; |
1186 default: png_ptr->do_filter = (png_byte)filters; break; |
1072 default: png_ptr->do_filter = (png_byte)filters; break; |
1187 #else |
1073 #else |
1188 default: png_warning(png_ptr, "Unknown row filter for method 0"); |
1074 default: png_warning(png_ptr, "Unknown row filter for method 0"); |
1189 #endif /* PNG_NO_WRITE_FILTER */ |
1075 #endif /* PNG_WRITE_FILTER_SUPPORTED */ |
1190 } |
1076 } |
1191 |
1077 |
1192 /* If we have allocated the row_buf, this means we have already started |
1078 /* If we have allocated the row_buf, this means we have already started |
1193 * with the image and we should have allocated all of the filter buffers |
1079 * with the image and we should have allocated all of the filter buffers |
1194 * that have been selected. If prev_row isn't already allocated, then |
1080 * that have been selected. If prev_row isn't already allocated, then |
1458 if (png_ptr == NULL) |
1349 if (png_ptr == NULL) |
1459 return; |
1350 return; |
1460 png_ptr->write_row_fn = write_row_fn; |
1351 png_ptr->write_row_fn = write_row_fn; |
1461 } |
1352 } |
1462 |
1353 |
1463 #if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) |
1354 #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED |
1464 void PNGAPI |
1355 void PNGAPI |
1465 png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr |
1356 png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr |
1466 write_user_transform_fn) |
1357 write_user_transform_fn) |
1467 { |
1358 { |
1468 png_debug(1, "in png_set_write_user_transform_fn"); |
1359 png_debug(1, "in png_set_write_user_transform_fn"); |
|
1360 |
1469 if (png_ptr == NULL) |
1361 if (png_ptr == NULL) |
1470 return; |
1362 return; |
1471 png_ptr->transformations |= PNG_USER_TRANSFORM; |
1363 png_ptr->transformations |= PNG_USER_TRANSFORM; |
1472 png_ptr->write_user_transform_fn = write_user_transform_fn; |
1364 png_ptr->write_user_transform_fn = write_user_transform_fn; |
1473 } |
1365 } |
1474 #endif |
1366 #endif |
1475 |
1367 |
1476 |
1368 |
1477 #if defined(PNG_INFO_IMAGE_SUPPORTED) |
1369 #ifdef PNG_INFO_IMAGE_SUPPORTED |
1478 void PNGAPI |
1370 void PNGAPI |
1479 png_write_png(png_structp png_ptr, png_infop info_ptr, |
1371 png_write_png(png_structp png_ptr, png_infop info_ptr, |
1480 int transforms, voidp params) |
1372 int transforms, voidp params) |
1481 { |
1373 { |
1482 if (png_ptr == NULL || info_ptr == NULL) |
1374 if (png_ptr == NULL || info_ptr == NULL) |
1483 return; |
1375 return; |
1484 #if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) |
|
1485 /* Invert the alpha channel from opacity to transparency */ |
|
1486 if (transforms & PNG_TRANSFORM_INVERT_ALPHA) |
|
1487 png_set_invert_alpha(png_ptr); |
|
1488 #endif |
|
1489 |
1376 |
1490 /* Write the file header information. */ |
1377 /* Write the file header information. */ |
1491 png_write_info(png_ptr, info_ptr); |
1378 png_write_info(png_ptr, info_ptr); |
1492 |
1379 |
1493 /* ------ these transformations don't touch the info structure ------- */ |
1380 /* ------ these transformations don't touch the info structure ------- */ |
1494 |
1381 |
1495 #if defined(PNG_WRITE_INVERT_SUPPORTED) |
1382 #ifdef PNG_WRITE_INVERT_SUPPORTED |
1496 /* Invert monochrome pixels */ |
1383 /* Invert monochrome pixels */ |
1497 if (transforms & PNG_TRANSFORM_INVERT_MONO) |
1384 if (transforms & PNG_TRANSFORM_INVERT_MONO) |
1498 png_set_invert_mono(png_ptr); |
1385 png_set_invert_mono(png_ptr); |
1499 #endif |
1386 #endif |
1500 |
1387 |
1501 #if defined(PNG_WRITE_SHIFT_SUPPORTED) |
1388 #ifdef PNG_WRITE_SHIFT_SUPPORTED |
1502 /* Shift the pixels up to a legal bit depth and fill in |
1389 /* Shift the pixels up to a legal bit depth and fill in |
1503 * as appropriate to correctly scale the image. |
1390 * as appropriate to correctly scale the image. |
1504 */ |
1391 */ |
1505 if ((transforms & PNG_TRANSFORM_SHIFT) |
1392 if ((transforms & PNG_TRANSFORM_SHIFT) |
1506 && (info_ptr->valid & PNG_INFO_sBIT)) |
1393 && (info_ptr->valid & PNG_INFO_sBIT)) |
1507 png_set_shift(png_ptr, &info_ptr->sig_bit); |
1394 png_set_shift(png_ptr, &info_ptr->sig_bit); |
1508 #endif |
1395 #endif |
1509 |
1396 |
1510 #if defined(PNG_WRITE_PACK_SUPPORTED) |
1397 #ifdef PNG_WRITE_PACK_SUPPORTED |
1511 /* Pack pixels into bytes */ |
1398 /* Pack pixels into bytes */ |
1512 if (transforms & PNG_TRANSFORM_PACKING) |
1399 if (transforms & PNG_TRANSFORM_PACKING) |
1513 png_set_packing(png_ptr); |
1400 png_set_packing(png_ptr); |
1514 #endif |
1401 #endif |
1515 |
1402 |
1516 #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) |
1403 #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED |
1517 /* Swap location of alpha bytes from ARGB to RGBA */ |
1404 /* Swap location of alpha bytes from ARGB to RGBA */ |
1518 if (transforms & PNG_TRANSFORM_SWAP_ALPHA) |
1405 if (transforms & PNG_TRANSFORM_SWAP_ALPHA) |
1519 png_set_swap_alpha(png_ptr); |
1406 png_set_swap_alpha(png_ptr); |
1520 #endif |
1407 #endif |
1521 |
1408 |
1522 #if defined(PNG_WRITE_FILLER_SUPPORTED) |
1409 #ifdef PNG_WRITE_FILLER_SUPPORTED |
1523 /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ |
1410 /* Pack XRGB/RGBX/ARGB/RGBA into * RGB (4 channels -> 3 channels) */ |
1524 if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) |
1411 if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) |
1525 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); |
1412 png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); |
1526 else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) |
1413 else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) |
1527 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); |
1414 png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); |
1528 #endif |
1415 #endif |
1529 |
1416 |
1530 #if defined(PNG_WRITE_BGR_SUPPORTED) |
1417 #ifdef PNG_WRITE_BGR_SUPPORTED |
1531 /* Flip BGR pixels to RGB */ |
1418 /* Flip BGR pixels to RGB */ |
1532 if (transforms & PNG_TRANSFORM_BGR) |
1419 if (transforms & PNG_TRANSFORM_BGR) |
1533 png_set_bgr(png_ptr); |
1420 png_set_bgr(png_ptr); |
1534 #endif |
1421 #endif |
1535 |
1422 |
1536 #if defined(PNG_WRITE_SWAP_SUPPORTED) |
1423 #ifdef PNG_WRITE_SWAP_SUPPORTED |
1537 /* Swap bytes of 16-bit files to most significant byte first */ |
1424 /* Swap bytes of 16-bit files to most significant byte first */ |
1538 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) |
1425 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) |
1539 png_set_swap(png_ptr); |
1426 png_set_swap(png_ptr); |
1540 #endif |
1427 #endif |
1541 |
1428 |
1542 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) |
1429 #ifdef PNG_WRITE_PACKSWAP_SUPPORTED |
1543 /* Swap bits of 1, 2, 4 bit packed pixel formats */ |
1430 /* Swap bits of 1, 2, 4 bit packed pixel formats */ |
1544 if (transforms & PNG_TRANSFORM_PACKSWAP) |
1431 if (transforms & PNG_TRANSFORM_PACKSWAP) |
1545 png_set_packswap(png_ptr); |
1432 png_set_packswap(png_ptr); |
1546 #endif |
1433 #endif |
1547 |
1434 |
|
1435 #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED |
|
1436 /* Invert the alpha channel from opacity to transparency */ |
|
1437 if (transforms & PNG_TRANSFORM_INVERT_ALPHA) |
|
1438 png_set_invert_alpha(png_ptr); |
|
1439 #endif |
|
1440 |
1548 /* ----------------------- end of transformations ------------------- */ |
1441 /* ----------------------- end of transformations ------------------- */ |
1549 |
1442 |
1550 /* Write the bits */ |
1443 /* Write the bits */ |
1551 if (info_ptr->valid & PNG_INFO_IDAT) |
1444 if (info_ptr->valid & PNG_INFO_IDAT) |
1552 png_write_image(png_ptr, info_ptr->row_pointers); |
1445 png_write_image(png_ptr, info_ptr->row_pointers); |