3dphotoshoot
diff libs/libpng/pngwrite.c @ 14:06dc8b9b4f89
added libimago, libjpeg and libpng
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 07 Jun 2015 17:25:49 +0300 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/libpng/pngwrite.c Sun Jun 07 17:25:49 2015 +0300 1.3 @@ -0,0 +1,1547 @@ 1.4 + 1.5 +/* pngwrite.c - general routines to write a PNG file 1.6 + * 1.7 + * Last changed in libpng 1.2.31 [August 19, 2008] 1.8 + * For conditions of distribution and use, see copyright notice in png.h 1.9 + * Copyright (c) 1998-2008 Glenn Randers-Pehrson 1.10 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 1.11 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 1.12 + */ 1.13 + 1.14 +/* get internal access to png.h */ 1.15 +#define PNG_INTERNAL 1.16 +#include "png.h" 1.17 +#ifdef PNG_WRITE_SUPPORTED 1.18 + 1.19 +/* Writes all the PNG information. This is the suggested way to use the 1.20 + * library. If you have a new chunk to add, make a function to write it, 1.21 + * and put it in the correct location here. If you want the chunk written 1.22 + * after the image data, put it in png_write_end(). I strongly encourage 1.23 + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing 1.24 + * the chunk, as that will keep the code from breaking if you want to just 1.25 + * write a plain PNG file. If you have long comments, I suggest writing 1.26 + * them in png_write_end(), and compressing them. 1.27 + */ 1.28 +void PNGAPI 1.29 +png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr) 1.30 +{ 1.31 + png_debug(1, "in png_write_info_before_PLTE\n"); 1.32 + if (png_ptr == NULL || info_ptr == NULL) 1.33 + return; 1.34 + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) 1.35 + { 1.36 + png_write_sig(png_ptr); /* write PNG signature */ 1.37 +#if defined(PNG_MNG_FEATURES_SUPPORTED) 1.38 + if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&(png_ptr->mng_features_permitted)) 1.39 + { 1.40 + png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); 1.41 + png_ptr->mng_features_permitted=0; 1.42 + } 1.43 +#endif 1.44 + /* write IHDR information. */ 1.45 + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, 1.46 + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, 1.47 + info_ptr->filter_type, 1.48 +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) 1.49 + info_ptr->interlace_type); 1.50 +#else 1.51 + 0); 1.52 +#endif 1.53 + /* the rest of these check to see if the valid field has the appropriate 1.54 + flag set, and if it does, writes the chunk. */ 1.55 +#if defined(PNG_WRITE_gAMA_SUPPORTED) 1.56 + if (info_ptr->valid & PNG_INFO_gAMA) 1.57 + { 1.58 +# ifdef PNG_FLOATING_POINT_SUPPORTED 1.59 + png_write_gAMA(png_ptr, info_ptr->gamma); 1.60 +#else 1.61 +#ifdef PNG_FIXED_POINT_SUPPORTED 1.62 + png_write_gAMA_fixed(png_ptr, info_ptr->int_gamma); 1.63 +# endif 1.64 +#endif 1.65 + } 1.66 +#endif 1.67 +#if defined(PNG_WRITE_sRGB_SUPPORTED) 1.68 + if (info_ptr->valid & PNG_INFO_sRGB) 1.69 + png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent); 1.70 +#endif 1.71 +#if defined(PNG_WRITE_iCCP_SUPPORTED) 1.72 + if (info_ptr->valid & PNG_INFO_iCCP) 1.73 + png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE, 1.74 + info_ptr->iccp_profile, (int)info_ptr->iccp_proflen); 1.75 +#endif 1.76 +#if defined(PNG_WRITE_sBIT_SUPPORTED) 1.77 + if (info_ptr->valid & PNG_INFO_sBIT) 1.78 + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); 1.79 +#endif 1.80 +#if defined(PNG_WRITE_cHRM_SUPPORTED) 1.81 + if (info_ptr->valid & PNG_INFO_cHRM) 1.82 + { 1.83 +#ifdef PNG_FLOATING_POINT_SUPPORTED 1.84 + png_write_cHRM(png_ptr, 1.85 + info_ptr->x_white, info_ptr->y_white, 1.86 + info_ptr->x_red, info_ptr->y_red, 1.87 + info_ptr->x_green, info_ptr->y_green, 1.88 + info_ptr->x_blue, info_ptr->y_blue); 1.89 +#else 1.90 +# ifdef PNG_FIXED_POINT_SUPPORTED 1.91 + png_write_cHRM_fixed(png_ptr, 1.92 + info_ptr->int_x_white, info_ptr->int_y_white, 1.93 + info_ptr->int_x_red, info_ptr->int_y_red, 1.94 + info_ptr->int_x_green, info_ptr->int_y_green, 1.95 + info_ptr->int_x_blue, info_ptr->int_y_blue); 1.96 +# endif 1.97 +#endif 1.98 + } 1.99 +#endif 1.100 +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) 1.101 + if (info_ptr->unknown_chunks_num) 1.102 + { 1.103 + png_unknown_chunk *up; 1.104 + 1.105 + png_debug(5, "writing extra chunks\n"); 1.106 + 1.107 + for (up = info_ptr->unknown_chunks; 1.108 + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; 1.109 + up++) 1.110 + { 1.111 + int keep=png_handle_as_unknown(png_ptr, up->name); 1.112 + if (keep != PNG_HANDLE_CHUNK_NEVER && 1.113 + up->location && !(up->location & PNG_HAVE_PLTE) && 1.114 + !(up->location & PNG_HAVE_IDAT) && 1.115 + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || 1.116 + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) 1.117 + { 1.118 + if (up->size == 0) 1.119 + png_warning(png_ptr, "Writing zero-length unknown chunk"); 1.120 + png_write_chunk(png_ptr, up->name, up->data, up->size); 1.121 + } 1.122 + } 1.123 + } 1.124 +#endif 1.125 + png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; 1.126 + } 1.127 +} 1.128 + 1.129 +void PNGAPI 1.130 +png_write_info(png_structp png_ptr, png_infop info_ptr) 1.131 +{ 1.132 +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 1.133 + int i; 1.134 +#endif 1.135 + 1.136 + png_debug(1, "in png_write_info\n"); 1.137 + 1.138 + if (png_ptr == NULL || info_ptr == NULL) 1.139 + return; 1.140 + 1.141 + png_write_info_before_PLTE(png_ptr, info_ptr); 1.142 + 1.143 + if (info_ptr->valid & PNG_INFO_PLTE) 1.144 + png_write_PLTE(png_ptr, info_ptr->palette, 1.145 + (png_uint_32)info_ptr->num_palette); 1.146 + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.147 + png_error(png_ptr, "Valid palette required for paletted images"); 1.148 + 1.149 +#if defined(PNG_WRITE_tRNS_SUPPORTED) 1.150 + if (info_ptr->valid & PNG_INFO_tRNS) 1.151 + { 1.152 +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) 1.153 + /* invert the alpha channel (in tRNS) */ 1.154 + if ((png_ptr->transformations & PNG_INVERT_ALPHA) && 1.155 + info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.156 + { 1.157 + int j; 1.158 + for (j=0; j<(int)info_ptr->num_trans; j++) 1.159 + info_ptr->trans[j] = (png_byte)(255 - info_ptr->trans[j]); 1.160 + } 1.161 +#endif 1.162 + png_write_tRNS(png_ptr, info_ptr->trans, &(info_ptr->trans_values), 1.163 + info_ptr->num_trans, info_ptr->color_type); 1.164 + } 1.165 +#endif 1.166 +#if defined(PNG_WRITE_bKGD_SUPPORTED) 1.167 + if (info_ptr->valid & PNG_INFO_bKGD) 1.168 + png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); 1.169 +#endif 1.170 +#if defined(PNG_WRITE_hIST_SUPPORTED) 1.171 + if (info_ptr->valid & PNG_INFO_hIST) 1.172 + png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); 1.173 +#endif 1.174 +#if defined(PNG_WRITE_oFFs_SUPPORTED) 1.175 + if (info_ptr->valid & PNG_INFO_oFFs) 1.176 + png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, 1.177 + info_ptr->offset_unit_type); 1.178 +#endif 1.179 +#if defined(PNG_WRITE_pCAL_SUPPORTED) 1.180 + if (info_ptr->valid & PNG_INFO_pCAL) 1.181 + png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, 1.182 + info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, 1.183 + info_ptr->pcal_units, info_ptr->pcal_params); 1.184 +#endif 1.185 +#if defined(PNG_WRITE_sCAL_SUPPORTED) 1.186 + if (info_ptr->valid & PNG_INFO_sCAL) 1.187 +#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO) 1.188 + png_write_sCAL(png_ptr, (int)info_ptr->scal_unit, 1.189 + info_ptr->scal_pixel_width, info_ptr->scal_pixel_height); 1.190 +#else 1.191 +#ifdef PNG_FIXED_POINT_SUPPORTED 1.192 + png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, 1.193 + info_ptr->scal_s_width, info_ptr->scal_s_height); 1.194 +#else 1.195 + png_warning(png_ptr, 1.196 + "png_write_sCAL not supported; sCAL chunk not written."); 1.197 +#endif 1.198 +#endif 1.199 +#endif 1.200 +#if defined(PNG_WRITE_pHYs_SUPPORTED) 1.201 + if (info_ptr->valid & PNG_INFO_pHYs) 1.202 + png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, 1.203 + info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); 1.204 +#endif 1.205 +#if defined(PNG_WRITE_tIME_SUPPORTED) 1.206 + if (info_ptr->valid & PNG_INFO_tIME) 1.207 + { 1.208 + png_write_tIME(png_ptr, &(info_ptr->mod_time)); 1.209 + png_ptr->mode |= PNG_WROTE_tIME; 1.210 + } 1.211 +#endif 1.212 +#if defined(PNG_WRITE_sPLT_SUPPORTED) 1.213 + if (info_ptr->valid & PNG_INFO_sPLT) 1.214 + for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) 1.215 + png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); 1.216 +#endif 1.217 +#if defined(PNG_WRITE_TEXT_SUPPORTED) 1.218 + /* Check to see if we need to write text chunks */ 1.219 + for (i = 0; i < info_ptr->num_text; i++) 1.220 + { 1.221 + png_debug2(2, "Writing header text chunk %d, type %d\n", i, 1.222 + info_ptr->text[i].compression); 1.223 + /* an internationalized chunk? */ 1.224 + if (info_ptr->text[i].compression > 0) 1.225 + { 1.226 +#if defined(PNG_WRITE_iTXt_SUPPORTED) 1.227 + /* write international chunk */ 1.228 + png_write_iTXt(png_ptr, 1.229 + info_ptr->text[i].compression, 1.230 + info_ptr->text[i].key, 1.231 + info_ptr->text[i].lang, 1.232 + info_ptr->text[i].lang_key, 1.233 + info_ptr->text[i].text); 1.234 +#else 1.235 + png_warning(png_ptr, "Unable to write international text"); 1.236 +#endif 1.237 + /* Mark this chunk as written */ 1.238 + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 1.239 + } 1.240 + /* If we want a compressed text chunk */ 1.241 + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) 1.242 + { 1.243 +#if defined(PNG_WRITE_zTXt_SUPPORTED) 1.244 + /* write compressed chunk */ 1.245 + png_write_zTXt(png_ptr, info_ptr->text[i].key, 1.246 + info_ptr->text[i].text, 0, 1.247 + info_ptr->text[i].compression); 1.248 +#else 1.249 + png_warning(png_ptr, "Unable to write compressed text"); 1.250 +#endif 1.251 + /* Mark this chunk as written */ 1.252 + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 1.253 + } 1.254 + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 1.255 + { 1.256 +#if defined(PNG_WRITE_tEXt_SUPPORTED) 1.257 + /* write uncompressed chunk */ 1.258 + png_write_tEXt(png_ptr, info_ptr->text[i].key, 1.259 + info_ptr->text[i].text, 1.260 + 0); 1.261 +#else 1.262 + png_warning(png_ptr, "Unable to write uncompressed text"); 1.263 +#endif 1.264 + /* Mark this chunk as written */ 1.265 + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 1.266 + } 1.267 + } 1.268 +#endif 1.269 +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) 1.270 + if (info_ptr->unknown_chunks_num) 1.271 + { 1.272 + png_unknown_chunk *up; 1.273 + 1.274 + png_debug(5, "writing extra chunks\n"); 1.275 + 1.276 + for (up = info_ptr->unknown_chunks; 1.277 + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; 1.278 + up++) 1.279 + { 1.280 + int keep=png_handle_as_unknown(png_ptr, up->name); 1.281 + if (keep != PNG_HANDLE_CHUNK_NEVER && 1.282 + up->location && (up->location & PNG_HAVE_PLTE) && 1.283 + !(up->location & PNG_HAVE_IDAT) && 1.284 + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || 1.285 + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) 1.286 + { 1.287 + png_write_chunk(png_ptr, up->name, up->data, up->size); 1.288 + } 1.289 + } 1.290 + } 1.291 +#endif 1.292 +} 1.293 + 1.294 +/* Writes the end of the PNG file. If you don't want to write comments or 1.295 + * time information, you can pass NULL for info. If you already wrote these 1.296 + * in png_write_info(), do not write them again here. If you have long 1.297 + * comments, I suggest writing them here, and compressing them. 1.298 + */ 1.299 +void PNGAPI 1.300 +png_write_end(png_structp png_ptr, png_infop info_ptr) 1.301 +{ 1.302 + png_debug(1, "in png_write_end\n"); 1.303 + if (png_ptr == NULL) 1.304 + return; 1.305 + if (!(png_ptr->mode & PNG_HAVE_IDAT)) 1.306 + png_error(png_ptr, "No IDATs written into file"); 1.307 + 1.308 + /* see if user wants us to write information chunks */ 1.309 + if (info_ptr != NULL) 1.310 + { 1.311 +#if defined(PNG_WRITE_TEXT_SUPPORTED) 1.312 + int i; /* local index variable */ 1.313 +#endif 1.314 +#if defined(PNG_WRITE_tIME_SUPPORTED) 1.315 + /* check to see if user has supplied a time chunk */ 1.316 + if ((info_ptr->valid & PNG_INFO_tIME) && 1.317 + !(png_ptr->mode & PNG_WROTE_tIME)) 1.318 + png_write_tIME(png_ptr, &(info_ptr->mod_time)); 1.319 +#endif 1.320 +#if defined(PNG_WRITE_TEXT_SUPPORTED) 1.321 + /* loop through comment chunks */ 1.322 + for (i = 0; i < info_ptr->num_text; i++) 1.323 + { 1.324 + png_debug2(2, "Writing trailer text chunk %d, type %d\n", i, 1.325 + info_ptr->text[i].compression); 1.326 + /* an internationalized chunk? */ 1.327 + if (info_ptr->text[i].compression > 0) 1.328 + { 1.329 +#if defined(PNG_WRITE_iTXt_SUPPORTED) 1.330 + /* write international chunk */ 1.331 + png_write_iTXt(png_ptr, 1.332 + info_ptr->text[i].compression, 1.333 + info_ptr->text[i].key, 1.334 + info_ptr->text[i].lang, 1.335 + info_ptr->text[i].lang_key, 1.336 + info_ptr->text[i].text); 1.337 +#else 1.338 + png_warning(png_ptr, "Unable to write international text"); 1.339 +#endif 1.340 + /* Mark this chunk as written */ 1.341 + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 1.342 + } 1.343 + else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) 1.344 + { 1.345 +#if defined(PNG_WRITE_zTXt_SUPPORTED) 1.346 + /* write compressed chunk */ 1.347 + png_write_zTXt(png_ptr, info_ptr->text[i].key, 1.348 + info_ptr->text[i].text, 0, 1.349 + info_ptr->text[i].compression); 1.350 +#else 1.351 + png_warning(png_ptr, "Unable to write compressed text"); 1.352 +#endif 1.353 + /* Mark this chunk as written */ 1.354 + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 1.355 + } 1.356 + else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 1.357 + { 1.358 +#if defined(PNG_WRITE_tEXt_SUPPORTED) 1.359 + /* write uncompressed chunk */ 1.360 + png_write_tEXt(png_ptr, info_ptr->text[i].key, 1.361 + info_ptr->text[i].text, 0); 1.362 +#else 1.363 + png_warning(png_ptr, "Unable to write uncompressed text"); 1.364 +#endif 1.365 + 1.366 + /* Mark this chunk as written */ 1.367 + info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 1.368 + } 1.369 + } 1.370 +#endif 1.371 +#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) 1.372 + if (info_ptr->unknown_chunks_num) 1.373 + { 1.374 + png_unknown_chunk *up; 1.375 + 1.376 + png_debug(5, "writing extra chunks\n"); 1.377 + 1.378 + for (up = info_ptr->unknown_chunks; 1.379 + up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; 1.380 + up++) 1.381 + { 1.382 + int keep=png_handle_as_unknown(png_ptr, up->name); 1.383 + if (keep != PNG_HANDLE_CHUNK_NEVER && 1.384 + up->location && (up->location & PNG_AFTER_IDAT) && 1.385 + ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS || 1.386 + (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS))) 1.387 + { 1.388 + png_write_chunk(png_ptr, up->name, up->data, up->size); 1.389 + } 1.390 + } 1.391 + } 1.392 +#endif 1.393 + } 1.394 + 1.395 + png_ptr->mode |= PNG_AFTER_IDAT; 1.396 + 1.397 + /* write end of PNG file */ 1.398 + png_write_IEND(png_ptr); 1.399 + /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, 1.400 + * and restored again in libpng-1.2.30, may cause some applications that 1.401 + * do not set png_ptr->output_flush_fn to crash. If your application 1.402 + * experiences a problem, please try building libpng with 1.403 + * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to 1.404 + * png-mng-implement at lists.sf.net . This kludge will be removed 1.405 + * from libpng-1.4.0. 1.406 + */ 1.407 +#if defined(PNG_WRITE_FLUSH_SUPPORTED) && \ 1.408 + defined(PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED) 1.409 + png_flush(png_ptr); 1.410 +#endif 1.411 +} 1.412 + 1.413 +#if defined(PNG_WRITE_tIME_SUPPORTED) 1.414 +#if !defined(_WIN32_WCE) 1.415 +/* "time.h" functions are not supported on WindowsCE */ 1.416 +void PNGAPI 1.417 +png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) 1.418 +{ 1.419 + png_debug(1, "in png_convert_from_struct_tm\n"); 1.420 + ptime->year = (png_uint_16)(1900 + ttime->tm_year); 1.421 + ptime->month = (png_byte)(ttime->tm_mon + 1); 1.422 + ptime->day = (png_byte)ttime->tm_mday; 1.423 + ptime->hour = (png_byte)ttime->tm_hour; 1.424 + ptime->minute = (png_byte)ttime->tm_min; 1.425 + ptime->second = (png_byte)ttime->tm_sec; 1.426 +} 1.427 + 1.428 +void PNGAPI 1.429 +png_convert_from_time_t(png_timep ptime, time_t ttime) 1.430 +{ 1.431 + struct tm *tbuf; 1.432 + 1.433 + png_debug(1, "in png_convert_from_time_t\n"); 1.434 + tbuf = gmtime(&ttime); 1.435 + png_convert_from_struct_tm(ptime, tbuf); 1.436 +} 1.437 +#endif 1.438 +#endif 1.439 + 1.440 +/* Initialize png_ptr structure, and allocate any memory needed */ 1.441 +png_structp PNGAPI 1.442 +png_create_write_struct(png_const_charp user_png_ver, png_voidp error_ptr, 1.443 + png_error_ptr error_fn, png_error_ptr warn_fn) 1.444 +{ 1.445 +#ifdef PNG_USER_MEM_SUPPORTED 1.446 + return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn, 1.447 + warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); 1.448 +} 1.449 + 1.450 +/* Alternate initialize png_ptr structure, and allocate any memory needed */ 1.451 +png_structp PNGAPI 1.452 +png_create_write_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, 1.453 + png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 1.454 + png_malloc_ptr malloc_fn, png_free_ptr free_fn) 1.455 +{ 1.456 +#endif /* PNG_USER_MEM_SUPPORTED */ 1.457 +#ifdef PNG_SETJMP_SUPPORTED 1.458 + volatile 1.459 +#endif 1.460 + png_structp png_ptr; 1.461 +#ifdef PNG_SETJMP_SUPPORTED 1.462 +#ifdef USE_FAR_KEYWORD 1.463 + jmp_buf jmpbuf; 1.464 +#endif 1.465 +#endif 1.466 + int i; 1.467 + png_debug(1, "in png_create_write_struct\n"); 1.468 +#ifdef PNG_USER_MEM_SUPPORTED 1.469 + png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, 1.470 + (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); 1.471 +#else 1.472 + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); 1.473 +#endif /* PNG_USER_MEM_SUPPORTED */ 1.474 + if (png_ptr == NULL) 1.475 + return (NULL); 1.476 + 1.477 + /* added at libpng-1.2.6 */ 1.478 +#ifdef PNG_SET_USER_LIMITS_SUPPORTED 1.479 + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; 1.480 + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; 1.481 +#endif 1.482 + 1.483 +#ifdef PNG_SETJMP_SUPPORTED 1.484 +#ifdef USE_FAR_KEYWORD 1.485 + if (setjmp(jmpbuf)) 1.486 +#else 1.487 + if (setjmp(png_ptr->jmpbuf)) 1.488 +#endif 1.489 + { 1.490 + png_free(png_ptr, png_ptr->zbuf); 1.491 + png_ptr->zbuf=NULL; 1.492 + png_destroy_struct(png_ptr); 1.493 + return (NULL); 1.494 + } 1.495 +#ifdef USE_FAR_KEYWORD 1.496 + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); 1.497 +#endif 1.498 +#endif 1.499 + 1.500 +#ifdef PNG_USER_MEM_SUPPORTED 1.501 + png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); 1.502 +#endif /* PNG_USER_MEM_SUPPORTED */ 1.503 + png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); 1.504 + 1.505 + if (user_png_ver) 1.506 + { 1.507 + i=0; 1.508 + do 1.509 + { 1.510 + if (user_png_ver[i] != png_libpng_ver[i]) 1.511 + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 1.512 + } while (png_libpng_ver[i++]); 1.513 + } 1.514 + 1.515 + if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) 1.516 + { 1.517 + /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so 1.518 + * we must recompile any applications that use any older library version. 1.519 + * For versions after libpng 1.0, we will be compatible, so we need 1.520 + * only check the first digit. 1.521 + */ 1.522 + if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || 1.523 + (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || 1.524 + (user_png_ver[0] == '0' && user_png_ver[2] < '9')) 1.525 + { 1.526 +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) 1.527 + char msg[80]; 1.528 + if (user_png_ver) 1.529 + { 1.530 + png_snprintf(msg, 80, 1.531 + "Application was compiled with png.h from libpng-%.20s", 1.532 + user_png_ver); 1.533 + png_warning(png_ptr, msg); 1.534 + } 1.535 + png_snprintf(msg, 80, 1.536 + "Application is running with png.c from libpng-%.20s", 1.537 + png_libpng_ver); 1.538 + png_warning(png_ptr, msg); 1.539 +#endif 1.540 +#ifdef PNG_ERROR_NUMBERS_SUPPORTED 1.541 + png_ptr->flags=0; 1.542 +#endif 1.543 + png_error(png_ptr, 1.544 + "Incompatible libpng version in application and library"); 1.545 + } 1.546 + } 1.547 + 1.548 + /* initialize zbuf - compression buffer */ 1.549 + png_ptr->zbuf_size = PNG_ZBUF_SIZE; 1.550 + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, 1.551 + (png_uint_32)png_ptr->zbuf_size); 1.552 + 1.553 + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, 1.554 + png_flush_ptr_NULL); 1.555 + 1.556 +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) 1.557 + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, 1.558 + 1, png_doublep_NULL, png_doublep_NULL); 1.559 +#endif 1.560 + 1.561 +#ifdef PNG_SETJMP_SUPPORTED 1.562 +/* Applications that neglect to set up their own setjmp() and then encounter 1.563 + a png_error() will longjmp here. Since the jmpbuf is then meaningless we 1.564 + abort instead of returning. */ 1.565 +#ifdef USE_FAR_KEYWORD 1.566 + if (setjmp(jmpbuf)) 1.567 + PNG_ABORT(); 1.568 + png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); 1.569 +#else 1.570 + if (setjmp(png_ptr->jmpbuf)) 1.571 + PNG_ABORT(); 1.572 +#endif 1.573 +#endif 1.574 + return (png_ptr); 1.575 +} 1.576 + 1.577 +/* Initialize png_ptr structure, and allocate any memory needed */ 1.578 +#if defined(PNG_1_0_X) || defined(PNG_1_2_X) 1.579 +/* Deprecated. */ 1.580 +#undef png_write_init 1.581 +void PNGAPI 1.582 +png_write_init(png_structp png_ptr) 1.583 +{ 1.584 + /* We only come here via pre-1.0.7-compiled applications */ 1.585 + png_write_init_2(png_ptr, "1.0.6 or earlier", 0, 0); 1.586 +} 1.587 + 1.588 +void PNGAPI 1.589 +png_write_init_2(png_structp png_ptr, png_const_charp user_png_ver, 1.590 + png_size_t png_struct_size, png_size_t png_info_size) 1.591 +{ 1.592 + /* We only come here via pre-1.0.12-compiled applications */ 1.593 + if (png_ptr == NULL) return; 1.594 +#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE) 1.595 + if (png_sizeof(png_struct) > png_struct_size || 1.596 + png_sizeof(png_info) > png_info_size) 1.597 + { 1.598 + char msg[80]; 1.599 + png_ptr->warning_fn=NULL; 1.600 + if (user_png_ver) 1.601 + { 1.602 + png_snprintf(msg, 80, 1.603 + "Application was compiled with png.h from libpng-%.20s", 1.604 + user_png_ver); 1.605 + png_warning(png_ptr, msg); 1.606 + } 1.607 + png_snprintf(msg, 80, 1.608 + "Application is running with png.c from libpng-%.20s", 1.609 + png_libpng_ver); 1.610 + png_warning(png_ptr, msg); 1.611 + } 1.612 +#endif 1.613 + if (png_sizeof(png_struct) > png_struct_size) 1.614 + { 1.615 + png_ptr->error_fn=NULL; 1.616 +#ifdef PNG_ERROR_NUMBERS_SUPPORTED 1.617 + png_ptr->flags=0; 1.618 +#endif 1.619 + png_error(png_ptr, 1.620 + "The png struct allocated by the application for writing is too small."); 1.621 + } 1.622 + if (png_sizeof(png_info) > png_info_size) 1.623 + { 1.624 + png_ptr->error_fn=NULL; 1.625 +#ifdef PNG_ERROR_NUMBERS_SUPPORTED 1.626 + png_ptr->flags=0; 1.627 +#endif 1.628 + png_error(png_ptr, 1.629 + "The info struct allocated by the application for writing is too small."); 1.630 + } 1.631 + png_write_init_3(&png_ptr, user_png_ver, png_struct_size); 1.632 +} 1.633 +#endif /* PNG_1_0_X || PNG_1_2_X */ 1.634 + 1.635 + 1.636 +void PNGAPI 1.637 +png_write_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, 1.638 + png_size_t png_struct_size) 1.639 +{ 1.640 + png_structp png_ptr=*ptr_ptr; 1.641 +#ifdef PNG_SETJMP_SUPPORTED 1.642 + jmp_buf tmp_jmp; /* to save current jump buffer */ 1.643 +#endif 1.644 + 1.645 + int i = 0; 1.646 + 1.647 + if (png_ptr == NULL) 1.648 + return; 1.649 + 1.650 + do 1.651 + { 1.652 + if (user_png_ver[i] != png_libpng_ver[i]) 1.653 + { 1.654 +#ifdef PNG_LEGACY_SUPPORTED 1.655 + png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 1.656 +#else 1.657 + png_ptr->warning_fn=NULL; 1.658 + png_warning(png_ptr, 1.659 + "Application uses deprecated png_write_init() and should be recompiled."); 1.660 + break; 1.661 +#endif 1.662 + } 1.663 + } while (png_libpng_ver[i++]); 1.664 + 1.665 + png_debug(1, "in png_write_init_3\n"); 1.666 + 1.667 +#ifdef PNG_SETJMP_SUPPORTED 1.668 + /* save jump buffer and error functions */ 1.669 + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); 1.670 +#endif 1.671 + 1.672 + if (png_sizeof(png_struct) > png_struct_size) 1.673 + { 1.674 + png_destroy_struct(png_ptr); 1.675 + png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); 1.676 + *ptr_ptr = png_ptr; 1.677 + } 1.678 + 1.679 + /* reset all variables to 0 */ 1.680 + png_memset(png_ptr, 0, png_sizeof(png_struct)); 1.681 + 1.682 + /* added at libpng-1.2.6 */ 1.683 +#ifdef PNG_SET_USER_LIMITS_SUPPORTED 1.684 + png_ptr->user_width_max=PNG_USER_WIDTH_MAX; 1.685 + png_ptr->user_height_max=PNG_USER_HEIGHT_MAX; 1.686 +#endif 1.687 + 1.688 +#ifdef PNG_SETJMP_SUPPORTED 1.689 + /* restore jump buffer */ 1.690 + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); 1.691 +#endif 1.692 + 1.693 + png_set_write_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL, 1.694 + png_flush_ptr_NULL); 1.695 + 1.696 + /* initialize zbuf - compression buffer */ 1.697 + png_ptr->zbuf_size = PNG_ZBUF_SIZE; 1.698 + png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, 1.699 + (png_uint_32)png_ptr->zbuf_size); 1.700 + 1.701 +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) 1.702 + png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT, 1.703 + 1, png_doublep_NULL, png_doublep_NULL); 1.704 +#endif 1.705 +} 1.706 + 1.707 +/* Write a few rows of image data. If the image is interlaced, 1.708 + * either you will have to write the 7 sub images, or, if you 1.709 + * have called png_set_interlace_handling(), you will have to 1.710 + * "write" the image seven times. 1.711 + */ 1.712 +void PNGAPI 1.713 +png_write_rows(png_structp png_ptr, png_bytepp row, 1.714 + png_uint_32 num_rows) 1.715 +{ 1.716 + png_uint_32 i; /* row counter */ 1.717 + png_bytepp rp; /* row pointer */ 1.718 + 1.719 + png_debug(1, "in png_write_rows\n"); 1.720 + 1.721 + if (png_ptr == NULL) 1.722 + return; 1.723 + 1.724 + /* loop through the rows */ 1.725 + for (i = 0, rp = row; i < num_rows; i++, rp++) 1.726 + { 1.727 + png_write_row(png_ptr, *rp); 1.728 + } 1.729 +} 1.730 + 1.731 +/* Write the image. You only need to call this function once, even 1.732 + * if you are writing an interlaced image. 1.733 + */ 1.734 +void PNGAPI 1.735 +png_write_image(png_structp png_ptr, png_bytepp image) 1.736 +{ 1.737 + png_uint_32 i; /* row index */ 1.738 + int pass, num_pass; /* pass variables */ 1.739 + png_bytepp rp; /* points to current row */ 1.740 + 1.741 + if (png_ptr == NULL) 1.742 + return; 1.743 + 1.744 + png_debug(1, "in png_write_image\n"); 1.745 +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) 1.746 + /* intialize interlace handling. If image is not interlaced, 1.747 + this will set pass to 1 */ 1.748 + num_pass = png_set_interlace_handling(png_ptr); 1.749 +#else 1.750 + num_pass = 1; 1.751 +#endif 1.752 + /* loop through passes */ 1.753 + for (pass = 0; pass < num_pass; pass++) 1.754 + { 1.755 + /* loop through image */ 1.756 + for (i = 0, rp = image; i < png_ptr->height; i++, rp++) 1.757 + { 1.758 + png_write_row(png_ptr, *rp); 1.759 + } 1.760 + } 1.761 +} 1.762 + 1.763 +/* called by user to write a row of image data */ 1.764 +void PNGAPI 1.765 +png_write_row(png_structp png_ptr, png_bytep row) 1.766 +{ 1.767 + if (png_ptr == NULL) 1.768 + return; 1.769 + png_debug2(1, "in png_write_row (row %ld, pass %d)\n", 1.770 + png_ptr->row_number, png_ptr->pass); 1.771 + 1.772 + /* initialize transformations and other stuff if first time */ 1.773 + if (png_ptr->row_number == 0 && png_ptr->pass == 0) 1.774 + { 1.775 + /* make sure we wrote the header info */ 1.776 + if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE)) 1.777 + png_error(png_ptr, 1.778 + "png_write_info was never called before png_write_row."); 1.779 + 1.780 + /* check for transforms that have been set but were defined out */ 1.781 +#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) 1.782 + if (png_ptr->transformations & PNG_INVERT_MONO) 1.783 + png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined."); 1.784 +#endif 1.785 +#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) 1.786 + if (png_ptr->transformations & PNG_FILLER) 1.787 + png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined."); 1.788 +#endif 1.789 +#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED) 1.790 + if (png_ptr->transformations & PNG_PACKSWAP) 1.791 + png_warning(png_ptr, "PNG_WRITE_PACKSWAP_SUPPORTED is not defined."); 1.792 +#endif 1.793 +#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) 1.794 + if (png_ptr->transformations & PNG_PACK) 1.795 + png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined."); 1.796 +#endif 1.797 +#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) 1.798 + if (png_ptr->transformations & PNG_SHIFT) 1.799 + png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined."); 1.800 +#endif 1.801 +#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) 1.802 + if (png_ptr->transformations & PNG_BGR) 1.803 + png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined."); 1.804 +#endif 1.805 +#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) 1.806 + if (png_ptr->transformations & PNG_SWAP_BYTES) 1.807 + png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined."); 1.808 +#endif 1.809 + 1.810 + png_write_start_row(png_ptr); 1.811 + } 1.812 + 1.813 +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) 1.814 + /* if interlaced and not interested in row, return */ 1.815 + if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) 1.816 + { 1.817 + switch (png_ptr->pass) 1.818 + { 1.819 + case 0: 1.820 + if (png_ptr->row_number & 0x07) 1.821 + { 1.822 + png_write_finish_row(png_ptr); 1.823 + return; 1.824 + } 1.825 + break; 1.826 + case 1: 1.827 + if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) 1.828 + { 1.829 + png_write_finish_row(png_ptr); 1.830 + return; 1.831 + } 1.832 + break; 1.833 + case 2: 1.834 + if ((png_ptr->row_number & 0x07) != 4) 1.835 + { 1.836 + png_write_finish_row(png_ptr); 1.837 + return; 1.838 + } 1.839 + break; 1.840 + case 3: 1.841 + if ((png_ptr->row_number & 0x03) || png_ptr->width < 3) 1.842 + { 1.843 + png_write_finish_row(png_ptr); 1.844 + return; 1.845 + } 1.846 + break; 1.847 + case 4: 1.848 + if ((png_ptr->row_number & 0x03) != 2) 1.849 + { 1.850 + png_write_finish_row(png_ptr); 1.851 + return; 1.852 + } 1.853 + break; 1.854 + case 5: 1.855 + if ((png_ptr->row_number & 0x01) || png_ptr->width < 2) 1.856 + { 1.857 + png_write_finish_row(png_ptr); 1.858 + return; 1.859 + } 1.860 + break; 1.861 + case 6: 1.862 + if (!(png_ptr->row_number & 0x01)) 1.863 + { 1.864 + png_write_finish_row(png_ptr); 1.865 + return; 1.866 + } 1.867 + break; 1.868 + } 1.869 + } 1.870 +#endif 1.871 + 1.872 + /* set up row info for transformations */ 1.873 + png_ptr->row_info.color_type = png_ptr->color_type; 1.874 + png_ptr->row_info.width = png_ptr->usr_width; 1.875 + png_ptr->row_info.channels = png_ptr->usr_channels; 1.876 + png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; 1.877 + png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth * 1.878 + png_ptr->row_info.channels); 1.879 + 1.880 + png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, 1.881 + png_ptr->row_info.width); 1.882 + 1.883 + png_debug1(3, "row_info->color_type = %d\n", png_ptr->row_info.color_type); 1.884 + png_debug1(3, "row_info->width = %lu\n", png_ptr->row_info.width); 1.885 + png_debug1(3, "row_info->channels = %d\n", png_ptr->row_info.channels); 1.886 + png_debug1(3, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth); 1.887 + png_debug1(3, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth); 1.888 + png_debug1(3, "row_info->rowbytes = %lu\n", png_ptr->row_info.rowbytes); 1.889 + 1.890 + /* Copy user's row into buffer, leaving room for filter byte. */ 1.891 + png_memcpy_check(png_ptr, png_ptr->row_buf + 1, row, 1.892 + png_ptr->row_info.rowbytes); 1.893 + 1.894 +#if defined(PNG_WRITE_INTERLACING_SUPPORTED) 1.895 + /* handle interlacing */ 1.896 + if (png_ptr->interlaced && png_ptr->pass < 6 && 1.897 + (png_ptr->transformations & PNG_INTERLACE)) 1.898 + { 1.899 + png_do_write_interlace(&(png_ptr->row_info), 1.900 + png_ptr->row_buf + 1, png_ptr->pass); 1.901 + /* this should always get caught above, but still ... */ 1.902 + if (!(png_ptr->row_info.width)) 1.903 + { 1.904 + png_write_finish_row(png_ptr); 1.905 + return; 1.906 + } 1.907 + } 1.908 +#endif 1.909 + 1.910 + /* handle other transformations */ 1.911 + if (png_ptr->transformations) 1.912 + png_do_write_transformations(png_ptr); 1.913 + 1.914 +#if defined(PNG_MNG_FEATURES_SUPPORTED) 1.915 + /* Write filter_method 64 (intrapixel differencing) only if 1.916 + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 1.917 + * 2. Libpng did not write a PNG signature (this filter_method is only 1.918 + * used in PNG datastreams that are embedded in MNG datastreams) and 1.919 + * 3. The application called png_permit_mng_features with a mask that 1.920 + * included PNG_FLAG_MNG_FILTER_64 and 1.921 + * 4. The filter_method is 64 and 1.922 + * 5. The color_type is RGB or RGBA 1.923 + */ 1.924 + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 1.925 + (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 1.926 + { 1.927 + /* Intrapixel differencing */ 1.928 + png_do_write_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); 1.929 + } 1.930 +#endif 1.931 + 1.932 + /* Find a filter if necessary, filter the row and write it out. */ 1.933 + png_write_find_filter(png_ptr, &(png_ptr->row_info)); 1.934 + 1.935 + if (png_ptr->write_row_fn != NULL) 1.936 + (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 1.937 +} 1.938 + 1.939 +#if defined(PNG_WRITE_FLUSH_SUPPORTED) 1.940 +/* Set the automatic flush interval or 0 to turn flushing off */ 1.941 +void PNGAPI 1.942 +png_set_flush(png_structp png_ptr, int nrows) 1.943 +{ 1.944 + png_debug(1, "in png_set_flush\n"); 1.945 + if (png_ptr == NULL) 1.946 + return; 1.947 + png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); 1.948 +} 1.949 + 1.950 +/* flush the current output buffers now */ 1.951 +void PNGAPI 1.952 +png_write_flush(png_structp png_ptr) 1.953 +{ 1.954 + int wrote_IDAT; 1.955 + 1.956 + png_debug(1, "in png_write_flush\n"); 1.957 + if (png_ptr == NULL) 1.958 + return; 1.959 + /* We have already written out all of the data */ 1.960 + if (png_ptr->row_number >= png_ptr->num_rows) 1.961 + return; 1.962 + 1.963 + do 1.964 + { 1.965 + int ret; 1.966 + 1.967 + /* compress the data */ 1.968 + ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH); 1.969 + wrote_IDAT = 0; 1.970 + 1.971 + /* check for compression errors */ 1.972 + if (ret != Z_OK) 1.973 + { 1.974 + if (png_ptr->zstream.msg != NULL) 1.975 + png_error(png_ptr, png_ptr->zstream.msg); 1.976 + else 1.977 + png_error(png_ptr, "zlib error"); 1.978 + } 1.979 + 1.980 + if (!(png_ptr->zstream.avail_out)) 1.981 + { 1.982 + /* write the IDAT and reset the zlib output buffer */ 1.983 + png_write_IDAT(png_ptr, png_ptr->zbuf, 1.984 + png_ptr->zbuf_size); 1.985 + png_ptr->zstream.next_out = png_ptr->zbuf; 1.986 + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 1.987 + wrote_IDAT = 1; 1.988 + } 1.989 + } while(wrote_IDAT == 1); 1.990 + 1.991 + /* If there is any data left to be output, write it into a new IDAT */ 1.992 + if (png_ptr->zbuf_size != png_ptr->zstream.avail_out) 1.993 + { 1.994 + /* write the IDAT and reset the zlib output buffer */ 1.995 + png_write_IDAT(png_ptr, png_ptr->zbuf, 1.996 + png_ptr->zbuf_size - png_ptr->zstream.avail_out); 1.997 + png_ptr->zstream.next_out = png_ptr->zbuf; 1.998 + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 1.999 + } 1.1000 + png_ptr->flush_rows = 0; 1.1001 + png_flush(png_ptr); 1.1002 +} 1.1003 +#endif /* PNG_WRITE_FLUSH_SUPPORTED */ 1.1004 + 1.1005 +/* free all memory used by the write */ 1.1006 +void PNGAPI 1.1007 +png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) 1.1008 +{ 1.1009 + png_structp png_ptr = NULL; 1.1010 + png_infop info_ptr = NULL; 1.1011 +#ifdef PNG_USER_MEM_SUPPORTED 1.1012 + png_free_ptr free_fn = NULL; 1.1013 + png_voidp mem_ptr = NULL; 1.1014 +#endif 1.1015 + 1.1016 + png_debug(1, "in png_destroy_write_struct\n"); 1.1017 + if (png_ptr_ptr != NULL) 1.1018 + { 1.1019 + png_ptr = *png_ptr_ptr; 1.1020 +#ifdef PNG_USER_MEM_SUPPORTED 1.1021 + free_fn = png_ptr->free_fn; 1.1022 + mem_ptr = png_ptr->mem_ptr; 1.1023 +#endif 1.1024 + } 1.1025 + 1.1026 +#ifdef PNG_USER_MEM_SUPPORTED 1.1027 + if (png_ptr != NULL) 1.1028 + { 1.1029 + free_fn = png_ptr->free_fn; 1.1030 + mem_ptr = png_ptr->mem_ptr; 1.1031 + } 1.1032 +#endif 1.1033 + 1.1034 + if (info_ptr_ptr != NULL) 1.1035 + info_ptr = *info_ptr_ptr; 1.1036 + 1.1037 + if (info_ptr != NULL) 1.1038 + { 1.1039 + if (png_ptr != NULL) 1.1040 + { 1.1041 + png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); 1.1042 + 1.1043 +#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) 1.1044 + if (png_ptr->num_chunk_list) 1.1045 + { 1.1046 + png_free(png_ptr, png_ptr->chunk_list); 1.1047 + png_ptr->chunk_list=NULL; 1.1048 + png_ptr->num_chunk_list = 0; 1.1049 + } 1.1050 +#endif 1.1051 + } 1.1052 + 1.1053 +#ifdef PNG_USER_MEM_SUPPORTED 1.1054 + png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, 1.1055 + (png_voidp)mem_ptr); 1.1056 +#else 1.1057 + png_destroy_struct((png_voidp)info_ptr); 1.1058 +#endif 1.1059 + *info_ptr_ptr = NULL; 1.1060 + } 1.1061 + 1.1062 + if (png_ptr != NULL) 1.1063 + { 1.1064 + png_write_destroy(png_ptr); 1.1065 +#ifdef PNG_USER_MEM_SUPPORTED 1.1066 + png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, 1.1067 + (png_voidp)mem_ptr); 1.1068 +#else 1.1069 + png_destroy_struct((png_voidp)png_ptr); 1.1070 +#endif 1.1071 + *png_ptr_ptr = NULL; 1.1072 + } 1.1073 +} 1.1074 + 1.1075 + 1.1076 +/* Free any memory used in png_ptr struct (old method) */ 1.1077 +void /* PRIVATE */ 1.1078 +png_write_destroy(png_structp png_ptr) 1.1079 +{ 1.1080 +#ifdef PNG_SETJMP_SUPPORTED 1.1081 + jmp_buf tmp_jmp; /* save jump buffer */ 1.1082 +#endif 1.1083 + png_error_ptr error_fn; 1.1084 + png_error_ptr warning_fn; 1.1085 + png_voidp error_ptr; 1.1086 +#ifdef PNG_USER_MEM_SUPPORTED 1.1087 + png_free_ptr free_fn; 1.1088 +#endif 1.1089 + 1.1090 + png_debug(1, "in png_write_destroy\n"); 1.1091 + /* free any memory zlib uses */ 1.1092 + deflateEnd(&png_ptr->zstream); 1.1093 + 1.1094 + /* free our memory. png_free checks NULL for us. */ 1.1095 + png_free(png_ptr, png_ptr->zbuf); 1.1096 + png_free(png_ptr, png_ptr->row_buf); 1.1097 +#ifndef PNG_NO_WRITE_FILTER 1.1098 + png_free(png_ptr, png_ptr->prev_row); 1.1099 + png_free(png_ptr, png_ptr->sub_row); 1.1100 + png_free(png_ptr, png_ptr->up_row); 1.1101 + png_free(png_ptr, png_ptr->avg_row); 1.1102 + png_free(png_ptr, png_ptr->paeth_row); 1.1103 +#endif 1.1104 + 1.1105 +#if defined(PNG_TIME_RFC1123_SUPPORTED) 1.1106 + png_free(png_ptr, png_ptr->time_buffer); 1.1107 +#endif 1.1108 + 1.1109 +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) 1.1110 + png_free(png_ptr, png_ptr->prev_filters); 1.1111 + png_free(png_ptr, png_ptr->filter_weights); 1.1112 + png_free(png_ptr, png_ptr->inv_filter_weights); 1.1113 + png_free(png_ptr, png_ptr->filter_costs); 1.1114 + png_free(png_ptr, png_ptr->inv_filter_costs); 1.1115 +#endif 1.1116 + 1.1117 +#ifdef PNG_SETJMP_SUPPORTED 1.1118 + /* reset structure */ 1.1119 + png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); 1.1120 +#endif 1.1121 + 1.1122 + error_fn = png_ptr->error_fn; 1.1123 + warning_fn = png_ptr->warning_fn; 1.1124 + error_ptr = png_ptr->error_ptr; 1.1125 +#ifdef PNG_USER_MEM_SUPPORTED 1.1126 + free_fn = png_ptr->free_fn; 1.1127 +#endif 1.1128 + 1.1129 + png_memset(png_ptr, 0, png_sizeof(png_struct)); 1.1130 + 1.1131 + png_ptr->error_fn = error_fn; 1.1132 + png_ptr->warning_fn = warning_fn; 1.1133 + png_ptr->error_ptr = error_ptr; 1.1134 +#ifdef PNG_USER_MEM_SUPPORTED 1.1135 + png_ptr->free_fn = free_fn; 1.1136 +#endif 1.1137 + 1.1138 +#ifdef PNG_SETJMP_SUPPORTED 1.1139 + png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); 1.1140 +#endif 1.1141 +} 1.1142 + 1.1143 +/* Allow the application to select one or more row filters to use. */ 1.1144 +void PNGAPI 1.1145 +png_set_filter(png_structp png_ptr, int method, int filters) 1.1146 +{ 1.1147 + png_debug(1, "in png_set_filter\n"); 1.1148 + if (png_ptr == NULL) 1.1149 + return; 1.1150 +#if defined(PNG_MNG_FEATURES_SUPPORTED) 1.1151 + if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 1.1152 + (method == PNG_INTRAPIXEL_DIFFERENCING)) 1.1153 + method = PNG_FILTER_TYPE_BASE; 1.1154 +#endif 1.1155 + if (method == PNG_FILTER_TYPE_BASE) 1.1156 + { 1.1157 + switch (filters & (PNG_ALL_FILTERS | 0x07)) 1.1158 + { 1.1159 +#ifndef PNG_NO_WRITE_FILTER 1.1160 + case 5: 1.1161 + case 6: 1.1162 + case 7: png_warning(png_ptr, "Unknown row filter for method 0"); 1.1163 +#endif /* PNG_NO_WRITE_FILTER */ 1.1164 + case PNG_FILTER_VALUE_NONE: 1.1165 + png_ptr->do_filter=PNG_FILTER_NONE; break; 1.1166 +#ifndef PNG_NO_WRITE_FILTER 1.1167 + case PNG_FILTER_VALUE_SUB: 1.1168 + png_ptr->do_filter=PNG_FILTER_SUB; break; 1.1169 + case PNG_FILTER_VALUE_UP: 1.1170 + png_ptr->do_filter=PNG_FILTER_UP; break; 1.1171 + case PNG_FILTER_VALUE_AVG: 1.1172 + png_ptr->do_filter=PNG_FILTER_AVG; break; 1.1173 + case PNG_FILTER_VALUE_PAETH: 1.1174 + png_ptr->do_filter=PNG_FILTER_PAETH; break; 1.1175 + default: png_ptr->do_filter = (png_byte)filters; break; 1.1176 +#else 1.1177 + default: png_warning(png_ptr, "Unknown row filter for method 0"); 1.1178 +#endif /* PNG_NO_WRITE_FILTER */ 1.1179 + } 1.1180 + 1.1181 + /* If we have allocated the row_buf, this means we have already started 1.1182 + * with the image and we should have allocated all of the filter buffers 1.1183 + * that have been selected. If prev_row isn't already allocated, then 1.1184 + * it is too late to start using the filters that need it, since we 1.1185 + * will be missing the data in the previous row. If an application 1.1186 + * wants to start and stop using particular filters during compression, 1.1187 + * it should start out with all of the filters, and then add and 1.1188 + * remove them after the start of compression. 1.1189 + */ 1.1190 + if (png_ptr->row_buf != NULL) 1.1191 + { 1.1192 +#ifndef PNG_NO_WRITE_FILTER 1.1193 + if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL) 1.1194 + { 1.1195 + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, 1.1196 + (png_ptr->rowbytes + 1)); 1.1197 + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; 1.1198 + } 1.1199 + 1.1200 + if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL) 1.1201 + { 1.1202 + if (png_ptr->prev_row == NULL) 1.1203 + { 1.1204 + png_warning(png_ptr, "Can't add Up filter after starting"); 1.1205 + png_ptr->do_filter &= ~PNG_FILTER_UP; 1.1206 + } 1.1207 + else 1.1208 + { 1.1209 + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, 1.1210 + (png_ptr->rowbytes + 1)); 1.1211 + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; 1.1212 + } 1.1213 + } 1.1214 + 1.1215 + if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL) 1.1216 + { 1.1217 + if (png_ptr->prev_row == NULL) 1.1218 + { 1.1219 + png_warning(png_ptr, "Can't add Average filter after starting"); 1.1220 + png_ptr->do_filter &= ~PNG_FILTER_AVG; 1.1221 + } 1.1222 + else 1.1223 + { 1.1224 + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, 1.1225 + (png_ptr->rowbytes + 1)); 1.1226 + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; 1.1227 + } 1.1228 + } 1.1229 + 1.1230 + if ((png_ptr->do_filter & PNG_FILTER_PAETH) && 1.1231 + png_ptr->paeth_row == NULL) 1.1232 + { 1.1233 + if (png_ptr->prev_row == NULL) 1.1234 + { 1.1235 + png_warning(png_ptr, "Can't add Paeth filter after starting"); 1.1236 + png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); 1.1237 + } 1.1238 + else 1.1239 + { 1.1240 + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, 1.1241 + (png_ptr->rowbytes + 1)); 1.1242 + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; 1.1243 + } 1.1244 + } 1.1245 + 1.1246 + if (png_ptr->do_filter == PNG_NO_FILTERS) 1.1247 +#endif /* PNG_NO_WRITE_FILTER */ 1.1248 + png_ptr->do_filter = PNG_FILTER_NONE; 1.1249 + } 1.1250 + } 1.1251 + else 1.1252 + png_error(png_ptr, "Unknown custom filter method"); 1.1253 +} 1.1254 + 1.1255 +/* This allows us to influence the way in which libpng chooses the "best" 1.1256 + * filter for the current scanline. While the "minimum-sum-of-absolute- 1.1257 + * differences metric is relatively fast and effective, there is some 1.1258 + * question as to whether it can be improved upon by trying to keep the 1.1259 + * filtered data going to zlib more consistent, hopefully resulting in 1.1260 + * better compression. 1.1261 + */ 1.1262 +#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */ 1.1263 +void PNGAPI 1.1264 +png_set_filter_heuristics(png_structp png_ptr, int heuristic_method, 1.1265 + int num_weights, png_doublep filter_weights, 1.1266 + png_doublep filter_costs) 1.1267 +{ 1.1268 + int i; 1.1269 + 1.1270 + png_debug(1, "in png_set_filter_heuristics\n"); 1.1271 + if (png_ptr == NULL) 1.1272 + return; 1.1273 + if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST) 1.1274 + { 1.1275 + png_warning(png_ptr, "Unknown filter heuristic method"); 1.1276 + return; 1.1277 + } 1.1278 + 1.1279 + if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT) 1.1280 + { 1.1281 + heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; 1.1282 + } 1.1283 + 1.1284 + if (num_weights < 0 || filter_weights == NULL || 1.1285 + heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) 1.1286 + { 1.1287 + num_weights = 0; 1.1288 + } 1.1289 + 1.1290 + png_ptr->num_prev_filters = (png_byte)num_weights; 1.1291 + png_ptr->heuristic_method = (png_byte)heuristic_method; 1.1292 + 1.1293 + if (num_weights > 0) 1.1294 + { 1.1295 + if (png_ptr->prev_filters == NULL) 1.1296 + { 1.1297 + png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, 1.1298 + (png_uint_32)(png_sizeof(png_byte) * num_weights)); 1.1299 + 1.1300 + /* To make sure that the weighting starts out fairly */ 1.1301 + for (i = 0; i < num_weights; i++) 1.1302 + { 1.1303 + png_ptr->prev_filters[i] = 255; 1.1304 + } 1.1305 + } 1.1306 + 1.1307 + if (png_ptr->filter_weights == NULL) 1.1308 + { 1.1309 + png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, 1.1310 + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); 1.1311 + 1.1312 + png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, 1.1313 + (png_uint_32)(png_sizeof(png_uint_16) * num_weights)); 1.1314 + for (i = 0; i < num_weights; i++) 1.1315 + { 1.1316 + png_ptr->inv_filter_weights[i] = 1.1317 + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; 1.1318 + } 1.1319 + } 1.1320 + 1.1321 + for (i = 0; i < num_weights; i++) 1.1322 + { 1.1323 + if (filter_weights[i] < 0.0) 1.1324 + { 1.1325 + png_ptr->inv_filter_weights[i] = 1.1326 + png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; 1.1327 + } 1.1328 + else 1.1329 + { 1.1330 + png_ptr->inv_filter_weights[i] = 1.1331 + (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5); 1.1332 + png_ptr->filter_weights[i] = 1.1333 + (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5); 1.1334 + } 1.1335 + } 1.1336 + } 1.1337 + 1.1338 + /* If, in the future, there are other filter methods, this would 1.1339 + * need to be based on png_ptr->filter. 1.1340 + */ 1.1341 + if (png_ptr->filter_costs == NULL) 1.1342 + { 1.1343 + png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, 1.1344 + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); 1.1345 + 1.1346 + png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, 1.1347 + (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST)); 1.1348 + 1.1349 + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) 1.1350 + { 1.1351 + png_ptr->inv_filter_costs[i] = 1.1352 + png_ptr->filter_costs[i] = PNG_COST_FACTOR; 1.1353 + } 1.1354 + } 1.1355 + 1.1356 + /* Here is where we set the relative costs of the different filters. We 1.1357 + * should take the desired compression level into account when setting 1.1358 + * the costs, so that Paeth, for instance, has a high relative cost at low 1.1359 + * compression levels, while it has a lower relative cost at higher 1.1360 + * compression settings. The filter types are in order of increasing 1.1361 + * relative cost, so it would be possible to do this with an algorithm. 1.1362 + */ 1.1363 + for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) 1.1364 + { 1.1365 + if (filter_costs == NULL || filter_costs[i] < 0.0) 1.1366 + { 1.1367 + png_ptr->inv_filter_costs[i] = 1.1368 + png_ptr->filter_costs[i] = PNG_COST_FACTOR; 1.1369 + } 1.1370 + else if (filter_costs[i] >= 1.0) 1.1371 + { 1.1372 + png_ptr->inv_filter_costs[i] = 1.1373 + (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5); 1.1374 + png_ptr->filter_costs[i] = 1.1375 + (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5); 1.1376 + } 1.1377 + } 1.1378 +} 1.1379 +#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ 1.1380 + 1.1381 +void PNGAPI 1.1382 +png_set_compression_level(png_structp png_ptr, int level) 1.1383 +{ 1.1384 + png_debug(1, "in png_set_compression_level\n"); 1.1385 + if (png_ptr == NULL) 1.1386 + return; 1.1387 + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; 1.1388 + png_ptr->zlib_level = level; 1.1389 +} 1.1390 + 1.1391 +void PNGAPI 1.1392 +png_set_compression_mem_level(png_structp png_ptr, int mem_level) 1.1393 +{ 1.1394 + png_debug(1, "in png_set_compression_mem_level\n"); 1.1395 + if (png_ptr == NULL) 1.1396 + return; 1.1397 + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; 1.1398 + png_ptr->zlib_mem_level = mem_level; 1.1399 +} 1.1400 + 1.1401 +void PNGAPI 1.1402 +png_set_compression_strategy(png_structp png_ptr, int strategy) 1.1403 +{ 1.1404 + png_debug(1, "in png_set_compression_strategy\n"); 1.1405 + if (png_ptr == NULL) 1.1406 + return; 1.1407 + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; 1.1408 + png_ptr->zlib_strategy = strategy; 1.1409 +} 1.1410 + 1.1411 +void PNGAPI 1.1412 +png_set_compression_window_bits(png_structp png_ptr, int window_bits) 1.1413 +{ 1.1414 + if (png_ptr == NULL) 1.1415 + return; 1.1416 + if (window_bits > 15) 1.1417 + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); 1.1418 + else if (window_bits < 8) 1.1419 + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); 1.1420 +#ifndef WBITS_8_OK 1.1421 + /* avoid libpng bug with 256-byte windows */ 1.1422 + if (window_bits == 8) 1.1423 + { 1.1424 + png_warning(png_ptr, "Compression window is being reset to 512"); 1.1425 + window_bits=9; 1.1426 + } 1.1427 +#endif 1.1428 + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS; 1.1429 + png_ptr->zlib_window_bits = window_bits; 1.1430 +} 1.1431 + 1.1432 +void PNGAPI 1.1433 +png_set_compression_method(png_structp png_ptr, int method) 1.1434 +{ 1.1435 + png_debug(1, "in png_set_compression_method\n"); 1.1436 + if (png_ptr == NULL) 1.1437 + return; 1.1438 + if (method != 8) 1.1439 + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1.1440 + png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; 1.1441 + png_ptr->zlib_method = method; 1.1442 +} 1.1443 + 1.1444 +void PNGAPI 1.1445 +png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) 1.1446 +{ 1.1447 + if (png_ptr == NULL) 1.1448 + return; 1.1449 + png_ptr->write_row_fn = write_row_fn; 1.1450 +} 1.1451 + 1.1452 +#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) 1.1453 +void PNGAPI 1.1454 +png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr 1.1455 + write_user_transform_fn) 1.1456 +{ 1.1457 + png_debug(1, "in png_set_write_user_transform_fn\n"); 1.1458 + if (png_ptr == NULL) 1.1459 + return; 1.1460 + png_ptr->transformations |= PNG_USER_TRANSFORM; 1.1461 + png_ptr->write_user_transform_fn = write_user_transform_fn; 1.1462 +} 1.1463 +#endif 1.1464 + 1.1465 + 1.1466 +#if defined(PNG_INFO_IMAGE_SUPPORTED) 1.1467 +void PNGAPI 1.1468 +png_write_png(png_structp png_ptr, png_infop info_ptr, 1.1469 + int transforms, voidp params) 1.1470 +{ 1.1471 + if (png_ptr == NULL || info_ptr == NULL) 1.1472 + return; 1.1473 +#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) 1.1474 + /* invert the alpha channel from opacity to transparency */ 1.1475 + if (transforms & PNG_TRANSFORM_INVERT_ALPHA) 1.1476 + png_set_invert_alpha(png_ptr); 1.1477 +#endif 1.1478 + 1.1479 + /* Write the file header information. */ 1.1480 + png_write_info(png_ptr, info_ptr); 1.1481 + 1.1482 + /* ------ these transformations don't touch the info structure ------- */ 1.1483 + 1.1484 +#if defined(PNG_WRITE_INVERT_SUPPORTED) 1.1485 + /* invert monochrome pixels */ 1.1486 + if (transforms & PNG_TRANSFORM_INVERT_MONO) 1.1487 + png_set_invert_mono(png_ptr); 1.1488 +#endif 1.1489 + 1.1490 +#if defined(PNG_WRITE_SHIFT_SUPPORTED) 1.1491 + /* Shift the pixels up to a legal bit depth and fill in 1.1492 + * as appropriate to correctly scale the image. 1.1493 + */ 1.1494 + if ((transforms & PNG_TRANSFORM_SHIFT) 1.1495 + && (info_ptr->valid & PNG_INFO_sBIT)) 1.1496 + png_set_shift(png_ptr, &info_ptr->sig_bit); 1.1497 +#endif 1.1498 + 1.1499 +#if defined(PNG_WRITE_PACK_SUPPORTED) 1.1500 + /* pack pixels into bytes */ 1.1501 + if (transforms & PNG_TRANSFORM_PACKING) 1.1502 + png_set_packing(png_ptr); 1.1503 +#endif 1.1504 + 1.1505 +#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) 1.1506 + /* swap location of alpha bytes from ARGB to RGBA */ 1.1507 + if (transforms & PNG_TRANSFORM_SWAP_ALPHA) 1.1508 + png_set_swap_alpha(png_ptr); 1.1509 +#endif 1.1510 + 1.1511 +#if defined(PNG_WRITE_FILLER_SUPPORTED) 1.1512 + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into 1.1513 + * RGB (4 channels -> 3 channels). The second parameter is not used. 1.1514 + */ 1.1515 + if (transforms & PNG_TRANSFORM_STRIP_FILLER) 1.1516 + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); 1.1517 +#endif 1.1518 + 1.1519 +#if defined(PNG_WRITE_BGR_SUPPORTED) 1.1520 + /* flip BGR pixels to RGB */ 1.1521 + if (transforms & PNG_TRANSFORM_BGR) 1.1522 + png_set_bgr(png_ptr); 1.1523 +#endif 1.1524 + 1.1525 +#if defined(PNG_WRITE_SWAP_SUPPORTED) 1.1526 + /* swap bytes of 16-bit files to most significant byte first */ 1.1527 + if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) 1.1528 + png_set_swap(png_ptr); 1.1529 +#endif 1.1530 + 1.1531 +#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) 1.1532 + /* swap bits of 1, 2, 4 bit packed pixel formats */ 1.1533 + if (transforms & PNG_TRANSFORM_PACKSWAP) 1.1534 + png_set_packswap(png_ptr); 1.1535 +#endif 1.1536 + 1.1537 + /* ----------------------- end of transformations ------------------- */ 1.1538 + 1.1539 + /* write the bits */ 1.1540 + if (info_ptr->valid & PNG_INFO_IDAT) 1.1541 + png_write_image(png_ptr, info_ptr->row_pointers); 1.1542 + 1.1543 + /* It is REQUIRED to call this to finish writing the rest of the file */ 1.1544 + png_write_end(png_ptr, info_ptr); 1.1545 + 1.1546 + transforms = transforms; /* quiet compiler warnings */ 1.1547 + params = params; 1.1548 +} 1.1549 +#endif 1.1550 +#endif /* PNG_WRITE_SUPPORTED */