1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libpng/pngwutil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,3156 @@ 1.4 + 1.5 +/* pngwutil.c - utilities to write a PNG file 1.6 + * 1.7 + * Last changed in libpng 1.6.2 [April 25, 2013] 1.8 + * Copyright (c) 1998-2013 Glenn Randers-Pehrson 1.9 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 1.10 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 1.11 + * 1.12 + * This code is released under the libpng license. 1.13 + * For conditions of distribution and use, see the disclaimer 1.14 + * and license in png.h 1.15 + */ 1.16 + 1.17 +#include "pngpriv.h" 1.18 + 1.19 +#ifdef PNG_WRITE_SUPPORTED 1.20 + 1.21 +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED 1.22 +/* Place a 32-bit number into a buffer in PNG byte order. We work 1.23 + * with unsigned numbers for convenience, although one supported 1.24 + * ancillary chunk uses signed (two's complement) numbers. 1.25 + */ 1.26 +void PNGAPI 1.27 +png_save_uint_32(png_bytep buf, png_uint_32 i) 1.28 +{ 1.29 + buf[0] = (png_byte)((i >> 24) & 0xff); 1.30 + buf[1] = (png_byte)((i >> 16) & 0xff); 1.31 + buf[2] = (png_byte)((i >> 8) & 0xff); 1.32 + buf[3] = (png_byte)(i & 0xff); 1.33 +} 1.34 + 1.35 +/* Place a 16-bit number into a buffer in PNG byte order. 1.36 + * The parameter is declared unsigned int, not png_uint_16, 1.37 + * just to avoid potential problems on pre-ANSI C compilers. 1.38 + */ 1.39 +void PNGAPI 1.40 +png_save_uint_16(png_bytep buf, unsigned int i) 1.41 +{ 1.42 + buf[0] = (png_byte)((i >> 8) & 0xff); 1.43 + buf[1] = (png_byte)(i & 0xff); 1.44 +} 1.45 +#endif 1.46 + 1.47 +/* Simple function to write the signature. If we have already written 1.48 + * the magic bytes of the signature, or more likely, the PNG stream is 1.49 + * being embedded into another stream and doesn't need its own signature, 1.50 + * we should call png_set_sig_bytes() to tell libpng how many of the 1.51 + * bytes have already been written. 1.52 + */ 1.53 +void PNGAPI 1.54 +png_write_sig(png_structrp png_ptr) 1.55 +{ 1.56 + png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 1.57 + 1.58 +#ifdef PNG_IO_STATE_SUPPORTED 1.59 + /* Inform the I/O callback that the signature is being written */ 1.60 + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; 1.61 +#endif 1.62 + 1.63 + /* Write the rest of the 8 byte signature */ 1.64 + png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], 1.65 + (png_size_t)(8 - png_ptr->sig_bytes)); 1.66 + 1.67 + if (png_ptr->sig_bytes < 3) 1.68 + png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; 1.69 +} 1.70 + 1.71 +/* Write the start of a PNG chunk. The type is the chunk type. 1.72 + * The total_length is the sum of the lengths of all the data you will be 1.73 + * passing in png_write_chunk_data(). 1.74 + */ 1.75 +static void 1.76 +png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, 1.77 + png_uint_32 length) 1.78 +{ 1.79 + png_byte buf[8]; 1.80 + 1.81 +#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) 1.82 + PNG_CSTRING_FROM_CHUNK(buf, chunk_name); 1.83 + png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); 1.84 +#endif 1.85 + 1.86 + if (png_ptr == NULL) 1.87 + return; 1.88 + 1.89 +#ifdef PNG_IO_STATE_SUPPORTED 1.90 + /* Inform the I/O callback that the chunk header is being written. 1.91 + * PNG_IO_CHUNK_HDR requires a single I/O call. 1.92 + */ 1.93 + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; 1.94 +#endif 1.95 + 1.96 + /* Write the length and the chunk name */ 1.97 + png_save_uint_32(buf, length); 1.98 + png_save_uint_32(buf + 4, chunk_name); 1.99 + png_write_data(png_ptr, buf, 8); 1.100 + 1.101 + /* Put the chunk name into png_ptr->chunk_name */ 1.102 + png_ptr->chunk_name = chunk_name; 1.103 + 1.104 + /* Reset the crc and run it over the chunk name */ 1.105 + png_reset_crc(png_ptr); 1.106 + 1.107 + png_calculate_crc(png_ptr, buf + 4, 4); 1.108 + 1.109 +#ifdef PNG_IO_STATE_SUPPORTED 1.110 + /* Inform the I/O callback that chunk data will (possibly) be written. 1.111 + * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. 1.112 + */ 1.113 + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; 1.114 +#endif 1.115 +} 1.116 + 1.117 +void PNGAPI 1.118 +png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, 1.119 + png_uint_32 length) 1.120 +{ 1.121 + png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); 1.122 +} 1.123 + 1.124 +/* Write the data of a PNG chunk started with png_write_chunk_header(). 1.125 + * Note that multiple calls to this function are allowed, and that the 1.126 + * sum of the lengths from these calls *must* add up to the total_length 1.127 + * given to png_write_chunk_header(). 1.128 + */ 1.129 +void PNGAPI 1.130 +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, 1.131 + png_size_t length) 1.132 +{ 1.133 + /* Write the data, and run the CRC over it */ 1.134 + if (png_ptr == NULL) 1.135 + return; 1.136 + 1.137 + if (data != NULL && length > 0) 1.138 + { 1.139 + png_write_data(png_ptr, data, length); 1.140 + 1.141 + /* Update the CRC after writing the data, 1.142 + * in case that the user I/O routine alters it. 1.143 + */ 1.144 + png_calculate_crc(png_ptr, data, length); 1.145 + } 1.146 +} 1.147 + 1.148 +/* Finish a chunk started with png_write_chunk_header(). */ 1.149 +void PNGAPI 1.150 +png_write_chunk_end(png_structrp png_ptr) 1.151 +{ 1.152 + png_byte buf[4]; 1.153 + 1.154 + if (png_ptr == NULL) return; 1.155 + 1.156 +#ifdef PNG_IO_STATE_SUPPORTED 1.157 + /* Inform the I/O callback that the chunk CRC is being written. 1.158 + * PNG_IO_CHUNK_CRC requires a single I/O function call. 1.159 + */ 1.160 + png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; 1.161 +#endif 1.162 + 1.163 + /* Write the crc in a single operation */ 1.164 + png_save_uint_32(buf, png_ptr->crc); 1.165 + 1.166 + png_write_data(png_ptr, buf, (png_size_t)4); 1.167 +} 1.168 + 1.169 +/* Write a PNG chunk all at once. The type is an array of ASCII characters 1.170 + * representing the chunk name. The array must be at least 4 bytes in 1.171 + * length, and does not need to be null terminated. To be safe, pass the 1.172 + * pre-defined chunk names here, and if you need a new one, define it 1.173 + * where the others are defined. The length is the length of the data. 1.174 + * All the data must be present. If that is not possible, use the 1.175 + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() 1.176 + * functions instead. 1.177 + */ 1.178 +static void 1.179 +png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, 1.180 + png_const_bytep data, png_size_t length) 1.181 +{ 1.182 + if (png_ptr == NULL) 1.183 + return; 1.184 + 1.185 + /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ 1.186 + if (length > PNG_UINT_31_MAX) 1.187 + png_error(png_ptr, "length exceeds PNG maxima"); 1.188 + 1.189 + png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); 1.190 + png_write_chunk_data(png_ptr, data, length); 1.191 + png_write_chunk_end(png_ptr); 1.192 +} 1.193 + 1.194 +/* This is the API that calls the internal function above. */ 1.195 +void PNGAPI 1.196 +png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, 1.197 + png_const_bytep data, png_size_t length) 1.198 +{ 1.199 + png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, 1.200 + length); 1.201 +} 1.202 + 1.203 +/* This is used below to find the size of an image to pass to png_deflate_claim, 1.204 + * so it only needs to be accurate if the size is less than 16384 bytes (the 1.205 + * point at which a lower LZ window size can be used.) 1.206 + */ 1.207 +static png_alloc_size_t 1.208 +png_image_size(png_structrp png_ptr) 1.209 +{ 1.210 + /* Only return sizes up to the maximum of a png_uint_32, do this by limiting 1.211 + * the width and height used to 15 bits. 1.212 + */ 1.213 + png_uint_32 h = png_ptr->height; 1.214 + 1.215 + if (png_ptr->rowbytes < 32768 && h < 32768) 1.216 + { 1.217 + if (png_ptr->interlaced) 1.218 + { 1.219 + /* Interlacing makes the image larger because of the replication of 1.220 + * both the filter byte and the padding to a byte boundary. 1.221 + */ 1.222 + png_uint_32 w = png_ptr->width; 1.223 + unsigned int pd = png_ptr->pixel_depth; 1.224 + png_alloc_size_t cb_base; 1.225 + int pass; 1.226 + 1.227 + for (cb_base=0, pass=0; pass<=6; ++pass) 1.228 + { 1.229 + png_uint_32 pw = PNG_PASS_COLS(w, pass); 1.230 + 1.231 + if (pw > 0) 1.232 + cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); 1.233 + } 1.234 + 1.235 + return cb_base; 1.236 + } 1.237 + 1.238 + else 1.239 + return (png_ptr->rowbytes+1) * h; 1.240 + } 1.241 + 1.242 + else 1.243 + return 0xffffffffU; 1.244 +} 1.245 + 1.246 +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 1.247 + /* This is the code to hack the first two bytes of the deflate stream (the 1.248 + * deflate header) to correct the windowBits value to match the actual data 1.249 + * size. Note that the second argument is the *uncompressed* size but the 1.250 + * first argument is the *compressed* data (and it must be deflate 1.251 + * compressed.) 1.252 + */ 1.253 +static void 1.254 +optimize_cmf(png_bytep data, png_alloc_size_t data_size) 1.255 +{ 1.256 + /* Optimize the CMF field in the zlib stream. The resultant zlib stream is 1.257 + * still compliant to the stream specification. 1.258 + */ 1.259 + if (data_size <= 16384) /* else windowBits must be 15 */ 1.260 + { 1.261 + unsigned int z_cmf = data[0]; /* zlib compression method and flags */ 1.262 + 1.263 + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) 1.264 + { 1.265 + unsigned int z_cinfo; 1.266 + unsigned int half_z_window_size; 1.267 + 1.268 + z_cinfo = z_cmf >> 4; 1.269 + half_z_window_size = 1U << (z_cinfo + 7); 1.270 + 1.271 + if (data_size <= half_z_window_size) /* else no change */ 1.272 + { 1.273 + unsigned int tmp; 1.274 + 1.275 + do 1.276 + { 1.277 + half_z_window_size >>= 1; 1.278 + --z_cinfo; 1.279 + } 1.280 + while (z_cinfo > 0 && data_size <= half_z_window_size); 1.281 + 1.282 + z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); 1.283 + 1.284 + data[0] = (png_byte)z_cmf; 1.285 + tmp = data[1] & 0xe0; 1.286 + tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; 1.287 + data[1] = (png_byte)tmp; 1.288 + } 1.289 + } 1.290 + } 1.291 +} 1.292 +#else 1.293 +# define optimize_cmf(dp,dl) ((void)0) 1.294 +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */ 1.295 + 1.296 +/* Initialize the compressor for the appropriate type of compression. */ 1.297 +static int 1.298 +png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, 1.299 + png_alloc_size_t data_size) 1.300 +{ 1.301 + if (png_ptr->zowner != 0) 1.302 + { 1.303 + char msg[64]; 1.304 + 1.305 + PNG_STRING_FROM_CHUNK(msg, owner); 1.306 + msg[4] = ':'; 1.307 + msg[5] = ' '; 1.308 + PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); 1.309 + /* So the message that results is "<chunk> using zstream"; this is an 1.310 + * internal error, but is very useful for debugging. i18n requirements 1.311 + * are minimal. 1.312 + */ 1.313 + (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); 1.314 +# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC 1.315 + png_warning(png_ptr, msg); 1.316 + 1.317 + /* Attempt sane error recovery */ 1.318 + if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ 1.319 + { 1.320 + png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); 1.321 + return Z_STREAM_ERROR; 1.322 + } 1.323 + 1.324 + png_ptr->zowner = 0; 1.325 +# else 1.326 + png_error(png_ptr, msg); 1.327 +# endif 1.328 + } 1.329 + 1.330 + { 1.331 + int level = png_ptr->zlib_level; 1.332 + int method = png_ptr->zlib_method; 1.333 + int windowBits = png_ptr->zlib_window_bits; 1.334 + int memLevel = png_ptr->zlib_mem_level; 1.335 + int strategy; /* set below */ 1.336 + int ret; /* zlib return code */ 1.337 + 1.338 + if (owner == png_IDAT) 1.339 + { 1.340 + if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) 1.341 + strategy = png_ptr->zlib_strategy; 1.342 + 1.343 + else if (png_ptr->do_filter != PNG_FILTER_NONE) 1.344 + strategy = PNG_Z_DEFAULT_STRATEGY; 1.345 + 1.346 + else 1.347 + strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; 1.348 + } 1.349 + 1.350 + else 1.351 + { 1.352 +# ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 1.353 + level = png_ptr->zlib_text_level; 1.354 + method = png_ptr->zlib_text_method; 1.355 + windowBits = png_ptr->zlib_text_window_bits; 1.356 + memLevel = png_ptr->zlib_text_mem_level; 1.357 + strategy = png_ptr->zlib_text_strategy; 1.358 +# else 1.359 + /* If customization is not supported the values all come from the 1.360 + * IDAT values except for the strategy, which is fixed to the 1.361 + * default. (This is the pre-1.6.0 behavior too, although it was 1.362 + * implemented in a very different way.) 1.363 + */ 1.364 + strategy = Z_DEFAULT_STRATEGY; 1.365 +# endif 1.366 + } 1.367 + 1.368 + /* Adjust 'windowBits' down if larger than 'data_size'; to stop this 1.369 + * happening just pass 32768 as the data_size parameter. Notice that zlib 1.370 + * requires an extra 262 bytes in the window in addition to the data to be 1.371 + * able to see the whole of the data, so if data_size+262 takes us to the 1.372 + * next windowBits size we need to fix up the value later. (Because even 1.373 + * though deflate needs the extra window, inflate does not!) 1.374 + */ 1.375 + if (data_size <= 16384) 1.376 + { 1.377 + /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to 1.378 + * work round a Microsoft Visual C misbehavior which, contrary to C-90, 1.379 + * widens the result of the following shift to 64-bits if (and, 1.380 + * apparently, only if) it is used in a test. 1.381 + */ 1.382 + unsigned int half_window_size = 1U << (windowBits-1); 1.383 + 1.384 + while (data_size + 262 <= half_window_size) 1.385 + { 1.386 + half_window_size >>= 1; 1.387 + --windowBits; 1.388 + } 1.389 + } 1.390 + 1.391 + /* Check against the previous initialized values, if any. */ 1.392 + if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) && 1.393 + (png_ptr->zlib_set_level != level || 1.394 + png_ptr->zlib_set_method != method || 1.395 + png_ptr->zlib_set_window_bits != windowBits || 1.396 + png_ptr->zlib_set_mem_level != memLevel || 1.397 + png_ptr->zlib_set_strategy != strategy)) 1.398 + { 1.399 + if (deflateEnd(&png_ptr->zstream) != Z_OK) 1.400 + png_warning(png_ptr, "deflateEnd failed (ignored)"); 1.401 + 1.402 + png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; 1.403 + } 1.404 + 1.405 + /* For safety clear out the input and output pointers (currently zlib 1.406 + * doesn't use them on Init, but it might in the future). 1.407 + */ 1.408 + png_ptr->zstream.next_in = NULL; 1.409 + png_ptr->zstream.avail_in = 0; 1.410 + png_ptr->zstream.next_out = NULL; 1.411 + png_ptr->zstream.avail_out = 0; 1.412 + 1.413 + /* Now initialize if required, setting the new parameters, otherwise just 1.414 + * to a simple reset to the previous parameters. 1.415 + */ 1.416 + if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) 1.417 + ret = deflateReset(&png_ptr->zstream); 1.418 + 1.419 + else 1.420 + { 1.421 + ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, 1.422 + memLevel, strategy); 1.423 + 1.424 + if (ret == Z_OK) 1.425 + png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; 1.426 + } 1.427 + 1.428 + /* The return code is from either deflateReset or deflateInit2; they have 1.429 + * pretty much the same set of error codes. 1.430 + */ 1.431 + if (ret == Z_OK) 1.432 + png_ptr->zowner = owner; 1.433 + 1.434 + else 1.435 + png_zstream_error(png_ptr, ret); 1.436 + 1.437 + return ret; 1.438 + } 1.439 +} 1.440 + 1.441 +/* Clean up (or trim) a linked list of compression buffers. */ 1.442 +void /* PRIVATE */ 1.443 +png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) 1.444 +{ 1.445 + png_compression_bufferp list = *listp; 1.446 + 1.447 + if (list != NULL) 1.448 + { 1.449 + *listp = NULL; 1.450 + 1.451 + do 1.452 + { 1.453 + png_compression_bufferp next = list->next; 1.454 + 1.455 + png_free(png_ptr, list); 1.456 + list = next; 1.457 + } 1.458 + while (list != NULL); 1.459 + } 1.460 +} 1.461 + 1.462 +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED 1.463 +/* This pair of functions encapsulates the operation of (a) compressing a 1.464 + * text string, and (b) issuing it later as a series of chunk data writes. 1.465 + * The compression_state structure is shared context for these functions 1.466 + * set up by the caller to allow access to the relevant local variables. 1.467 + * 1.468 + * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size 1.469 + * temporary buffers. From 1.6.0 it is retained in png_struct so that it will 1.470 + * be correctly freed in the event of a write error (previous implementations 1.471 + * just leaked memory.) 1.472 + */ 1.473 +typedef struct 1.474 +{ 1.475 + png_const_bytep input; /* The uncompressed input data */ 1.476 + png_alloc_size_t input_len; /* Its length */ 1.477 + png_uint_32 output_len; /* Final compressed length */ 1.478 + png_byte output[1024]; /* First block of output */ 1.479 +} compression_state; 1.480 + 1.481 +static void 1.482 +png_text_compress_init(compression_state *comp, png_const_bytep input, 1.483 + png_alloc_size_t input_len) 1.484 +{ 1.485 + comp->input = input; 1.486 + comp->input_len = input_len; 1.487 + comp->output_len = 0; 1.488 +} 1.489 + 1.490 +/* Compress the data in the compression state input */ 1.491 +static int 1.492 +png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, 1.493 + compression_state *comp, png_uint_32 prefix_len) 1.494 +{ 1.495 + int ret; 1.496 + 1.497 + /* To find the length of the output it is necessary to first compress the 1.498 + * input, the result is buffered rather than using the two-pass algorithm 1.499 + * that is used on the inflate side; deflate is assumed to be slower and a 1.500 + * PNG writer is assumed to have more memory available than a PNG reader. 1.501 + * 1.502 + * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an 1.503 + * upper limit on the output size, but it is always bigger than the input 1.504 + * size so it is likely to be more efficient to use this linked-list 1.505 + * approach. 1.506 + */ 1.507 + ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); 1.508 + 1.509 + if (ret != Z_OK) 1.510 + return ret; 1.511 + 1.512 + /* Set up the compression buffers, we need a loop here to avoid overflowing a 1.513 + * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited 1.514 + * by the output buffer size, so there is no need to check that. Since this 1.515 + * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits 1.516 + * in size. 1.517 + */ 1.518 + { 1.519 + png_compression_bufferp *end = &png_ptr->zbuffer_list; 1.520 + png_alloc_size_t input_len = comp->input_len; /* may be zero! */ 1.521 + png_uint_32 output_len; 1.522 + 1.523 + /* zlib updates these for us: */ 1.524 + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); 1.525 + png_ptr->zstream.avail_in = 0; /* Set below */ 1.526 + png_ptr->zstream.next_out = comp->output; 1.527 + png_ptr->zstream.avail_out = (sizeof comp->output); 1.528 + 1.529 + output_len = png_ptr->zstream.avail_out; 1.530 + 1.531 + do 1.532 + { 1.533 + uInt avail_in = ZLIB_IO_MAX; 1.534 + 1.535 + if (avail_in > input_len) 1.536 + avail_in = (uInt)input_len; 1.537 + 1.538 + input_len -= avail_in; 1.539 + 1.540 + png_ptr->zstream.avail_in = avail_in; 1.541 + 1.542 + if (png_ptr->zstream.avail_out == 0) 1.543 + { 1.544 + png_compression_buffer *next; 1.545 + 1.546 + /* Chunk data is limited to 2^31 bytes in length, so the prefix 1.547 + * length must be counted here. 1.548 + */ 1.549 + if (output_len + prefix_len > PNG_UINT_31_MAX) 1.550 + { 1.551 + ret = Z_MEM_ERROR; 1.552 + break; 1.553 + } 1.554 + 1.555 + /* Need a new (malloc'ed) buffer, but there may be one present 1.556 + * already. 1.557 + */ 1.558 + next = *end; 1.559 + if (next == NULL) 1.560 + { 1.561 + next = png_voidcast(png_compression_bufferp, png_malloc_base 1.562 + (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); 1.563 + 1.564 + if (next == NULL) 1.565 + { 1.566 + ret = Z_MEM_ERROR; 1.567 + break; 1.568 + } 1.569 + 1.570 + /* Link in this buffer (so that it will be freed later) */ 1.571 + next->next = NULL; 1.572 + *end = next; 1.573 + } 1.574 + 1.575 + png_ptr->zstream.next_out = next->output; 1.576 + png_ptr->zstream.avail_out = png_ptr->zbuffer_size; 1.577 + output_len += png_ptr->zstream.avail_out; 1.578 + 1.579 + /* Move 'end' to the next buffer pointer. */ 1.580 + end = &next->next; 1.581 + } 1.582 + 1.583 + /* Compress the data */ 1.584 + ret = deflate(&png_ptr->zstream, 1.585 + input_len > 0 ? Z_NO_FLUSH : Z_FINISH); 1.586 + 1.587 + /* Claw back input data that was not consumed (because avail_in is 1.588 + * reset above every time round the loop). 1.589 + */ 1.590 + input_len += png_ptr->zstream.avail_in; 1.591 + png_ptr->zstream.avail_in = 0; /* safety */ 1.592 + } 1.593 + while (ret == Z_OK); 1.594 + 1.595 + /* There may be some space left in the last output buffer, this needs to 1.596 + * be subtracted from output_len. 1.597 + */ 1.598 + output_len -= png_ptr->zstream.avail_out; 1.599 + png_ptr->zstream.avail_out = 0; /* safety */ 1.600 + comp->output_len = output_len; 1.601 + 1.602 + /* Now double check the output length, put in a custom message if it is 1.603 + * too long. Otherwise ensure the z_stream::msg pointer is set to 1.604 + * something. 1.605 + */ 1.606 + if (output_len + prefix_len >= PNG_UINT_31_MAX) 1.607 + { 1.608 + png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); 1.609 + ret = Z_MEM_ERROR; 1.610 + } 1.611 + 1.612 + else 1.613 + png_zstream_error(png_ptr, ret); 1.614 + 1.615 + /* Reset zlib for another zTXt/iTXt or image data */ 1.616 + png_ptr->zowner = 0; 1.617 + 1.618 + /* The only success case is Z_STREAM_END, input_len must be 0, if not this 1.619 + * is an internal error. 1.620 + */ 1.621 + if (ret == Z_STREAM_END && input_len == 0) 1.622 + { 1.623 + /* Fix up the deflate header, if required */ 1.624 + optimize_cmf(comp->output, comp->input_len); 1.625 + 1.626 + /* But Z_OK is returned, not Z_STREAM_END; this allows the claim 1.627 + * function above to return Z_STREAM_END on an error (though it never 1.628 + * does in the current versions of zlib.) 1.629 + */ 1.630 + return Z_OK; 1.631 + } 1.632 + 1.633 + else 1.634 + return ret; 1.635 + } 1.636 +} 1.637 + 1.638 +/* Ship the compressed text out via chunk writes */ 1.639 +static void 1.640 +png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) 1.641 +{ 1.642 + png_uint_32 output_len = comp->output_len; 1.643 + png_const_bytep output = comp->output; 1.644 + png_uint_32 avail = (sizeof comp->output); 1.645 + png_compression_buffer *next = png_ptr->zbuffer_list; 1.646 + 1.647 + for (;;) 1.648 + { 1.649 + if (avail > output_len) 1.650 + avail = output_len; 1.651 + 1.652 + png_write_chunk_data(png_ptr, output, avail); 1.653 + 1.654 + output_len -= avail; 1.655 + 1.656 + if (output_len == 0 || next == NULL) 1.657 + break; 1.658 + 1.659 + avail = png_ptr->zbuffer_size; 1.660 + output = next->output; 1.661 + next = next->next; 1.662 + } 1.663 + 1.664 + /* This is an internal error; 'next' must have been NULL! */ 1.665 + if (output_len > 0) 1.666 + png_error(png_ptr, "error writing ancillary chunked compressed data"); 1.667 +} 1.668 +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */ 1.669 + 1.670 +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ 1.671 + defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 1.672 +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, 1.673 + * and if invalid, correct the keyword rather than discarding the entire 1.674 + * chunk. The PNG 1.0 specification requires keywords 1-79 characters in 1.675 + * length, forbids leading or trailing whitespace, multiple internal spaces, 1.676 + * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. 1.677 + * 1.678 + * The 'new_key' buffer must be 80 characters in size (for the keyword plus a 1.679 + * trailing '\0'). If this routine returns 0 then there was no keyword, or a 1.680 + * valid one could not be generated, and the caller must png_error. 1.681 + */ 1.682 +static png_uint_32 1.683 +png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) 1.684 +{ 1.685 + png_const_charp orig_key = key; 1.686 + png_uint_32 key_len = 0; 1.687 + int bad_character = 0; 1.688 + int space = 1; 1.689 + 1.690 + png_debug(1, "in png_check_keyword"); 1.691 + 1.692 + if (key == NULL) 1.693 + { 1.694 + *new_key = 0; 1.695 + return 0; 1.696 + } 1.697 + 1.698 + while (*key && key_len < 79) 1.699 + { 1.700 + png_byte ch = (png_byte)(0xff & *key++); 1.701 + 1.702 + if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) 1.703 + *new_key++ = ch, ++key_len, space = 0; 1.704 + 1.705 + else if (!space) 1.706 + { 1.707 + /* A space or an invalid character when one wasn't seen immediately 1.708 + * before; output just a space. 1.709 + */ 1.710 + *new_key++ = 32, ++key_len, space = 1; 1.711 + 1.712 + /* If the character was not a space then it is invalid. */ 1.713 + if (ch != 32) 1.714 + bad_character = ch; 1.715 + } 1.716 + 1.717 + else if (!bad_character) 1.718 + bad_character = ch; /* just skip it, record the first error */ 1.719 + } 1.720 + 1.721 + if (key_len > 0 && space) /* trailing space */ 1.722 + { 1.723 + --key_len, --new_key; 1.724 + if (!bad_character) 1.725 + bad_character = 32; 1.726 + } 1.727 + 1.728 + /* Terminate the keyword */ 1.729 + *new_key = 0; 1.730 + 1.731 + if (key_len == 0) 1.732 + return 0; 1.733 + 1.734 + /* Try to only output one warning per keyword: */ 1.735 + if (*key) /* keyword too long */ 1.736 + png_warning(png_ptr, "keyword truncated"); 1.737 + 1.738 + else if (bad_character) 1.739 + { 1.740 + PNG_WARNING_PARAMETERS(p) 1.741 + 1.742 + png_warning_parameter(p, 1, orig_key); 1.743 + png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character); 1.744 + 1.745 + png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'"); 1.746 + } 1.747 + 1.748 + return key_len; 1.749 +} 1.750 +#endif 1.751 + 1.752 +/* Write the IHDR chunk, and update the png_struct with the necessary 1.753 + * information. Note that the rest of this code depends upon this 1.754 + * information being correct. 1.755 + */ 1.756 +void /* PRIVATE */ 1.757 +png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, 1.758 + int bit_depth, int color_type, int compression_type, int filter_type, 1.759 + int interlace_type) 1.760 +{ 1.761 + png_byte buf[13]; /* Buffer to store the IHDR info */ 1.762 + 1.763 + png_debug(1, "in png_write_IHDR"); 1.764 + 1.765 + /* Check that we have valid input data from the application info */ 1.766 + switch (color_type) 1.767 + { 1.768 + case PNG_COLOR_TYPE_GRAY: 1.769 + switch (bit_depth) 1.770 + { 1.771 + case 1: 1.772 + case 2: 1.773 + case 4: 1.774 + case 8: 1.775 +#ifdef PNG_WRITE_16BIT_SUPPORTED 1.776 + case 16: 1.777 +#endif 1.778 + png_ptr->channels = 1; break; 1.779 + 1.780 + default: 1.781 + png_error(png_ptr, 1.782 + "Invalid bit depth for grayscale image"); 1.783 + } 1.784 + break; 1.785 + 1.786 + case PNG_COLOR_TYPE_RGB: 1.787 +#ifdef PNG_WRITE_16BIT_SUPPORTED 1.788 + if (bit_depth != 8 && bit_depth != 16) 1.789 +#else 1.790 + if (bit_depth != 8) 1.791 +#endif 1.792 + png_error(png_ptr, "Invalid bit depth for RGB image"); 1.793 + 1.794 + png_ptr->channels = 3; 1.795 + break; 1.796 + 1.797 + case PNG_COLOR_TYPE_PALETTE: 1.798 + switch (bit_depth) 1.799 + { 1.800 + case 1: 1.801 + case 2: 1.802 + case 4: 1.803 + case 8: 1.804 + png_ptr->channels = 1; 1.805 + break; 1.806 + 1.807 + default: 1.808 + png_error(png_ptr, "Invalid bit depth for paletted image"); 1.809 + } 1.810 + break; 1.811 + 1.812 + case PNG_COLOR_TYPE_GRAY_ALPHA: 1.813 + if (bit_depth != 8 && bit_depth != 16) 1.814 + png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); 1.815 + 1.816 + png_ptr->channels = 2; 1.817 + break; 1.818 + 1.819 + case PNG_COLOR_TYPE_RGB_ALPHA: 1.820 +#ifdef PNG_WRITE_16BIT_SUPPORTED 1.821 + if (bit_depth != 8 && bit_depth != 16) 1.822 +#else 1.823 + if (bit_depth != 8) 1.824 +#endif 1.825 + png_error(png_ptr, "Invalid bit depth for RGBA image"); 1.826 + 1.827 + png_ptr->channels = 4; 1.828 + break; 1.829 + 1.830 + default: 1.831 + png_error(png_ptr, "Invalid image color type specified"); 1.832 + } 1.833 + 1.834 + if (compression_type != PNG_COMPRESSION_TYPE_BASE) 1.835 + { 1.836 + png_warning(png_ptr, "Invalid compression type specified"); 1.837 + compression_type = PNG_COMPRESSION_TYPE_BASE; 1.838 + } 1.839 + 1.840 + /* Write filter_method 64 (intrapixel differencing) only if 1.841 + * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 1.842 + * 2. Libpng did not write a PNG signature (this filter_method is only 1.843 + * used in PNG datastreams that are embedded in MNG datastreams) and 1.844 + * 3. The application called png_permit_mng_features with a mask that 1.845 + * included PNG_FLAG_MNG_FILTER_64 and 1.846 + * 4. The filter_method is 64 and 1.847 + * 5. The color_type is RGB or RGBA 1.848 + */ 1.849 + if ( 1.850 +#ifdef PNG_MNG_FEATURES_SUPPORTED 1.851 + !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 1.852 + ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && 1.853 + (color_type == PNG_COLOR_TYPE_RGB || 1.854 + color_type == PNG_COLOR_TYPE_RGB_ALPHA) && 1.855 + (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && 1.856 +#endif 1.857 + filter_type != PNG_FILTER_TYPE_BASE) 1.858 + { 1.859 + png_warning(png_ptr, "Invalid filter type specified"); 1.860 + filter_type = PNG_FILTER_TYPE_BASE; 1.861 + } 1.862 + 1.863 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1.864 + if (interlace_type != PNG_INTERLACE_NONE && 1.865 + interlace_type != PNG_INTERLACE_ADAM7) 1.866 + { 1.867 + png_warning(png_ptr, "Invalid interlace type specified"); 1.868 + interlace_type = PNG_INTERLACE_ADAM7; 1.869 + } 1.870 +#else 1.871 + interlace_type=PNG_INTERLACE_NONE; 1.872 +#endif 1.873 + 1.874 + /* Save the relevent information */ 1.875 + png_ptr->bit_depth = (png_byte)bit_depth; 1.876 + png_ptr->color_type = (png_byte)color_type; 1.877 + png_ptr->interlaced = (png_byte)interlace_type; 1.878 +#ifdef PNG_MNG_FEATURES_SUPPORTED 1.879 + png_ptr->filter_type = (png_byte)filter_type; 1.880 +#endif 1.881 + png_ptr->compression_type = (png_byte)compression_type; 1.882 + png_ptr->width = width; 1.883 + png_ptr->height = height; 1.884 + 1.885 + png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); 1.886 + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); 1.887 + /* Set the usr info, so any transformations can modify it */ 1.888 + png_ptr->usr_width = png_ptr->width; 1.889 + png_ptr->usr_bit_depth = png_ptr->bit_depth; 1.890 + png_ptr->usr_channels = png_ptr->channels; 1.891 + 1.892 + /* Pack the header information into the buffer */ 1.893 + png_save_uint_32(buf, width); 1.894 + png_save_uint_32(buf + 4, height); 1.895 + buf[8] = (png_byte)bit_depth; 1.896 + buf[9] = (png_byte)color_type; 1.897 + buf[10] = (png_byte)compression_type; 1.898 + buf[11] = (png_byte)filter_type; 1.899 + buf[12] = (png_byte)interlace_type; 1.900 + 1.901 + /* Write the chunk */ 1.902 + png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); 1.903 + 1.904 +#ifdef PNG_WRITE_APNG_SUPPORTED 1.905 + png_ptr->first_frame_width = width; 1.906 + png_ptr->first_frame_height = height; 1.907 +#endif 1.908 + 1.909 + if (!(png_ptr->do_filter)) 1.910 + { 1.911 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || 1.912 + png_ptr->bit_depth < 8) 1.913 + png_ptr->do_filter = PNG_FILTER_NONE; 1.914 + 1.915 + else 1.916 + png_ptr->do_filter = PNG_ALL_FILTERS; 1.917 + } 1.918 + 1.919 + png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ 1.920 +} 1.921 + 1.922 +/* Write the palette. We are careful not to trust png_color to be in the 1.923 + * correct order for PNG, so people can redefine it to any convenient 1.924 + * structure. 1.925 + */ 1.926 +void /* PRIVATE */ 1.927 +png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, 1.928 + png_uint_32 num_pal) 1.929 +{ 1.930 + png_uint_32 i; 1.931 + png_const_colorp pal_ptr; 1.932 + png_byte buf[3]; 1.933 + 1.934 + png_debug(1, "in png_write_PLTE"); 1.935 + 1.936 + if (( 1.937 +#ifdef PNG_MNG_FEATURES_SUPPORTED 1.938 + !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && 1.939 +#endif 1.940 + num_pal == 0) || num_pal > 256) 1.941 + { 1.942 + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 1.943 + { 1.944 + png_error(png_ptr, "Invalid number of colors in palette"); 1.945 + } 1.946 + 1.947 + else 1.948 + { 1.949 + png_warning(png_ptr, "Invalid number of colors in palette"); 1.950 + return; 1.951 + } 1.952 + } 1.953 + 1.954 + if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) 1.955 + { 1.956 + png_warning(png_ptr, 1.957 + "Ignoring request to write a PLTE chunk in grayscale PNG"); 1.958 + 1.959 + return; 1.960 + } 1.961 + 1.962 + png_ptr->num_palette = (png_uint_16)num_pal; 1.963 + png_debug1(3, "num_palette = %d", png_ptr->num_palette); 1.964 + 1.965 + png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); 1.966 +#ifdef PNG_POINTER_INDEXING_SUPPORTED 1.967 + 1.968 + for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) 1.969 + { 1.970 + buf[0] = pal_ptr->red; 1.971 + buf[1] = pal_ptr->green; 1.972 + buf[2] = pal_ptr->blue; 1.973 + png_write_chunk_data(png_ptr, buf, (png_size_t)3); 1.974 + } 1.975 + 1.976 +#else 1.977 + /* This is a little slower but some buggy compilers need to do this 1.978 + * instead 1.979 + */ 1.980 + pal_ptr=palette; 1.981 + 1.982 + for (i = 0; i < num_pal; i++) 1.983 + { 1.984 + buf[0] = pal_ptr[i].red; 1.985 + buf[1] = pal_ptr[i].green; 1.986 + buf[2] = pal_ptr[i].blue; 1.987 + png_write_chunk_data(png_ptr, buf, (png_size_t)3); 1.988 + } 1.989 + 1.990 +#endif 1.991 + png_write_chunk_end(png_ptr); 1.992 + png_ptr->mode |= PNG_HAVE_PLTE; 1.993 +} 1.994 + 1.995 +/* This is similar to png_text_compress, above, except that it does not require 1.996 + * all of the data at once and, instead of buffering the compressed result, 1.997 + * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out 1.998 + * because it calls the write interface. As a result it does its own error 1.999 + * reporting and does not return an error code. In the event of error it will 1.1000 + * just call png_error. The input data length may exceed 32-bits. The 'flush' 1.1001 + * parameter is exactly the same as that to deflate, with the following 1.1002 + * meanings: 1.1003 + * 1.1004 + * Z_NO_FLUSH: normal incremental output of compressed data 1.1005 + * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush 1.1006 + * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up 1.1007 + * 1.1008 + * The routine manages the acquire and release of the png_ptr->zstream by 1.1009 + * checking and (at the end) clearing png_ptr->zowner, it does some sanity 1.1010 + * checks on the 'mode' flags while doing this. 1.1011 + */ 1.1012 +void /* PRIVATE */ 1.1013 +png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, 1.1014 + png_alloc_size_t input_len, int flush) 1.1015 +{ 1.1016 + if (png_ptr->zowner != png_IDAT) 1.1017 + { 1.1018 + /* First time. Ensure we have a temporary buffer for compression and 1.1019 + * trim the buffer list if it has more than one entry to free memory. 1.1020 + * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been 1.1021 + * created at this point, but the check here is quick and safe. 1.1022 + */ 1.1023 + if (png_ptr->zbuffer_list == NULL) 1.1024 + { 1.1025 + png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, 1.1026 + png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); 1.1027 + png_ptr->zbuffer_list->next = NULL; 1.1028 + } 1.1029 + 1.1030 + else 1.1031 + png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); 1.1032 + 1.1033 + /* It is a terminal error if we can't claim the zstream. */ 1.1034 + if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) 1.1035 + png_error(png_ptr, png_ptr->zstream.msg); 1.1036 + 1.1037 + /* The output state is maintained in png_ptr->zstream, so it must be 1.1038 + * initialized here after the claim. 1.1039 + */ 1.1040 + png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; 1.1041 + png_ptr->zstream.avail_out = png_ptr->zbuffer_size; 1.1042 + } 1.1043 + 1.1044 + /* Now loop reading and writing until all the input is consumed or an error 1.1045 + * terminates the operation. The _out values are maintained across calls to 1.1046 + * this function, but the input must be reset each time. 1.1047 + */ 1.1048 + png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); 1.1049 + png_ptr->zstream.avail_in = 0; /* set below */ 1.1050 + for (;;) 1.1051 + { 1.1052 + int ret; 1.1053 + 1.1054 + /* INPUT: from the row data */ 1.1055 + uInt avail = ZLIB_IO_MAX; 1.1056 + 1.1057 + if (avail > input_len) 1.1058 + avail = (uInt)input_len; /* safe because of the check */ 1.1059 + 1.1060 + png_ptr->zstream.avail_in = avail; 1.1061 + input_len -= avail; 1.1062 + 1.1063 + ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); 1.1064 + 1.1065 + /* Include as-yet unconsumed input */ 1.1066 + input_len += png_ptr->zstream.avail_in; 1.1067 + png_ptr->zstream.avail_in = 0; 1.1068 + 1.1069 + /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note 1.1070 + * that these two zstream fields are preserved across the calls, therefore 1.1071 + * there is no need to set these up on entry to the loop. 1.1072 + */ 1.1073 + if (png_ptr->zstream.avail_out == 0) 1.1074 + { 1.1075 + png_bytep data = png_ptr->zbuffer_list->output; 1.1076 + uInt size = png_ptr->zbuffer_size; 1.1077 + 1.1078 + /* Write an IDAT containing the data then reset the buffer. The 1.1079 + * first IDAT may need deflate header optimization. 1.1080 + */ 1.1081 +# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 1.1082 + if (!(png_ptr->mode & PNG_HAVE_IDAT) && 1.1083 + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) 1.1084 + optimize_cmf(data, png_image_size(png_ptr)); 1.1085 +# endif 1.1086 + 1.1087 +# ifdef PNG_WRITE_APNG_SUPPORTED 1.1088 + if (png_ptr->num_frames_written == 0) 1.1089 +# endif 1.1090 + png_write_complete_chunk(png_ptr, png_IDAT, data, size); 1.1091 +# ifdef PNG_WRITE_APNG_SUPPORTED 1.1092 + else 1.1093 + png_write_fdAT(png_ptr, data, size); 1.1094 +# endif /* PNG_WRITE_APNG_SUPPORTED */ 1.1095 + 1.1096 + png_ptr->mode |= PNG_HAVE_IDAT; 1.1097 + 1.1098 + png_ptr->zstream.next_out = data; 1.1099 + png_ptr->zstream.avail_out = size; 1.1100 + 1.1101 + /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with 1.1102 + * the same flush parameter until it has finished output, for NO_FLUSH 1.1103 + * it doesn't matter. 1.1104 + */ 1.1105 + if (ret == Z_OK && flush != Z_NO_FLUSH) 1.1106 + continue; 1.1107 + } 1.1108 + 1.1109 + /* The order of these checks doesn't matter much; it just effect which 1.1110 + * possible error might be detected if multiple things go wrong at once. 1.1111 + */ 1.1112 + if (ret == Z_OK) /* most likely return code! */ 1.1113 + { 1.1114 + /* If all the input has been consumed then just return. If Z_FINISH 1.1115 + * was used as the flush parameter something has gone wrong if we get 1.1116 + * here. 1.1117 + */ 1.1118 + if (input_len == 0) 1.1119 + { 1.1120 + if (flush == Z_FINISH) 1.1121 + png_error(png_ptr, "Z_OK on Z_FINISH with output space"); 1.1122 + 1.1123 + return; 1.1124 + } 1.1125 + } 1.1126 + 1.1127 + else if (ret == Z_STREAM_END && flush == Z_FINISH) 1.1128 + { 1.1129 + /* This is the end of the IDAT data; any pending output must be 1.1130 + * flushed. For small PNG files we may still be at the beginning. 1.1131 + */ 1.1132 + png_bytep data = png_ptr->zbuffer_list->output; 1.1133 + uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; 1.1134 + 1.1135 +# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 1.1136 + if (!(png_ptr->mode & PNG_HAVE_IDAT) && 1.1137 + png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) 1.1138 + optimize_cmf(data, png_image_size(png_ptr)); 1.1139 +# endif 1.1140 + 1.1141 +# ifdef PNG_WRITE_APNG_SUPPORTED 1.1142 + if (png_ptr->num_frames_written == 0) 1.1143 +# endif 1.1144 + png_write_complete_chunk(png_ptr, png_IDAT, data, size); 1.1145 +# ifdef PNG_WRITE_APNG_SUPPORTED 1.1146 + else 1.1147 + png_write_fdAT(png_ptr, data, size); 1.1148 +# endif /* PNG_WRITE_APNG_SUPPORTED */ 1.1149 + 1.1150 + png_ptr->zstream.avail_out = 0; 1.1151 + png_ptr->zstream.next_out = NULL; 1.1152 + png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; 1.1153 + 1.1154 + png_ptr->zowner = 0; /* Release the stream */ 1.1155 + return; 1.1156 + } 1.1157 + 1.1158 + else 1.1159 + { 1.1160 + /* This is an error condition. */ 1.1161 + png_zstream_error(png_ptr, ret); 1.1162 + png_error(png_ptr, png_ptr->zstream.msg); 1.1163 + } 1.1164 + } 1.1165 +} 1.1166 + 1.1167 +/* Write an IEND chunk */ 1.1168 +void /* PRIVATE */ 1.1169 +png_write_IEND(png_structrp png_ptr) 1.1170 +{ 1.1171 + png_debug(1, "in png_write_IEND"); 1.1172 + 1.1173 + png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); 1.1174 + png_ptr->mode |= PNG_HAVE_IEND; 1.1175 +} 1.1176 + 1.1177 +#ifdef PNG_WRITE_gAMA_SUPPORTED 1.1178 +/* Write a gAMA chunk */ 1.1179 +void /* PRIVATE */ 1.1180 +png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) 1.1181 +{ 1.1182 + png_byte buf[4]; 1.1183 + 1.1184 + png_debug(1, "in png_write_gAMA"); 1.1185 + 1.1186 + /* file_gamma is saved in 1/100,000ths */ 1.1187 + png_save_uint_32(buf, (png_uint_32)file_gamma); 1.1188 + png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); 1.1189 +} 1.1190 +#endif 1.1191 + 1.1192 +#ifdef PNG_WRITE_sRGB_SUPPORTED 1.1193 +/* Write a sRGB chunk */ 1.1194 +void /* PRIVATE */ 1.1195 +png_write_sRGB(png_structrp png_ptr, int srgb_intent) 1.1196 +{ 1.1197 + png_byte buf[1]; 1.1198 + 1.1199 + png_debug(1, "in png_write_sRGB"); 1.1200 + 1.1201 + if (srgb_intent >= PNG_sRGB_INTENT_LAST) 1.1202 + png_warning(png_ptr, 1.1203 + "Invalid sRGB rendering intent specified"); 1.1204 + 1.1205 + buf[0]=(png_byte)srgb_intent; 1.1206 + png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); 1.1207 +} 1.1208 +#endif 1.1209 + 1.1210 +#ifdef PNG_WRITE_iCCP_SUPPORTED 1.1211 +/* Write an iCCP chunk */ 1.1212 +void /* PRIVATE */ 1.1213 +png_write_iCCP(png_structrp png_ptr, png_const_charp name, 1.1214 + png_const_bytep profile) 1.1215 +{ 1.1216 + png_uint_32 name_len; 1.1217 + png_uint_32 profile_len; 1.1218 + png_byte new_name[81]; /* 1 byte for the compression byte */ 1.1219 + compression_state comp; 1.1220 + 1.1221 + png_debug(1, "in png_write_iCCP"); 1.1222 + 1.1223 + /* These are all internal problems: the profile should have been checked 1.1224 + * before when it was stored. 1.1225 + */ 1.1226 + if (profile == NULL) 1.1227 + png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ 1.1228 + 1.1229 + profile_len = png_get_uint_32(profile); 1.1230 + 1.1231 + if (profile_len < 132) 1.1232 + png_error(png_ptr, "ICC profile too short"); 1.1233 + 1.1234 + if (profile_len & 0x03) 1.1235 + png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); 1.1236 + 1.1237 + { 1.1238 + png_uint_32 embedded_profile_len = png_get_uint_32(profile); 1.1239 + 1.1240 + if (profile_len != embedded_profile_len) 1.1241 + png_error(png_ptr, "Profile length does not match profile"); 1.1242 + } 1.1243 + 1.1244 + name_len = png_check_keyword(png_ptr, name, new_name); 1.1245 + 1.1246 + if (name_len == 0) 1.1247 + png_error(png_ptr, "iCCP: invalid keyword"); 1.1248 + 1.1249 + new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; 1.1250 + 1.1251 + /* Make sure we include the NULL after the name and the compression type */ 1.1252 + ++name_len; 1.1253 + 1.1254 + png_text_compress_init(&comp, profile, profile_len); 1.1255 + 1.1256 + /* Allow for keyword terminator and compression byte */ 1.1257 + if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) 1.1258 + png_error(png_ptr, png_ptr->zstream.msg); 1.1259 + 1.1260 + png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); 1.1261 + 1.1262 + png_write_chunk_data(png_ptr, new_name, name_len); 1.1263 + 1.1264 + png_write_compressed_data_out(png_ptr, &comp); 1.1265 + 1.1266 + png_write_chunk_end(png_ptr); 1.1267 +} 1.1268 +#endif 1.1269 + 1.1270 +#ifdef PNG_WRITE_sPLT_SUPPORTED 1.1271 +/* Write a sPLT chunk */ 1.1272 +void /* PRIVATE */ 1.1273 +png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) 1.1274 +{ 1.1275 + png_uint_32 name_len; 1.1276 + png_byte new_name[80]; 1.1277 + png_byte entrybuf[10]; 1.1278 + png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); 1.1279 + png_size_t palette_size = entry_size * spalette->nentries; 1.1280 + png_sPLT_entryp ep; 1.1281 +#ifndef PNG_POINTER_INDEXING_SUPPORTED 1.1282 + int i; 1.1283 +#endif 1.1284 + 1.1285 + png_debug(1, "in png_write_sPLT"); 1.1286 + 1.1287 + name_len = png_check_keyword(png_ptr, spalette->name, new_name); 1.1288 + 1.1289 + if (name_len == 0) 1.1290 + png_error(png_ptr, "sPLT: invalid keyword"); 1.1291 + 1.1292 + /* Make sure we include the NULL after the name */ 1.1293 + png_write_chunk_header(png_ptr, png_sPLT, 1.1294 + (png_uint_32)(name_len + 2 + palette_size)); 1.1295 + 1.1296 + png_write_chunk_data(png_ptr, (png_bytep)new_name, 1.1297 + (png_size_t)(name_len + 1)); 1.1298 + 1.1299 + png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); 1.1300 + 1.1301 + /* Loop through each palette entry, writing appropriately */ 1.1302 +#ifdef PNG_POINTER_INDEXING_SUPPORTED 1.1303 + for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) 1.1304 + { 1.1305 + if (spalette->depth == 8) 1.1306 + { 1.1307 + entrybuf[0] = (png_byte)ep->red; 1.1308 + entrybuf[1] = (png_byte)ep->green; 1.1309 + entrybuf[2] = (png_byte)ep->blue; 1.1310 + entrybuf[3] = (png_byte)ep->alpha; 1.1311 + png_save_uint_16(entrybuf + 4, ep->frequency); 1.1312 + } 1.1313 + 1.1314 + else 1.1315 + { 1.1316 + png_save_uint_16(entrybuf + 0, ep->red); 1.1317 + png_save_uint_16(entrybuf + 2, ep->green); 1.1318 + png_save_uint_16(entrybuf + 4, ep->blue); 1.1319 + png_save_uint_16(entrybuf + 6, ep->alpha); 1.1320 + png_save_uint_16(entrybuf + 8, ep->frequency); 1.1321 + } 1.1322 + 1.1323 + png_write_chunk_data(png_ptr, entrybuf, entry_size); 1.1324 + } 1.1325 +#else 1.1326 + ep=spalette->entries; 1.1327 + for (i = 0; i>spalette->nentries; i++) 1.1328 + { 1.1329 + if (spalette->depth == 8) 1.1330 + { 1.1331 + entrybuf[0] = (png_byte)ep[i].red; 1.1332 + entrybuf[1] = (png_byte)ep[i].green; 1.1333 + entrybuf[2] = (png_byte)ep[i].blue; 1.1334 + entrybuf[3] = (png_byte)ep[i].alpha; 1.1335 + png_save_uint_16(entrybuf + 4, ep[i].frequency); 1.1336 + } 1.1337 + 1.1338 + else 1.1339 + { 1.1340 + png_save_uint_16(entrybuf + 0, ep[i].red); 1.1341 + png_save_uint_16(entrybuf + 2, ep[i].green); 1.1342 + png_save_uint_16(entrybuf + 4, ep[i].blue); 1.1343 + png_save_uint_16(entrybuf + 6, ep[i].alpha); 1.1344 + png_save_uint_16(entrybuf + 8, ep[i].frequency); 1.1345 + } 1.1346 + 1.1347 + png_write_chunk_data(png_ptr, entrybuf, entry_size); 1.1348 + } 1.1349 +#endif 1.1350 + 1.1351 + png_write_chunk_end(png_ptr); 1.1352 +} 1.1353 +#endif 1.1354 + 1.1355 +#ifdef PNG_WRITE_sBIT_SUPPORTED 1.1356 +/* Write the sBIT chunk */ 1.1357 +void /* PRIVATE */ 1.1358 +png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) 1.1359 +{ 1.1360 + png_byte buf[4]; 1.1361 + png_size_t size; 1.1362 + 1.1363 + png_debug(1, "in png_write_sBIT"); 1.1364 + 1.1365 + /* Make sure we don't depend upon the order of PNG_COLOR_8 */ 1.1366 + if (color_type & PNG_COLOR_MASK_COLOR) 1.1367 + { 1.1368 + png_byte maxbits; 1.1369 + 1.1370 + maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : 1.1371 + png_ptr->usr_bit_depth); 1.1372 + 1.1373 + if (sbit->red == 0 || sbit->red > maxbits || 1.1374 + sbit->green == 0 || sbit->green > maxbits || 1.1375 + sbit->blue == 0 || sbit->blue > maxbits) 1.1376 + { 1.1377 + png_warning(png_ptr, "Invalid sBIT depth specified"); 1.1378 + return; 1.1379 + } 1.1380 + 1.1381 + buf[0] = sbit->red; 1.1382 + buf[1] = sbit->green; 1.1383 + buf[2] = sbit->blue; 1.1384 + size = 3; 1.1385 + } 1.1386 + 1.1387 + else 1.1388 + { 1.1389 + if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) 1.1390 + { 1.1391 + png_warning(png_ptr, "Invalid sBIT depth specified"); 1.1392 + return; 1.1393 + } 1.1394 + 1.1395 + buf[0] = sbit->gray; 1.1396 + size = 1; 1.1397 + } 1.1398 + 1.1399 + if (color_type & PNG_COLOR_MASK_ALPHA) 1.1400 + { 1.1401 + if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) 1.1402 + { 1.1403 + png_warning(png_ptr, "Invalid sBIT depth specified"); 1.1404 + return; 1.1405 + } 1.1406 + 1.1407 + buf[size++] = sbit->alpha; 1.1408 + } 1.1409 + 1.1410 + png_write_complete_chunk(png_ptr, png_sBIT, buf, size); 1.1411 +} 1.1412 +#endif 1.1413 + 1.1414 +#ifdef PNG_WRITE_cHRM_SUPPORTED 1.1415 +/* Write the cHRM chunk */ 1.1416 +void /* PRIVATE */ 1.1417 +png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) 1.1418 +{ 1.1419 + png_byte buf[32]; 1.1420 + 1.1421 + png_debug(1, "in png_write_cHRM"); 1.1422 + 1.1423 + /* Each value is saved in 1/100,000ths */ 1.1424 + png_save_int_32(buf, xy->whitex); 1.1425 + png_save_int_32(buf + 4, xy->whitey); 1.1426 + 1.1427 + png_save_int_32(buf + 8, xy->redx); 1.1428 + png_save_int_32(buf + 12, xy->redy); 1.1429 + 1.1430 + png_save_int_32(buf + 16, xy->greenx); 1.1431 + png_save_int_32(buf + 20, xy->greeny); 1.1432 + 1.1433 + png_save_int_32(buf + 24, xy->bluex); 1.1434 + png_save_int_32(buf + 28, xy->bluey); 1.1435 + 1.1436 + png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); 1.1437 +} 1.1438 +#endif 1.1439 + 1.1440 +#ifdef PNG_WRITE_tRNS_SUPPORTED 1.1441 +/* Write the tRNS chunk */ 1.1442 +void /* PRIVATE */ 1.1443 +png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, 1.1444 + png_const_color_16p tran, int num_trans, int color_type) 1.1445 +{ 1.1446 + png_byte buf[6]; 1.1447 + 1.1448 + png_debug(1, "in png_write_tRNS"); 1.1449 + 1.1450 + if (color_type == PNG_COLOR_TYPE_PALETTE) 1.1451 + { 1.1452 + if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) 1.1453 + { 1.1454 + png_app_warning(png_ptr, 1.1455 + "Invalid number of transparent colors specified"); 1.1456 + return; 1.1457 + } 1.1458 + 1.1459 + /* Write the chunk out as it is */ 1.1460 + png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, 1.1461 + (png_size_t)num_trans); 1.1462 + } 1.1463 + 1.1464 + else if (color_type == PNG_COLOR_TYPE_GRAY) 1.1465 + { 1.1466 + /* One 16 bit value */ 1.1467 + if (tran->gray >= (1 << png_ptr->bit_depth)) 1.1468 + { 1.1469 + png_app_warning(png_ptr, 1.1470 + "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); 1.1471 + 1.1472 + return; 1.1473 + } 1.1474 + 1.1475 + png_save_uint_16(buf, tran->gray); 1.1476 + png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); 1.1477 + } 1.1478 + 1.1479 + else if (color_type == PNG_COLOR_TYPE_RGB) 1.1480 + { 1.1481 + /* Three 16 bit values */ 1.1482 + png_save_uint_16(buf, tran->red); 1.1483 + png_save_uint_16(buf + 2, tran->green); 1.1484 + png_save_uint_16(buf + 4, tran->blue); 1.1485 +#ifdef PNG_WRITE_16BIT_SUPPORTED 1.1486 + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) 1.1487 +#else 1.1488 + if (buf[0] | buf[2] | buf[4]) 1.1489 +#endif 1.1490 + { 1.1491 + png_app_warning(png_ptr, 1.1492 + "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); 1.1493 + return; 1.1494 + } 1.1495 + 1.1496 + png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); 1.1497 + } 1.1498 + 1.1499 + else 1.1500 + { 1.1501 + png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); 1.1502 + } 1.1503 +} 1.1504 +#endif 1.1505 + 1.1506 +#ifdef PNG_WRITE_bKGD_SUPPORTED 1.1507 +/* Write the background chunk */ 1.1508 +void /* PRIVATE */ 1.1509 +png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) 1.1510 +{ 1.1511 + png_byte buf[6]; 1.1512 + 1.1513 + png_debug(1, "in png_write_bKGD"); 1.1514 + 1.1515 + if (color_type == PNG_COLOR_TYPE_PALETTE) 1.1516 + { 1.1517 + if ( 1.1518 +#ifdef PNG_MNG_FEATURES_SUPPORTED 1.1519 + (png_ptr->num_palette || 1.1520 + (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && 1.1521 +#endif 1.1522 + back->index >= png_ptr->num_palette) 1.1523 + { 1.1524 + png_warning(png_ptr, "Invalid background palette index"); 1.1525 + return; 1.1526 + } 1.1527 + 1.1528 + buf[0] = back->index; 1.1529 + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); 1.1530 + } 1.1531 + 1.1532 + else if (color_type & PNG_COLOR_MASK_COLOR) 1.1533 + { 1.1534 + png_save_uint_16(buf, back->red); 1.1535 + png_save_uint_16(buf + 2, back->green); 1.1536 + png_save_uint_16(buf + 4, back->blue); 1.1537 +#ifdef PNG_WRITE_16BIT_SUPPORTED 1.1538 + if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) 1.1539 +#else 1.1540 + if (buf[0] | buf[2] | buf[4]) 1.1541 +#endif 1.1542 + { 1.1543 + png_warning(png_ptr, 1.1544 + "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); 1.1545 + 1.1546 + return; 1.1547 + } 1.1548 + 1.1549 + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); 1.1550 + } 1.1551 + 1.1552 + else 1.1553 + { 1.1554 + if (back->gray >= (1 << png_ptr->bit_depth)) 1.1555 + { 1.1556 + png_warning(png_ptr, 1.1557 + "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); 1.1558 + 1.1559 + return; 1.1560 + } 1.1561 + 1.1562 + png_save_uint_16(buf, back->gray); 1.1563 + png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); 1.1564 + } 1.1565 +} 1.1566 +#endif 1.1567 + 1.1568 +#ifdef PNG_WRITE_hIST_SUPPORTED 1.1569 +/* Write the histogram */ 1.1570 +void /* PRIVATE */ 1.1571 +png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) 1.1572 +{ 1.1573 + int i; 1.1574 + png_byte buf[3]; 1.1575 + 1.1576 + png_debug(1, "in png_write_hIST"); 1.1577 + 1.1578 + if (num_hist > (int)png_ptr->num_palette) 1.1579 + { 1.1580 + png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, 1.1581 + png_ptr->num_palette); 1.1582 + 1.1583 + png_warning(png_ptr, "Invalid number of histogram entries specified"); 1.1584 + return; 1.1585 + } 1.1586 + 1.1587 + png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); 1.1588 + 1.1589 + for (i = 0; i < num_hist; i++) 1.1590 + { 1.1591 + png_save_uint_16(buf, hist[i]); 1.1592 + png_write_chunk_data(png_ptr, buf, (png_size_t)2); 1.1593 + } 1.1594 + 1.1595 + png_write_chunk_end(png_ptr); 1.1596 +} 1.1597 +#endif 1.1598 + 1.1599 +#ifdef PNG_WRITE_tEXt_SUPPORTED 1.1600 +/* Write a tEXt chunk */ 1.1601 +void /* PRIVATE */ 1.1602 +png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, 1.1603 + png_size_t text_len) 1.1604 +{ 1.1605 + png_uint_32 key_len; 1.1606 + png_byte new_key[80]; 1.1607 + 1.1608 + png_debug(1, "in png_write_tEXt"); 1.1609 + 1.1610 + key_len = png_check_keyword(png_ptr, key, new_key); 1.1611 + 1.1612 + if (key_len == 0) 1.1613 + png_error(png_ptr, "tEXt: invalid keyword"); 1.1614 + 1.1615 + if (text == NULL || *text == '\0') 1.1616 + text_len = 0; 1.1617 + 1.1618 + else 1.1619 + text_len = strlen(text); 1.1620 + 1.1621 + if (text_len > PNG_UINT_31_MAX - (key_len+1)) 1.1622 + png_error(png_ptr, "tEXt: text too long"); 1.1623 + 1.1624 + /* Make sure we include the 0 after the key */ 1.1625 + png_write_chunk_header(png_ptr, png_tEXt, 1.1626 + (png_uint_32)/*checked above*/(key_len + text_len + 1)); 1.1627 + /* 1.1628 + * We leave it to the application to meet PNG-1.0 requirements on the 1.1629 + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 1.1630 + * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. 1.1631 + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 1.1632 + */ 1.1633 + png_write_chunk_data(png_ptr, new_key, key_len + 1); 1.1634 + 1.1635 + if (text_len) 1.1636 + png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); 1.1637 + 1.1638 + png_write_chunk_end(png_ptr); 1.1639 +} 1.1640 +#endif 1.1641 + 1.1642 +#ifdef PNG_WRITE_zTXt_SUPPORTED 1.1643 +/* Write a compressed text chunk */ 1.1644 +void /* PRIVATE */ 1.1645 +png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, 1.1646 + png_size_t text_len, int compression) 1.1647 +{ 1.1648 + png_uint_32 key_len; 1.1649 + png_byte new_key[81]; 1.1650 + compression_state comp; 1.1651 + 1.1652 + png_debug(1, "in png_write_zTXt"); 1.1653 + PNG_UNUSED(text_len) /* Always use strlen */ 1.1654 + 1.1655 + if (compression == PNG_TEXT_COMPRESSION_NONE) 1.1656 + { 1.1657 + png_write_tEXt(png_ptr, key, text, 0); 1.1658 + return; 1.1659 + } 1.1660 + 1.1661 + if (compression != PNG_TEXT_COMPRESSION_zTXt) 1.1662 + png_error(png_ptr, "zTXt: invalid compression type"); 1.1663 + 1.1664 + key_len = png_check_keyword(png_ptr, key, new_key); 1.1665 + 1.1666 + if (key_len == 0) 1.1667 + png_error(png_ptr, "zTXt: invalid keyword"); 1.1668 + 1.1669 + /* Add the compression method and 1 for the keyword separator. */ 1.1670 + new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; 1.1671 + ++key_len; 1.1672 + 1.1673 + /* Compute the compressed data; do it now for the length */ 1.1674 + png_text_compress_init(&comp, (png_const_bytep)text, 1.1675 + text == NULL ? 0 : strlen(text)); 1.1676 + 1.1677 + if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) 1.1678 + png_error(png_ptr, png_ptr->zstream.msg); 1.1679 + 1.1680 + /* Write start of chunk */ 1.1681 + png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len); 1.1682 + 1.1683 + /* Write key */ 1.1684 + png_write_chunk_data(png_ptr, new_key, key_len); 1.1685 + 1.1686 + /* Write the compressed data */ 1.1687 + png_write_compressed_data_out(png_ptr, &comp); 1.1688 + 1.1689 + /* Close the chunk */ 1.1690 + png_write_chunk_end(png_ptr); 1.1691 +} 1.1692 +#endif 1.1693 + 1.1694 +#ifdef PNG_WRITE_iTXt_SUPPORTED 1.1695 +/* Write an iTXt chunk */ 1.1696 +void /* PRIVATE */ 1.1697 +png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, 1.1698 + png_const_charp lang, png_const_charp lang_key, png_const_charp text) 1.1699 +{ 1.1700 + png_uint_32 key_len, prefix_len; 1.1701 + png_size_t lang_len, lang_key_len; 1.1702 + png_byte new_key[82]; 1.1703 + compression_state comp; 1.1704 + 1.1705 + png_debug(1, "in png_write_iTXt"); 1.1706 + 1.1707 + key_len = png_check_keyword(png_ptr, key, new_key); 1.1708 + 1.1709 + if (key_len == 0) 1.1710 + png_error(png_ptr, "iTXt: invalid keyword"); 1.1711 + 1.1712 + /* Set the compression flag */ 1.1713 + switch (compression) 1.1714 + { 1.1715 + case PNG_ITXT_COMPRESSION_NONE: 1.1716 + case PNG_TEXT_COMPRESSION_NONE: 1.1717 + compression = new_key[++key_len] = 0; /* no compression */ 1.1718 + break; 1.1719 + 1.1720 + case PNG_TEXT_COMPRESSION_zTXt: 1.1721 + case PNG_ITXT_COMPRESSION_zTXt: 1.1722 + compression = new_key[++key_len] = 1; /* compressed */ 1.1723 + break; 1.1724 + 1.1725 + default: 1.1726 + png_error(png_ptr, "iTXt: invalid compression"); 1.1727 + } 1.1728 + 1.1729 + new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; 1.1730 + ++key_len; /* for the keywod separator */ 1.1731 + 1.1732 + /* We leave it to the application to meet PNG-1.0 requirements on the 1.1733 + * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 1.1734 + * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, 1.1735 + * specifies that the text is UTF-8 and this really doesn't require any 1.1736 + * checking. 1.1737 + * 1.1738 + * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 1.1739 + * 1.1740 + * TODO: validate the language tag correctly (see the spec.) 1.1741 + */ 1.1742 + if (lang == NULL) lang = ""; /* empty language is valid */ 1.1743 + lang_len = strlen(lang)+1; 1.1744 + if (lang_key == NULL) lang_key = ""; /* may be empty */ 1.1745 + lang_key_len = strlen(lang_key)+1; 1.1746 + if (text == NULL) text = ""; /* may be empty */ 1.1747 + 1.1748 + prefix_len = key_len; 1.1749 + if (lang_len > PNG_UINT_31_MAX-prefix_len) 1.1750 + prefix_len = PNG_UINT_31_MAX; 1.1751 + else 1.1752 + prefix_len = (png_uint_32)(prefix_len + lang_len); 1.1753 + 1.1754 + if (lang_key_len > PNG_UINT_31_MAX-prefix_len) 1.1755 + prefix_len = PNG_UINT_31_MAX; 1.1756 + else 1.1757 + prefix_len = (png_uint_32)(prefix_len + lang_key_len); 1.1758 + 1.1759 + png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); 1.1760 + 1.1761 + if (compression) 1.1762 + { 1.1763 + if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) 1.1764 + png_error(png_ptr, png_ptr->zstream.msg); 1.1765 + } 1.1766 + 1.1767 + else 1.1768 + { 1.1769 + if (comp.input_len > PNG_UINT_31_MAX-prefix_len) 1.1770 + png_error(png_ptr, "iTXt: uncompressed text too long"); 1.1771 + 1.1772 + /* So the string will fit in a chunk: */ 1.1773 + comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; 1.1774 + } 1.1775 + 1.1776 + png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); 1.1777 + 1.1778 + png_write_chunk_data(png_ptr, new_key, key_len); 1.1779 + 1.1780 + png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); 1.1781 + 1.1782 + png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); 1.1783 + 1.1784 + if (compression) 1.1785 + png_write_compressed_data_out(png_ptr, &comp); 1.1786 + 1.1787 + else 1.1788 + png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len); 1.1789 + 1.1790 + png_write_chunk_end(png_ptr); 1.1791 +} 1.1792 +#endif 1.1793 + 1.1794 +#ifdef PNG_WRITE_oFFs_SUPPORTED 1.1795 +/* Write the oFFs chunk */ 1.1796 +void /* PRIVATE */ 1.1797 +png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, 1.1798 + int unit_type) 1.1799 +{ 1.1800 + png_byte buf[9]; 1.1801 + 1.1802 + png_debug(1, "in png_write_oFFs"); 1.1803 + 1.1804 + if (unit_type >= PNG_OFFSET_LAST) 1.1805 + png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); 1.1806 + 1.1807 + png_save_int_32(buf, x_offset); 1.1808 + png_save_int_32(buf + 4, y_offset); 1.1809 + buf[8] = (png_byte)unit_type; 1.1810 + 1.1811 + png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); 1.1812 +} 1.1813 +#endif 1.1814 +#ifdef PNG_WRITE_pCAL_SUPPORTED 1.1815 +/* Write the pCAL chunk (described in the PNG extensions document) */ 1.1816 +void /* PRIVATE */ 1.1817 +png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, 1.1818 + png_int_32 X1, int type, int nparams, png_const_charp units, 1.1819 + png_charpp params) 1.1820 +{ 1.1821 + png_uint_32 purpose_len; 1.1822 + png_size_t units_len, total_len; 1.1823 + png_size_tp params_len; 1.1824 + png_byte buf[10]; 1.1825 + png_byte new_purpose[80]; 1.1826 + int i; 1.1827 + 1.1828 + png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); 1.1829 + 1.1830 + if (type >= PNG_EQUATION_LAST) 1.1831 + png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); 1.1832 + 1.1833 + purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); 1.1834 + 1.1835 + if (purpose_len == 0) 1.1836 + png_error(png_ptr, "pCAL: invalid keyword"); 1.1837 + 1.1838 + ++purpose_len; /* terminator */ 1.1839 + 1.1840 + png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); 1.1841 + units_len = strlen(units) + (nparams == 0 ? 0 : 1); 1.1842 + png_debug1(3, "pCAL units length = %d", (int)units_len); 1.1843 + total_len = purpose_len + units_len + 10; 1.1844 + 1.1845 + params_len = (png_size_tp)png_malloc(png_ptr, 1.1846 + (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); 1.1847 + 1.1848 + /* Find the length of each parameter, making sure we don't count the 1.1849 + * null terminator for the last parameter. 1.1850 + */ 1.1851 + for (i = 0; i < nparams; i++) 1.1852 + { 1.1853 + params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); 1.1854 + png_debug2(3, "pCAL parameter %d length = %lu", i, 1.1855 + (unsigned long)params_len[i]); 1.1856 + total_len += params_len[i]; 1.1857 + } 1.1858 + 1.1859 + png_debug1(3, "pCAL total length = %d", (int)total_len); 1.1860 + png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); 1.1861 + png_write_chunk_data(png_ptr, new_purpose, purpose_len); 1.1862 + png_save_int_32(buf, X0); 1.1863 + png_save_int_32(buf + 4, X1); 1.1864 + buf[8] = (png_byte)type; 1.1865 + buf[9] = (png_byte)nparams; 1.1866 + png_write_chunk_data(png_ptr, buf, (png_size_t)10); 1.1867 + png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); 1.1868 + 1.1869 + for (i = 0; i < nparams; i++) 1.1870 + { 1.1871 + png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); 1.1872 + } 1.1873 + 1.1874 + png_free(png_ptr, params_len); 1.1875 + png_write_chunk_end(png_ptr); 1.1876 +} 1.1877 +#endif 1.1878 + 1.1879 +#ifdef PNG_WRITE_sCAL_SUPPORTED 1.1880 +/* Write the sCAL chunk */ 1.1881 +void /* PRIVATE */ 1.1882 +png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, 1.1883 + png_const_charp height) 1.1884 +{ 1.1885 + png_byte buf[64]; 1.1886 + png_size_t wlen, hlen, total_len; 1.1887 + 1.1888 + png_debug(1, "in png_write_sCAL_s"); 1.1889 + 1.1890 + wlen = strlen(width); 1.1891 + hlen = strlen(height); 1.1892 + total_len = wlen + hlen + 2; 1.1893 + 1.1894 + if (total_len > 64) 1.1895 + { 1.1896 + png_warning(png_ptr, "Can't write sCAL (buffer too small)"); 1.1897 + return; 1.1898 + } 1.1899 + 1.1900 + buf[0] = (png_byte)unit; 1.1901 + memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ 1.1902 + memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ 1.1903 + 1.1904 + png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); 1.1905 + png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len); 1.1906 +} 1.1907 +#endif 1.1908 + 1.1909 +#ifdef PNG_WRITE_pHYs_SUPPORTED 1.1910 +/* Write the pHYs chunk */ 1.1911 +void /* PRIVATE */ 1.1912 +png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, 1.1913 + png_uint_32 y_pixels_per_unit, 1.1914 + int unit_type) 1.1915 +{ 1.1916 + png_byte buf[9]; 1.1917 + 1.1918 + png_debug(1, "in png_write_pHYs"); 1.1919 + 1.1920 + if (unit_type >= PNG_RESOLUTION_LAST) 1.1921 + png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); 1.1922 + 1.1923 + png_save_uint_32(buf, x_pixels_per_unit); 1.1924 + png_save_uint_32(buf + 4, y_pixels_per_unit); 1.1925 + buf[8] = (png_byte)unit_type; 1.1926 + 1.1927 + png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); 1.1928 +} 1.1929 +#endif 1.1930 + 1.1931 +#ifdef PNG_WRITE_tIME_SUPPORTED 1.1932 +/* Write the tIME chunk. Use either png_convert_from_struct_tm() 1.1933 + * or png_convert_from_time_t(), or fill in the structure yourself. 1.1934 + */ 1.1935 +void /* PRIVATE */ 1.1936 +png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) 1.1937 +{ 1.1938 + png_byte buf[7]; 1.1939 + 1.1940 + png_debug(1, "in png_write_tIME"); 1.1941 + 1.1942 + if (mod_time->month > 12 || mod_time->month < 1 || 1.1943 + mod_time->day > 31 || mod_time->day < 1 || 1.1944 + mod_time->hour > 23 || mod_time->second > 60) 1.1945 + { 1.1946 + png_warning(png_ptr, "Invalid time specified for tIME chunk"); 1.1947 + return; 1.1948 + } 1.1949 + 1.1950 + png_save_uint_16(buf, mod_time->year); 1.1951 + buf[2] = mod_time->month; 1.1952 + buf[3] = mod_time->day; 1.1953 + buf[4] = mod_time->hour; 1.1954 + buf[5] = mod_time->minute; 1.1955 + buf[6] = mod_time->second; 1.1956 + 1.1957 + png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); 1.1958 +} 1.1959 +#endif 1.1960 + 1.1961 +#ifdef PNG_WRITE_APNG_SUPPORTED 1.1962 +void /* PRIVATE */ 1.1963 +png_write_acTL(png_structp png_ptr, 1.1964 + png_uint_32 num_frames, png_uint_32 num_plays) 1.1965 +{ 1.1966 + png_byte buf[8]; 1.1967 + 1.1968 + png_debug(1, "in png_write_acTL"); 1.1969 + 1.1970 + png_ptr->num_frames_to_write = num_frames; 1.1971 + 1.1972 + if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) 1.1973 + num_frames--; 1.1974 + 1.1975 + png_save_uint_32(buf, num_frames); 1.1976 + png_save_uint_32(buf + 4, num_plays); 1.1977 + 1.1978 + png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8); 1.1979 +} 1.1980 + 1.1981 +void /* PRIVATE */ 1.1982 +png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, 1.1983 + png_uint_32 x_offset, png_uint_32 y_offset, 1.1984 + png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, 1.1985 + png_byte blend_op) 1.1986 +{ 1.1987 + png_byte buf[26]; 1.1988 + 1.1989 + png_debug(1, "in png_write_fcTL"); 1.1990 + 1.1991 + if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) 1.1992 + png_error(png_ptr, "x and/or y offset for the first frame aren't 0"); 1.1993 + if (png_ptr->num_frames_written == 0 && 1.1994 + (width != png_ptr->first_frame_width || 1.1995 + height != png_ptr->first_frame_height)) 1.1996 + png_error(png_ptr, "width and/or height in the first frame's fcTL " 1.1997 + "don't match the ones in IHDR"); 1.1998 + 1.1999 + /* more error checking */ 1.2000 + png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, 1.2001 + delay_num, delay_den, dispose_op, blend_op); 1.2002 + 1.2003 + png_save_uint_32(buf, png_ptr->next_seq_num); 1.2004 + png_save_uint_32(buf + 4, width); 1.2005 + png_save_uint_32(buf + 8, height); 1.2006 + png_save_uint_32(buf + 12, x_offset); 1.2007 + png_save_uint_32(buf + 16, y_offset); 1.2008 + png_save_uint_16(buf + 20, delay_num); 1.2009 + png_save_uint_16(buf + 22, delay_den); 1.2010 + buf[24] = dispose_op; 1.2011 + buf[25] = blend_op; 1.2012 + 1.2013 + png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26); 1.2014 + 1.2015 + png_ptr->next_seq_num++; 1.2016 +} 1.2017 + 1.2018 +void /* PRIVATE */ 1.2019 +png_write_fdAT(png_structp png_ptr, 1.2020 + png_const_bytep data, png_size_t length) 1.2021 +{ 1.2022 + png_byte buf[4]; 1.2023 + 1.2024 + png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length)); 1.2025 + 1.2026 + png_save_uint_32(buf, png_ptr->next_seq_num); 1.2027 + png_write_chunk_data(png_ptr, buf, 4); 1.2028 + 1.2029 + png_write_chunk_data(png_ptr, data, length); 1.2030 + 1.2031 + png_write_chunk_end(png_ptr); 1.2032 + 1.2033 + png_ptr->next_seq_num++; 1.2034 +} 1.2035 +#endif /* PNG_WRITE_APNG_SUPPORTED */ 1.2036 + 1.2037 +/* Initializes the row writing capability of libpng */ 1.2038 +void /* PRIVATE */ 1.2039 +png_write_start_row(png_structrp png_ptr) 1.2040 +{ 1.2041 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1.2042 + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1.2043 + 1.2044 + /* Start of interlace block */ 1.2045 + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1.2046 + 1.2047 + /* Offset to next interlace block */ 1.2048 + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1.2049 + 1.2050 + /* Start of interlace block in the y direction */ 1.2051 + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 1.2052 + 1.2053 + /* Offset to next interlace block in the y direction */ 1.2054 + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 1.2055 +#endif 1.2056 + 1.2057 + png_alloc_size_t buf_size; 1.2058 + int usr_pixel_depth; 1.2059 + 1.2060 + png_debug(1, "in png_write_start_row"); 1.2061 + 1.2062 + usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; 1.2063 + buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; 1.2064 + 1.2065 + /* 1.5.6: added to allow checking in the row write code. */ 1.2066 + png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; 1.2067 + png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; 1.2068 + 1.2069 + /* Set up row buffer */ 1.2070 + png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size); 1.2071 + 1.2072 + png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; 1.2073 + 1.2074 +#ifdef PNG_WRITE_FILTER_SUPPORTED 1.2075 + /* Set up filtering buffer, if using this filter */ 1.2076 + if (png_ptr->do_filter & PNG_FILTER_SUB) 1.2077 + { 1.2078 + png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); 1.2079 + 1.2080 + png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; 1.2081 + } 1.2082 + 1.2083 + /* We only need to keep the previous row if we are using one of these. */ 1.2084 + if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) 1.2085 + { 1.2086 + /* Set up previous row buffer */ 1.2087 + png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size); 1.2088 + 1.2089 + if (png_ptr->do_filter & PNG_FILTER_UP) 1.2090 + { 1.2091 + png_ptr->up_row = (png_bytep)png_malloc(png_ptr, 1.2092 + png_ptr->rowbytes + 1); 1.2093 + 1.2094 + png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; 1.2095 + } 1.2096 + 1.2097 + if (png_ptr->do_filter & PNG_FILTER_AVG) 1.2098 + { 1.2099 + png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, 1.2100 + png_ptr->rowbytes + 1); 1.2101 + 1.2102 + png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; 1.2103 + } 1.2104 + 1.2105 + if (png_ptr->do_filter & PNG_FILTER_PAETH) 1.2106 + { 1.2107 + png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, 1.2108 + png_ptr->rowbytes + 1); 1.2109 + 1.2110 + png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; 1.2111 + } 1.2112 + } 1.2113 +#endif /* PNG_WRITE_FILTER_SUPPORTED */ 1.2114 + 1.2115 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1.2116 + /* If interlaced, we need to set up width and height of pass */ 1.2117 + if (png_ptr->interlaced) 1.2118 + { 1.2119 + if (!(png_ptr->transformations & PNG_INTERLACE)) 1.2120 + { 1.2121 + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - 1.2122 + png_pass_ystart[0]) / png_pass_yinc[0]; 1.2123 + 1.2124 + png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - 1.2125 + png_pass_start[0]) / png_pass_inc[0]; 1.2126 + } 1.2127 + 1.2128 + else 1.2129 + { 1.2130 + png_ptr->num_rows = png_ptr->height; 1.2131 + png_ptr->usr_width = png_ptr->width; 1.2132 + } 1.2133 + } 1.2134 + 1.2135 + else 1.2136 +#endif 1.2137 + { 1.2138 + png_ptr->num_rows = png_ptr->height; 1.2139 + png_ptr->usr_width = png_ptr->width; 1.2140 + } 1.2141 +} 1.2142 + 1.2143 +/* Internal use only. Called when finished processing a row of data. */ 1.2144 +void /* PRIVATE */ 1.2145 +png_write_finish_row(png_structrp png_ptr) 1.2146 +{ 1.2147 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1.2148 + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1.2149 + 1.2150 + /* Start of interlace block */ 1.2151 + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1.2152 + 1.2153 + /* Offset to next interlace block */ 1.2154 + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1.2155 + 1.2156 + /* Start of interlace block in the y direction */ 1.2157 + static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 1.2158 + 1.2159 + /* Offset to next interlace block in the y direction */ 1.2160 + static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 1.2161 +#endif 1.2162 + 1.2163 + png_debug(1, "in png_write_finish_row"); 1.2164 + 1.2165 + /* Next row */ 1.2166 + png_ptr->row_number++; 1.2167 + 1.2168 + /* See if we are done */ 1.2169 + if (png_ptr->row_number < png_ptr->num_rows) 1.2170 + return; 1.2171 + 1.2172 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1.2173 + /* If interlaced, go to next pass */ 1.2174 + if (png_ptr->interlaced) 1.2175 + { 1.2176 + png_ptr->row_number = 0; 1.2177 + if (png_ptr->transformations & PNG_INTERLACE) 1.2178 + { 1.2179 + png_ptr->pass++; 1.2180 + } 1.2181 + 1.2182 + else 1.2183 + { 1.2184 + /* Loop until we find a non-zero width or height pass */ 1.2185 + do 1.2186 + { 1.2187 + png_ptr->pass++; 1.2188 + 1.2189 + if (png_ptr->pass >= 7) 1.2190 + break; 1.2191 + 1.2192 + png_ptr->usr_width = (png_ptr->width + 1.2193 + png_pass_inc[png_ptr->pass] - 1 - 1.2194 + png_pass_start[png_ptr->pass]) / 1.2195 + png_pass_inc[png_ptr->pass]; 1.2196 + 1.2197 + png_ptr->num_rows = (png_ptr->height + 1.2198 + png_pass_yinc[png_ptr->pass] - 1 - 1.2199 + png_pass_ystart[png_ptr->pass]) / 1.2200 + png_pass_yinc[png_ptr->pass]; 1.2201 + 1.2202 + if (png_ptr->transformations & PNG_INTERLACE) 1.2203 + break; 1.2204 + 1.2205 + } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); 1.2206 + 1.2207 + } 1.2208 + 1.2209 + /* Reset the row above the image for the next pass */ 1.2210 + if (png_ptr->pass < 7) 1.2211 + { 1.2212 + if (png_ptr->prev_row != NULL) 1.2213 + memset(png_ptr->prev_row, 0, 1.2214 + (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* 1.2215 + png_ptr->usr_bit_depth, png_ptr->width)) + 1); 1.2216 + 1.2217 + return; 1.2218 + } 1.2219 + } 1.2220 +#endif 1.2221 + 1.2222 + /* If we get here, we've just written the last row, so we need 1.2223 + to flush the compressor */ 1.2224 + png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); 1.2225 +} 1.2226 + 1.2227 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1.2228 +/* Pick out the correct pixels for the interlace pass. 1.2229 + * The basic idea here is to go through the row with a source 1.2230 + * pointer and a destination pointer (sp and dp), and copy the 1.2231 + * correct pixels for the pass. As the row gets compacted, 1.2232 + * sp will always be >= dp, so we should never overwrite anything. 1.2233 + * See the default: case for the easiest code to understand. 1.2234 + */ 1.2235 +void /* PRIVATE */ 1.2236 +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) 1.2237 +{ 1.2238 + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1.2239 + 1.2240 + /* Start of interlace block */ 1.2241 + static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1.2242 + 1.2243 + /* Offset to next interlace block */ 1.2244 + static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1.2245 + 1.2246 + png_debug(1, "in png_do_write_interlace"); 1.2247 + 1.2248 + /* We don't have to do anything on the last pass (6) */ 1.2249 + if (pass < 6) 1.2250 + { 1.2251 + /* Each pixel depth is handled separately */ 1.2252 + switch (row_info->pixel_depth) 1.2253 + { 1.2254 + case 1: 1.2255 + { 1.2256 + png_bytep sp; 1.2257 + png_bytep dp; 1.2258 + int shift; 1.2259 + int d; 1.2260 + int value; 1.2261 + png_uint_32 i; 1.2262 + png_uint_32 row_width = row_info->width; 1.2263 + 1.2264 + dp = row; 1.2265 + d = 0; 1.2266 + shift = 7; 1.2267 + 1.2268 + for (i = png_pass_start[pass]; i < row_width; 1.2269 + i += png_pass_inc[pass]) 1.2270 + { 1.2271 + sp = row + (png_size_t)(i >> 3); 1.2272 + value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; 1.2273 + d |= (value << shift); 1.2274 + 1.2275 + if (shift == 0) 1.2276 + { 1.2277 + shift = 7; 1.2278 + *dp++ = (png_byte)d; 1.2279 + d = 0; 1.2280 + } 1.2281 + 1.2282 + else 1.2283 + shift--; 1.2284 + 1.2285 + } 1.2286 + if (shift != 7) 1.2287 + *dp = (png_byte)d; 1.2288 + 1.2289 + break; 1.2290 + } 1.2291 + 1.2292 + case 2: 1.2293 + { 1.2294 + png_bytep sp; 1.2295 + png_bytep dp; 1.2296 + int shift; 1.2297 + int d; 1.2298 + int value; 1.2299 + png_uint_32 i; 1.2300 + png_uint_32 row_width = row_info->width; 1.2301 + 1.2302 + dp = row; 1.2303 + shift = 6; 1.2304 + d = 0; 1.2305 + 1.2306 + for (i = png_pass_start[pass]; i < row_width; 1.2307 + i += png_pass_inc[pass]) 1.2308 + { 1.2309 + sp = row + (png_size_t)(i >> 2); 1.2310 + value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; 1.2311 + d |= (value << shift); 1.2312 + 1.2313 + if (shift == 0) 1.2314 + { 1.2315 + shift = 6; 1.2316 + *dp++ = (png_byte)d; 1.2317 + d = 0; 1.2318 + } 1.2319 + 1.2320 + else 1.2321 + shift -= 2; 1.2322 + } 1.2323 + if (shift != 6) 1.2324 + *dp = (png_byte)d; 1.2325 + 1.2326 + break; 1.2327 + } 1.2328 + 1.2329 + case 4: 1.2330 + { 1.2331 + png_bytep sp; 1.2332 + png_bytep dp; 1.2333 + int shift; 1.2334 + int d; 1.2335 + int value; 1.2336 + png_uint_32 i; 1.2337 + png_uint_32 row_width = row_info->width; 1.2338 + 1.2339 + dp = row; 1.2340 + shift = 4; 1.2341 + d = 0; 1.2342 + for (i = png_pass_start[pass]; i < row_width; 1.2343 + i += png_pass_inc[pass]) 1.2344 + { 1.2345 + sp = row + (png_size_t)(i >> 1); 1.2346 + value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; 1.2347 + d |= (value << shift); 1.2348 + 1.2349 + if (shift == 0) 1.2350 + { 1.2351 + shift = 4; 1.2352 + *dp++ = (png_byte)d; 1.2353 + d = 0; 1.2354 + } 1.2355 + 1.2356 + else 1.2357 + shift -= 4; 1.2358 + } 1.2359 + if (shift != 4) 1.2360 + *dp = (png_byte)d; 1.2361 + 1.2362 + break; 1.2363 + } 1.2364 + 1.2365 + default: 1.2366 + { 1.2367 + png_bytep sp; 1.2368 + png_bytep dp; 1.2369 + png_uint_32 i; 1.2370 + png_uint_32 row_width = row_info->width; 1.2371 + png_size_t pixel_bytes; 1.2372 + 1.2373 + /* Start at the beginning */ 1.2374 + dp = row; 1.2375 + 1.2376 + /* Find out how many bytes each pixel takes up */ 1.2377 + pixel_bytes = (row_info->pixel_depth >> 3); 1.2378 + 1.2379 + /* Loop through the row, only looking at the pixels that matter */ 1.2380 + for (i = png_pass_start[pass]; i < row_width; 1.2381 + i += png_pass_inc[pass]) 1.2382 + { 1.2383 + /* Find out where the original pixel is */ 1.2384 + sp = row + (png_size_t)i * pixel_bytes; 1.2385 + 1.2386 + /* Move the pixel */ 1.2387 + if (dp != sp) 1.2388 + memcpy(dp, sp, pixel_bytes); 1.2389 + 1.2390 + /* Next pixel */ 1.2391 + dp += pixel_bytes; 1.2392 + } 1.2393 + break; 1.2394 + } 1.2395 + } 1.2396 + /* Set new row width */ 1.2397 + row_info->width = (row_info->width + 1.2398 + png_pass_inc[pass] - 1 - 1.2399 + png_pass_start[pass]) / 1.2400 + png_pass_inc[pass]; 1.2401 + 1.2402 + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 1.2403 + row_info->width); 1.2404 + } 1.2405 +} 1.2406 +#endif 1.2407 + 1.2408 +/* This filters the row, chooses which filter to use, if it has not already 1.2409 + * been specified by the application, and then writes the row out with the 1.2410 + * chosen filter. 1.2411 + */ 1.2412 +static void 1.2413 +png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, 1.2414 + png_size_t row_bytes); 1.2415 + 1.2416 +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) 1.2417 +#define PNG_HISHIFT 10 1.2418 +#define PNG_LOMASK ((png_uint_32)0xffffL) 1.2419 +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) 1.2420 +void /* PRIVATE */ 1.2421 +png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) 1.2422 +{ 1.2423 + png_bytep best_row; 1.2424 +#ifdef PNG_WRITE_FILTER_SUPPORTED 1.2425 + png_bytep prev_row, row_buf; 1.2426 + png_uint_32 mins, bpp; 1.2427 + png_byte filter_to_do = png_ptr->do_filter; 1.2428 + png_size_t row_bytes = row_info->rowbytes; 1.2429 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2430 + int num_p_filters = png_ptr->num_prev_filters; 1.2431 +#endif 1.2432 + 1.2433 + png_debug(1, "in png_write_find_filter"); 1.2434 + 1.2435 +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2436 + if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) 1.2437 + { 1.2438 + /* These will never be selected so we need not test them. */ 1.2439 + filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); 1.2440 + } 1.2441 +#endif 1.2442 + 1.2443 + /* Find out how many bytes offset each pixel is */ 1.2444 + bpp = (row_info->pixel_depth + 7) >> 3; 1.2445 + 1.2446 + prev_row = png_ptr->prev_row; 1.2447 +#endif 1.2448 + best_row = png_ptr->row_buf; 1.2449 +#ifdef PNG_WRITE_FILTER_SUPPORTED 1.2450 + row_buf = best_row; 1.2451 + mins = PNG_MAXSUM; 1.2452 + 1.2453 + /* The prediction method we use is to find which method provides the 1.2454 + * smallest value when summing the absolute values of the distances 1.2455 + * from zero, using anything >= 128 as negative numbers. This is known 1.2456 + * as the "minimum sum of absolute differences" heuristic. Other 1.2457 + * heuristics are the "weighted minimum sum of absolute differences" 1.2458 + * (experimental and can in theory improve compression), and the "zlib 1.2459 + * predictive" method (not implemented yet), which does test compressions 1.2460 + * of lines using different filter methods, and then chooses the 1.2461 + * (series of) filter(s) that give minimum compressed data size (VERY 1.2462 + * computationally expensive). 1.2463 + * 1.2464 + * GRR 980525: consider also 1.2465 + * 1.2466 + * (1) minimum sum of absolute differences from running average (i.e., 1.2467 + * keep running sum of non-absolute differences & count of bytes) 1.2468 + * [track dispersion, too? restart average if dispersion too large?] 1.2469 + * 1.2470 + * (1b) minimum sum of absolute differences from sliding average, probably 1.2471 + * with window size <= deflate window (usually 32K) 1.2472 + * 1.2473 + * (2) minimum sum of squared differences from zero or running average 1.2474 + * (i.e., ~ root-mean-square approach) 1.2475 + */ 1.2476 + 1.2477 + 1.2478 + /* We don't need to test the 'no filter' case if this is the only filter 1.2479 + * that has been chosen, as it doesn't actually do anything to the data. 1.2480 + */ 1.2481 + if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE) 1.2482 + { 1.2483 + png_bytep rp; 1.2484 + png_uint_32 sum = 0; 1.2485 + png_size_t i; 1.2486 + int v; 1.2487 + 1.2488 + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) 1.2489 + { 1.2490 + v = *rp; 1.2491 + sum += (v < 128) ? v : 256 - v; 1.2492 + } 1.2493 + 1.2494 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2495 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2496 + { 1.2497 + png_uint_32 sumhi, sumlo; 1.2498 + int j; 1.2499 + sumlo = sum & PNG_LOMASK; 1.2500 + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ 1.2501 + 1.2502 + /* Reduce the sum if we match any of the previous rows */ 1.2503 + for (j = 0; j < num_p_filters; j++) 1.2504 + { 1.2505 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) 1.2506 + { 1.2507 + sumlo = (sumlo * png_ptr->filter_weights[j]) >> 1.2508 + PNG_WEIGHT_SHIFT; 1.2509 + 1.2510 + sumhi = (sumhi * png_ptr->filter_weights[j]) >> 1.2511 + PNG_WEIGHT_SHIFT; 1.2512 + } 1.2513 + } 1.2514 + 1.2515 + /* Factor in the cost of this filter (this is here for completeness, 1.2516 + * but it makes no sense to have a "cost" for the NONE filter, as 1.2517 + * it has the minimum possible computational cost - none). 1.2518 + */ 1.2519 + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> 1.2520 + PNG_COST_SHIFT; 1.2521 + 1.2522 + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> 1.2523 + PNG_COST_SHIFT; 1.2524 + 1.2525 + if (sumhi > PNG_HIMASK) 1.2526 + sum = PNG_MAXSUM; 1.2527 + 1.2528 + else 1.2529 + sum = (sumhi << PNG_HISHIFT) + sumlo; 1.2530 + } 1.2531 +#endif 1.2532 + mins = sum; 1.2533 + } 1.2534 + 1.2535 + /* Sub filter */ 1.2536 + if (filter_to_do == PNG_FILTER_SUB) 1.2537 + /* It's the only filter so no testing is needed */ 1.2538 + { 1.2539 + png_bytep rp, lp, dp; 1.2540 + png_size_t i; 1.2541 + 1.2542 + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; 1.2543 + i++, rp++, dp++) 1.2544 + { 1.2545 + *dp = *rp; 1.2546 + } 1.2547 + 1.2548 + for (lp = row_buf + 1; i < row_bytes; 1.2549 + i++, rp++, lp++, dp++) 1.2550 + { 1.2551 + *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 1.2552 + } 1.2553 + 1.2554 + best_row = png_ptr->sub_row; 1.2555 + } 1.2556 + 1.2557 + else if (filter_to_do & PNG_FILTER_SUB) 1.2558 + { 1.2559 + png_bytep rp, dp, lp; 1.2560 + png_uint_32 sum = 0, lmins = mins; 1.2561 + png_size_t i; 1.2562 + int v; 1.2563 + 1.2564 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2565 + /* We temporarily increase the "minimum sum" by the factor we 1.2566 + * would reduce the sum of this filter, so that we can do the 1.2567 + * early exit comparison without scaling the sum each time. 1.2568 + */ 1.2569 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2570 + { 1.2571 + int j; 1.2572 + png_uint_32 lmhi, lmlo; 1.2573 + lmlo = lmins & PNG_LOMASK; 1.2574 + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 1.2575 + 1.2576 + for (j = 0; j < num_p_filters; j++) 1.2577 + { 1.2578 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) 1.2579 + { 1.2580 + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 1.2581 + PNG_WEIGHT_SHIFT; 1.2582 + 1.2583 + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 1.2584 + PNG_WEIGHT_SHIFT; 1.2585 + } 1.2586 + } 1.2587 + 1.2588 + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 1.2589 + PNG_COST_SHIFT; 1.2590 + 1.2591 + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 1.2592 + PNG_COST_SHIFT; 1.2593 + 1.2594 + if (lmhi > PNG_HIMASK) 1.2595 + lmins = PNG_MAXSUM; 1.2596 + 1.2597 + else 1.2598 + lmins = (lmhi << PNG_HISHIFT) + lmlo; 1.2599 + } 1.2600 +#endif 1.2601 + 1.2602 + for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; 1.2603 + i++, rp++, dp++) 1.2604 + { 1.2605 + v = *dp = *rp; 1.2606 + 1.2607 + sum += (v < 128) ? v : 256 - v; 1.2608 + } 1.2609 + 1.2610 + for (lp = row_buf + 1; i < row_bytes; 1.2611 + i++, rp++, lp++, dp++) 1.2612 + { 1.2613 + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 1.2614 + 1.2615 + sum += (v < 128) ? v : 256 - v; 1.2616 + 1.2617 + if (sum > lmins) /* We are already worse, don't continue. */ 1.2618 + break; 1.2619 + } 1.2620 + 1.2621 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2622 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2623 + { 1.2624 + int j; 1.2625 + png_uint_32 sumhi, sumlo; 1.2626 + sumlo = sum & PNG_LOMASK; 1.2627 + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 1.2628 + 1.2629 + for (j = 0; j < num_p_filters; j++) 1.2630 + { 1.2631 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) 1.2632 + { 1.2633 + sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> 1.2634 + PNG_WEIGHT_SHIFT; 1.2635 + 1.2636 + sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> 1.2637 + PNG_WEIGHT_SHIFT; 1.2638 + } 1.2639 + } 1.2640 + 1.2641 + sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 1.2642 + PNG_COST_SHIFT; 1.2643 + 1.2644 + sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 1.2645 + PNG_COST_SHIFT; 1.2646 + 1.2647 + if (sumhi > PNG_HIMASK) 1.2648 + sum = PNG_MAXSUM; 1.2649 + 1.2650 + else 1.2651 + sum = (sumhi << PNG_HISHIFT) + sumlo; 1.2652 + } 1.2653 +#endif 1.2654 + 1.2655 + if (sum < mins) 1.2656 + { 1.2657 + mins = sum; 1.2658 + best_row = png_ptr->sub_row; 1.2659 + } 1.2660 + } 1.2661 + 1.2662 + /* Up filter */ 1.2663 + if (filter_to_do == PNG_FILTER_UP) 1.2664 + { 1.2665 + png_bytep rp, dp, pp; 1.2666 + png_size_t i; 1.2667 + 1.2668 + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, 1.2669 + pp = prev_row + 1; i < row_bytes; 1.2670 + i++, rp++, pp++, dp++) 1.2671 + { 1.2672 + *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); 1.2673 + } 1.2674 + 1.2675 + best_row = png_ptr->up_row; 1.2676 + } 1.2677 + 1.2678 + else if (filter_to_do & PNG_FILTER_UP) 1.2679 + { 1.2680 + png_bytep rp, dp, pp; 1.2681 + png_uint_32 sum = 0, lmins = mins; 1.2682 + png_size_t i; 1.2683 + int v; 1.2684 + 1.2685 + 1.2686 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2687 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2688 + { 1.2689 + int j; 1.2690 + png_uint_32 lmhi, lmlo; 1.2691 + lmlo = lmins & PNG_LOMASK; 1.2692 + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 1.2693 + 1.2694 + for (j = 0; j < num_p_filters; j++) 1.2695 + { 1.2696 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) 1.2697 + { 1.2698 + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 1.2699 + PNG_WEIGHT_SHIFT; 1.2700 + 1.2701 + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 1.2702 + PNG_WEIGHT_SHIFT; 1.2703 + } 1.2704 + } 1.2705 + 1.2706 + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> 1.2707 + PNG_COST_SHIFT; 1.2708 + 1.2709 + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> 1.2710 + PNG_COST_SHIFT; 1.2711 + 1.2712 + if (lmhi > PNG_HIMASK) 1.2713 + lmins = PNG_MAXSUM; 1.2714 + 1.2715 + else 1.2716 + lmins = (lmhi << PNG_HISHIFT) + lmlo; 1.2717 + } 1.2718 +#endif 1.2719 + 1.2720 + for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, 1.2721 + pp = prev_row + 1; i < row_bytes; i++) 1.2722 + { 1.2723 + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 1.2724 + 1.2725 + sum += (v < 128) ? v : 256 - v; 1.2726 + 1.2727 + if (sum > lmins) /* We are already worse, don't continue. */ 1.2728 + break; 1.2729 + } 1.2730 + 1.2731 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2732 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2733 + { 1.2734 + int j; 1.2735 + png_uint_32 sumhi, sumlo; 1.2736 + sumlo = sum & PNG_LOMASK; 1.2737 + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 1.2738 + 1.2739 + for (j = 0; j < num_p_filters; j++) 1.2740 + { 1.2741 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) 1.2742 + { 1.2743 + sumlo = (sumlo * png_ptr->filter_weights[j]) >> 1.2744 + PNG_WEIGHT_SHIFT; 1.2745 + 1.2746 + sumhi = (sumhi * png_ptr->filter_weights[j]) >> 1.2747 + PNG_WEIGHT_SHIFT; 1.2748 + } 1.2749 + } 1.2750 + 1.2751 + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> 1.2752 + PNG_COST_SHIFT; 1.2753 + 1.2754 + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> 1.2755 + PNG_COST_SHIFT; 1.2756 + 1.2757 + if (sumhi > PNG_HIMASK) 1.2758 + sum = PNG_MAXSUM; 1.2759 + 1.2760 + else 1.2761 + sum = (sumhi << PNG_HISHIFT) + sumlo; 1.2762 + } 1.2763 +#endif 1.2764 + 1.2765 + if (sum < mins) 1.2766 + { 1.2767 + mins = sum; 1.2768 + best_row = png_ptr->up_row; 1.2769 + } 1.2770 + } 1.2771 + 1.2772 + /* Avg filter */ 1.2773 + if (filter_to_do == PNG_FILTER_AVG) 1.2774 + { 1.2775 + png_bytep rp, dp, pp, lp; 1.2776 + png_uint_32 i; 1.2777 + 1.2778 + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, 1.2779 + pp = prev_row + 1; i < bpp; i++) 1.2780 + { 1.2781 + *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 1.2782 + } 1.2783 + 1.2784 + for (lp = row_buf + 1; i < row_bytes; i++) 1.2785 + { 1.2786 + *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) 1.2787 + & 0xff); 1.2788 + } 1.2789 + best_row = png_ptr->avg_row; 1.2790 + } 1.2791 + 1.2792 + else if (filter_to_do & PNG_FILTER_AVG) 1.2793 + { 1.2794 + png_bytep rp, dp, pp, lp; 1.2795 + png_uint_32 sum = 0, lmins = mins; 1.2796 + png_size_t i; 1.2797 + int v; 1.2798 + 1.2799 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2800 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2801 + { 1.2802 + int j; 1.2803 + png_uint_32 lmhi, lmlo; 1.2804 + lmlo = lmins & PNG_LOMASK; 1.2805 + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 1.2806 + 1.2807 + for (j = 0; j < num_p_filters; j++) 1.2808 + { 1.2809 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) 1.2810 + { 1.2811 + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 1.2812 + PNG_WEIGHT_SHIFT; 1.2813 + 1.2814 + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 1.2815 + PNG_WEIGHT_SHIFT; 1.2816 + } 1.2817 + } 1.2818 + 1.2819 + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> 1.2820 + PNG_COST_SHIFT; 1.2821 + 1.2822 + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> 1.2823 + PNG_COST_SHIFT; 1.2824 + 1.2825 + if (lmhi > PNG_HIMASK) 1.2826 + lmins = PNG_MAXSUM; 1.2827 + 1.2828 + else 1.2829 + lmins = (lmhi << PNG_HISHIFT) + lmlo; 1.2830 + } 1.2831 +#endif 1.2832 + 1.2833 + for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, 1.2834 + pp = prev_row + 1; i < bpp; i++) 1.2835 + { 1.2836 + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 1.2837 + 1.2838 + sum += (v < 128) ? v : 256 - v; 1.2839 + } 1.2840 + 1.2841 + for (lp = row_buf + 1; i < row_bytes; i++) 1.2842 + { 1.2843 + v = *dp++ = 1.2844 + (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); 1.2845 + 1.2846 + sum += (v < 128) ? v : 256 - v; 1.2847 + 1.2848 + if (sum > lmins) /* We are already worse, don't continue. */ 1.2849 + break; 1.2850 + } 1.2851 + 1.2852 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2853 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2854 + { 1.2855 + int j; 1.2856 + png_uint_32 sumhi, sumlo; 1.2857 + sumlo = sum & PNG_LOMASK; 1.2858 + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 1.2859 + 1.2860 + for (j = 0; j < num_p_filters; j++) 1.2861 + { 1.2862 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) 1.2863 + { 1.2864 + sumlo = (sumlo * png_ptr->filter_weights[j]) >> 1.2865 + PNG_WEIGHT_SHIFT; 1.2866 + 1.2867 + sumhi = (sumhi * png_ptr->filter_weights[j]) >> 1.2868 + PNG_WEIGHT_SHIFT; 1.2869 + } 1.2870 + } 1.2871 + 1.2872 + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> 1.2873 + PNG_COST_SHIFT; 1.2874 + 1.2875 + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> 1.2876 + PNG_COST_SHIFT; 1.2877 + 1.2878 + if (sumhi > PNG_HIMASK) 1.2879 + sum = PNG_MAXSUM; 1.2880 + 1.2881 + else 1.2882 + sum = (sumhi << PNG_HISHIFT) + sumlo; 1.2883 + } 1.2884 +#endif 1.2885 + 1.2886 + if (sum < mins) 1.2887 + { 1.2888 + mins = sum; 1.2889 + best_row = png_ptr->avg_row; 1.2890 + } 1.2891 + } 1.2892 + 1.2893 + /* Paeth filter */ 1.2894 + if (filter_to_do == PNG_FILTER_PAETH) 1.2895 + { 1.2896 + png_bytep rp, dp, pp, cp, lp; 1.2897 + png_size_t i; 1.2898 + 1.2899 + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, 1.2900 + pp = prev_row + 1; i < bpp; i++) 1.2901 + { 1.2902 + *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 1.2903 + } 1.2904 + 1.2905 + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) 1.2906 + { 1.2907 + int a, b, c, pa, pb, pc, p; 1.2908 + 1.2909 + b = *pp++; 1.2910 + c = *cp++; 1.2911 + a = *lp++; 1.2912 + 1.2913 + p = b - c; 1.2914 + pc = a - c; 1.2915 + 1.2916 +#ifdef PNG_USE_ABS 1.2917 + pa = abs(p); 1.2918 + pb = abs(pc); 1.2919 + pc = abs(p + pc); 1.2920 +#else 1.2921 + pa = p < 0 ? -p : p; 1.2922 + pb = pc < 0 ? -pc : pc; 1.2923 + pc = (p + pc) < 0 ? -(p + pc) : p + pc; 1.2924 +#endif 1.2925 + 1.2926 + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 1.2927 + 1.2928 + *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 1.2929 + } 1.2930 + best_row = png_ptr->paeth_row; 1.2931 + } 1.2932 + 1.2933 + else if (filter_to_do & PNG_FILTER_PAETH) 1.2934 + { 1.2935 + png_bytep rp, dp, pp, cp, lp; 1.2936 + png_uint_32 sum = 0, lmins = mins; 1.2937 + png_size_t i; 1.2938 + int v; 1.2939 + 1.2940 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.2941 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.2942 + { 1.2943 + int j; 1.2944 + png_uint_32 lmhi, lmlo; 1.2945 + lmlo = lmins & PNG_LOMASK; 1.2946 + lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 1.2947 + 1.2948 + for (j = 0; j < num_p_filters; j++) 1.2949 + { 1.2950 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) 1.2951 + { 1.2952 + lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 1.2953 + PNG_WEIGHT_SHIFT; 1.2954 + 1.2955 + lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 1.2956 + PNG_WEIGHT_SHIFT; 1.2957 + } 1.2958 + } 1.2959 + 1.2960 + lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> 1.2961 + PNG_COST_SHIFT; 1.2962 + 1.2963 + lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> 1.2964 + PNG_COST_SHIFT; 1.2965 + 1.2966 + if (lmhi > PNG_HIMASK) 1.2967 + lmins = PNG_MAXSUM; 1.2968 + 1.2969 + else 1.2970 + lmins = (lmhi << PNG_HISHIFT) + lmlo; 1.2971 + } 1.2972 +#endif 1.2973 + 1.2974 + for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, 1.2975 + pp = prev_row + 1; i < bpp; i++) 1.2976 + { 1.2977 + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 1.2978 + 1.2979 + sum += (v < 128) ? v : 256 - v; 1.2980 + } 1.2981 + 1.2982 + for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) 1.2983 + { 1.2984 + int a, b, c, pa, pb, pc, p; 1.2985 + 1.2986 + b = *pp++; 1.2987 + c = *cp++; 1.2988 + a = *lp++; 1.2989 + 1.2990 +#ifndef PNG_SLOW_PAETH 1.2991 + p = b - c; 1.2992 + pc = a - c; 1.2993 +#ifdef PNG_USE_ABS 1.2994 + pa = abs(p); 1.2995 + pb = abs(pc); 1.2996 + pc = abs(p + pc); 1.2997 +#else 1.2998 + pa = p < 0 ? -p : p; 1.2999 + pb = pc < 0 ? -pc : pc; 1.3000 + pc = (p + pc) < 0 ? -(p + pc) : p + pc; 1.3001 +#endif 1.3002 + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 1.3003 +#else /* PNG_SLOW_PAETH */ 1.3004 + p = a + b - c; 1.3005 + pa = abs(p - a); 1.3006 + pb = abs(p - b); 1.3007 + pc = abs(p - c); 1.3008 + 1.3009 + if (pa <= pb && pa <= pc) 1.3010 + p = a; 1.3011 + 1.3012 + else if (pb <= pc) 1.3013 + p = b; 1.3014 + 1.3015 + else 1.3016 + p = c; 1.3017 +#endif /* PNG_SLOW_PAETH */ 1.3018 + 1.3019 + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 1.3020 + 1.3021 + sum += (v < 128) ? v : 256 - v; 1.3022 + 1.3023 + if (sum > lmins) /* We are already worse, don't continue. */ 1.3024 + break; 1.3025 + } 1.3026 + 1.3027 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.3028 + if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 1.3029 + { 1.3030 + int j; 1.3031 + png_uint_32 sumhi, sumlo; 1.3032 + sumlo = sum & PNG_LOMASK; 1.3033 + sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 1.3034 + 1.3035 + for (j = 0; j < num_p_filters; j++) 1.3036 + { 1.3037 + if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) 1.3038 + { 1.3039 + sumlo = (sumlo * png_ptr->filter_weights[j]) >> 1.3040 + PNG_WEIGHT_SHIFT; 1.3041 + 1.3042 + sumhi = (sumhi * png_ptr->filter_weights[j]) >> 1.3043 + PNG_WEIGHT_SHIFT; 1.3044 + } 1.3045 + } 1.3046 + 1.3047 + sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> 1.3048 + PNG_COST_SHIFT; 1.3049 + 1.3050 + sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> 1.3051 + PNG_COST_SHIFT; 1.3052 + 1.3053 + if (sumhi > PNG_HIMASK) 1.3054 + sum = PNG_MAXSUM; 1.3055 + 1.3056 + else 1.3057 + sum = (sumhi << PNG_HISHIFT) + sumlo; 1.3058 + } 1.3059 +#endif 1.3060 + 1.3061 + if (sum < mins) 1.3062 + { 1.3063 + best_row = png_ptr->paeth_row; 1.3064 + } 1.3065 + } 1.3066 +#endif /* PNG_WRITE_FILTER_SUPPORTED */ 1.3067 + 1.3068 + /* Do the actual writing of the filtered row data from the chosen filter. */ 1.3069 + png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); 1.3070 + 1.3071 +#ifdef PNG_WRITE_FILTER_SUPPORTED 1.3072 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 1.3073 + /* Save the type of filter we picked this time for future calculations */ 1.3074 + if (png_ptr->num_prev_filters > 0) 1.3075 + { 1.3076 + int j; 1.3077 + 1.3078 + for (j = 1; j < num_p_filters; j++) 1.3079 + { 1.3080 + png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; 1.3081 + } 1.3082 + 1.3083 + png_ptr->prev_filters[j] = best_row[0]; 1.3084 + } 1.3085 +#endif 1.3086 +#endif /* PNG_WRITE_FILTER_SUPPORTED */ 1.3087 +} 1.3088 + 1.3089 + 1.3090 +/* Do the actual writing of a previously filtered row. */ 1.3091 +static void 1.3092 +png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, 1.3093 + png_size_t full_row_length/*includes filter byte*/) 1.3094 +{ 1.3095 + png_debug(1, "in png_write_filtered_row"); 1.3096 + 1.3097 + png_debug1(2, "filter = %d", filtered_row[0]); 1.3098 + 1.3099 + png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); 1.3100 + 1.3101 + /* Swap the current and previous rows */ 1.3102 + if (png_ptr->prev_row != NULL) 1.3103 + { 1.3104 + png_bytep tptr; 1.3105 + 1.3106 + tptr = png_ptr->prev_row; 1.3107 + png_ptr->prev_row = png_ptr->row_buf; 1.3108 + png_ptr->row_buf = tptr; 1.3109 + } 1.3110 + 1.3111 + /* Finish row - updates counters and flushes zlib if last row */ 1.3112 + png_write_finish_row(png_ptr); 1.3113 + 1.3114 +#ifdef PNG_WRITE_FLUSH_SUPPORTED 1.3115 + png_ptr->flush_rows++; 1.3116 + 1.3117 + if (png_ptr->flush_dist > 0 && 1.3118 + png_ptr->flush_rows >= png_ptr->flush_dist) 1.3119 + { 1.3120 + png_write_flush(png_ptr); 1.3121 + } 1.3122 +#endif 1.3123 +} 1.3124 + 1.3125 +#ifdef PNG_WRITE_APNG_SUPPORTED 1.3126 +void /* PRIVATE */ 1.3127 +png_write_reset(png_structp png_ptr) 1.3128 +{ 1.3129 + png_ptr->row_number = 0; 1.3130 + png_ptr->pass = 0; 1.3131 + png_ptr->mode &= ~PNG_HAVE_IDAT; 1.3132 +} 1.3133 + 1.3134 +void /* PRIVATE */ 1.3135 +png_write_reinit(png_structp png_ptr, png_infop info_ptr, 1.3136 + png_uint_32 width, png_uint_32 height) 1.3137 +{ 1.3138 + if (png_ptr->num_frames_written == 0 && 1.3139 + (width != png_ptr->first_frame_width || 1.3140 + height != png_ptr->first_frame_height)) 1.3141 + png_error(png_ptr, "width and/or height in the first frame's fcTL " 1.3142 + "don't match the ones in IHDR"); 1.3143 + if (width > png_ptr->first_frame_width || 1.3144 + height > png_ptr->first_frame_height) 1.3145 + png_error(png_ptr, "width and/or height for a frame greater than" 1.3146 + "the ones in IHDR"); 1.3147 + 1.3148 + png_set_IHDR(png_ptr, info_ptr, width, height, 1.3149 + info_ptr->bit_depth, info_ptr->color_type, 1.3150 + info_ptr->interlace_type, info_ptr->compression_type, 1.3151 + info_ptr->filter_type); 1.3152 + 1.3153 + png_ptr->width = width; 1.3154 + png_ptr->height = height; 1.3155 + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); 1.3156 + png_ptr->usr_width = png_ptr->width; 1.3157 +} 1.3158 +#endif /* PNG_WRITE_APNG_SUPPORTED */ 1.3159 +#endif /* PNG_WRITE_SUPPORTED */