OLD | NEW |
1 | 1 |
2 /* pngwutil.c - utilities to write a PNG file | 2 /* pngwutil.c - utilities to write a PNG file |
3 * | 3 * |
4 * Last changed in libpng 1.2.56 [%RDATE%] | 4 * Last changed in libpng 1.6.22 [May 26, 2016] |
5 * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson | 5 * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson |
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) | 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) | 7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 * | 8 * |
9 * This code is released under the libpng license. | 9 * This code is released under the libpng license. |
10 * For conditions of distribution and use, see the disclaimer | 10 * For conditions of distribution and use, see the disclaimer |
11 * and license in png.h | 11 * and license in png.h |
12 */ | 12 */ |
13 | 13 |
14 #define PNG_INTERNAL | 14 #include "pngpriv.h" |
15 #define PNG_NO_PEDANTIC_WARNINGS | 15 |
16 #include "png.h" | |
17 #ifdef PNG_WRITE_SUPPORTED | 16 #ifdef PNG_WRITE_SUPPORTED |
18 | 17 |
| 18 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED |
19 /* Place a 32-bit number into a buffer in PNG byte order. We work | 19 /* Place a 32-bit number into a buffer in PNG byte order. We work |
20 * with unsigned numbers for convenience, although one supported | 20 * with unsigned numbers for convenience, although one supported |
21 * ancillary chunk uses signed (two's complement) numbers. | 21 * ancillary chunk uses signed (two's complement) numbers. |
22 */ | 22 */ |
23 void PNGAPI | 23 void PNGAPI |
24 png_save_uint_32(png_bytep buf, png_uint_32 i) | 24 png_save_uint_32(png_bytep buf, png_uint_32 i) |
25 { | 25 { |
26 buf[0] = (png_byte)((i >> 24) & 0xff); | 26 buf[0] = (png_byte)((i >> 24) & 0xffU); |
27 buf[1] = (png_byte)((i >> 16) & 0xff); | 27 buf[1] = (png_byte)((i >> 16) & 0xffU); |
28 buf[2] = (png_byte)((i >> 8) & 0xff); | 28 buf[2] = (png_byte)((i >> 8) & 0xffU); |
29 buf[3] = (png_byte)(i & 0xff); | 29 buf[3] = (png_byte)( i & 0xffU); |
30 } | |
31 | |
32 /* The png_save_int_32 function assumes integers are stored in two's | |
33 * complement format. If this isn't the case, then this routine needs to | |
34 * be modified to write data in two's complement format. | |
35 */ | |
36 void PNGAPI | |
37 png_save_int_32(png_bytep buf, png_int_32 i) | |
38 { | |
39 buf[0] = (png_byte)((i >> 24) & 0xff); | |
40 buf[1] = (png_byte)((i >> 16) & 0xff); | |
41 buf[2] = (png_byte)((i >> 8) & 0xff); | |
42 buf[3] = (png_byte)(i & 0xff); | |
43 } | 30 } |
44 | 31 |
45 /* Place a 16-bit number into a buffer in PNG byte order. | 32 /* Place a 16-bit number into a buffer in PNG byte order. |
46 * The parameter is declared unsigned int, not png_uint_16, | 33 * The parameter is declared unsigned int, not png_uint_16, |
47 * just to avoid potential problems on pre-ANSI C compilers. | 34 * just to avoid potential problems on pre-ANSI C compilers. |
48 */ | 35 */ |
49 void PNGAPI | 36 void PNGAPI |
50 png_save_uint_16(png_bytep buf, unsigned int i) | 37 png_save_uint_16(png_bytep buf, unsigned int i) |
51 { | 38 { |
52 buf[0] = (png_byte)((i >> 8) & 0xff); | 39 buf[0] = (png_byte)((i >> 8) & 0xffU); |
53 buf[1] = (png_byte)(i & 0xff); | 40 buf[1] = (png_byte)( i & 0xffU); |
54 } | 41 } |
| 42 #endif |
55 | 43 |
56 /* Simple function to write the signature. If we have already written | 44 /* Simple function to write the signature. If we have already written |
57 * the magic bytes of the signature, or more likely, the PNG stream is | 45 * the magic bytes of the signature, or more likely, the PNG stream is |
58 * being embedded into another stream and doesn't need its own signature, | 46 * being embedded into another stream and doesn't need its own signature, |
59 * we should call png_set_sig_bytes() to tell libpng how many of the | 47 * we should call png_set_sig_bytes() to tell libpng how many of the |
60 * bytes have already been written. | 48 * bytes have already been written. |
61 */ | 49 */ |
62 void /* PRIVATE */ | 50 void PNGAPI |
63 png_write_sig(png_structp png_ptr) | 51 png_write_sig(png_structrp png_ptr) |
64 { | 52 { |
65 png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; | 53 png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; |
66 | 54 |
| 55 #ifdef PNG_IO_STATE_SUPPORTED |
| 56 /* Inform the I/O callback that the signature is being written */ |
| 57 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; |
| 58 #endif |
| 59 |
67 /* Write the rest of the 8 byte signature */ | 60 /* Write the rest of the 8 byte signature */ |
68 png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], | 61 png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], |
69 (png_size_t)(8 - png_ptr->sig_bytes)); | 62 (png_size_t)(8 - png_ptr->sig_bytes)); |
| 63 |
70 if (png_ptr->sig_bytes < 3) | 64 if (png_ptr->sig_bytes < 3) |
71 png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; | 65 png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; |
72 } | 66 } |
73 | 67 |
| 68 /* Write the start of a PNG chunk. The type is the chunk type. |
| 69 * The total_length is the sum of the lengths of all the data you will be |
| 70 * passing in png_write_chunk_data(). |
| 71 */ |
| 72 static void |
| 73 png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, |
| 74 png_uint_32 length) |
| 75 { |
| 76 png_byte buf[8]; |
| 77 |
| 78 #if defined(PNG_DEBUG) && (PNG_DEBUG > 0) |
| 79 PNG_CSTRING_FROM_CHUNK(buf, chunk_name); |
| 80 png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); |
| 81 #endif |
| 82 |
| 83 if (png_ptr == NULL) |
| 84 return; |
| 85 |
| 86 #ifdef PNG_IO_STATE_SUPPORTED |
| 87 /* Inform the I/O callback that the chunk header is being written. |
| 88 * PNG_IO_CHUNK_HDR requires a single I/O call. |
| 89 */ |
| 90 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; |
| 91 #endif |
| 92 |
| 93 /* Write the length and the chunk name */ |
| 94 png_save_uint_32(buf, length); |
| 95 png_save_uint_32(buf + 4, chunk_name); |
| 96 png_write_data(png_ptr, buf, 8); |
| 97 |
| 98 /* Put the chunk name into png_ptr->chunk_name */ |
| 99 png_ptr->chunk_name = chunk_name; |
| 100 |
| 101 /* Reset the crc and run it over the chunk name */ |
| 102 png_reset_crc(png_ptr); |
| 103 |
| 104 png_calculate_crc(png_ptr, buf + 4, 4); |
| 105 |
| 106 #ifdef PNG_IO_STATE_SUPPORTED |
| 107 /* Inform the I/O callback that chunk data will (possibly) be written. |
| 108 * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. |
| 109 */ |
| 110 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; |
| 111 #endif |
| 112 } |
| 113 |
| 114 void PNGAPI |
| 115 png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, |
| 116 png_uint_32 length) |
| 117 { |
| 118 png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); |
| 119 } |
| 120 |
| 121 /* Write the data of a PNG chunk started with png_write_chunk_header(). |
| 122 * Note that multiple calls to this function are allowed, and that the |
| 123 * sum of the lengths from these calls *must* add up to the total_length |
| 124 * given to png_write_chunk_header(). |
| 125 */ |
| 126 void PNGAPI |
| 127 png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, |
| 128 png_size_t length) |
| 129 { |
| 130 /* Write the data, and run the CRC over it */ |
| 131 if (png_ptr == NULL) |
| 132 return; |
| 133 |
| 134 if (data != NULL && length > 0) |
| 135 { |
| 136 png_write_data(png_ptr, data, length); |
| 137 |
| 138 /* Update the CRC after writing the data, |
| 139 * in case the user I/O routine alters it. |
| 140 */ |
| 141 png_calculate_crc(png_ptr, data, length); |
| 142 } |
| 143 } |
| 144 |
| 145 /* Finish a chunk started with png_write_chunk_header(). */ |
| 146 void PNGAPI |
| 147 png_write_chunk_end(png_structrp png_ptr) |
| 148 { |
| 149 png_byte buf[4]; |
| 150 |
| 151 if (png_ptr == NULL) return; |
| 152 |
| 153 #ifdef PNG_IO_STATE_SUPPORTED |
| 154 /* Inform the I/O callback that the chunk CRC is being written. |
| 155 * PNG_IO_CHUNK_CRC requires a single I/O function call. |
| 156 */ |
| 157 png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; |
| 158 #endif |
| 159 |
| 160 /* Write the crc in a single operation */ |
| 161 png_save_uint_32(buf, png_ptr->crc); |
| 162 |
| 163 png_write_data(png_ptr, buf, (png_size_t)4); |
| 164 } |
| 165 |
74 /* Write a PNG chunk all at once. The type is an array of ASCII characters | 166 /* Write a PNG chunk all at once. The type is an array of ASCII characters |
75 * representing the chunk name. The array must be at least 4 bytes in | 167 * representing the chunk name. The array must be at least 4 bytes in |
76 * length, and does not need to be null terminated. To be safe, pass the | 168 * length, and does not need to be null terminated. To be safe, pass the |
77 * pre-defined chunk names here, and if you need a new one, define it | 169 * pre-defined chunk names here, and if you need a new one, define it |
78 * where the others are defined. The length is the length of the data. | 170 * where the others are defined. The length is the length of the data. |
79 * All the data must be present. If that is not possible, use the | 171 * All the data must be present. If that is not possible, use the |
80 * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() | 172 * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() |
81 * functions instead. | 173 * functions instead. |
82 */ | 174 */ |
83 void PNGAPI | 175 static void |
84 png_write_chunk(png_structp png_ptr, png_bytep chunk_name, | 176 png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, |
85 png_bytep data, png_size_t length) | 177 png_const_bytep data, png_size_t length) |
86 { | 178 { |
87 if (png_ptr == NULL) | 179 if (png_ptr == NULL) |
88 return; | 180 return; |
89 png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); | 181 |
90 png_write_chunk_data(png_ptr, data, (png_size_t)length); | 182 /* On 64-bit architectures 'length' may not fit in a png_uint_32. */ |
| 183 if (length > PNG_UINT_31_MAX) |
| 184 png_error(png_ptr, "length exceeds PNG maximum"); |
| 185 |
| 186 png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); |
| 187 png_write_chunk_data(png_ptr, data, length); |
91 png_write_chunk_end(png_ptr); | 188 png_write_chunk_end(png_ptr); |
92 } | 189 } |
93 | 190 |
94 /* Write the start of a PNG chunk. The type is the chunk type. | 191 /* This is the API that calls the internal function above. */ |
95 * The total_length is the sum of the lengths of all the data you will be | 192 void PNGAPI |
96 * passing in png_write_chunk_data(). | 193 png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, |
| 194 png_const_bytep data, png_size_t length) |
| 195 { |
| 196 png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, |
| 197 length); |
| 198 } |
| 199 |
| 200 /* This is used below to find the size of an image to pass to png_deflate_claim, |
| 201 * so it only needs to be accurate if the size is less than 16384 bytes (the |
| 202 * point at which a lower LZ window size can be used.) |
97 */ | 203 */ |
98 void PNGAPI | 204 static png_alloc_size_t |
99 png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, | 205 png_image_size(png_structrp png_ptr) |
100 png_uint_32 length) | 206 { |
101 { | 207 /* Only return sizes up to the maximum of a png_uint_32; do this by limiting |
102 png_byte buf[8]; | 208 * the width and height used to 15 bits. |
103 | 209 */ |
104 png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, | 210 png_uint_32 h = png_ptr->height; |
105 (unsigned long)length); | 211 |
106 | 212 if (png_ptr->rowbytes < 32768 && h < 32768) |
107 if (png_ptr == NULL) | 213 { |
108 return; | 214 if (png_ptr->interlaced != 0) |
109 | 215 { |
110 | 216 /* Interlacing makes the image larger because of the replication of |
111 /* Write the length and the chunk name */ | 217 * both the filter byte and the padding to a byte boundary. |
112 png_save_uint_32(buf, length); | 218 */ |
113 png_memcpy(buf + 4, chunk_name, 4); | 219 png_uint_32 w = png_ptr->width; |
114 png_write_data(png_ptr, buf, (png_size_t)8); | 220 unsigned int pd = png_ptr->pixel_depth; |
115 /* Put the chunk name into png_ptr->chunk_name */ | 221 png_alloc_size_t cb_base; |
116 png_memcpy(png_ptr->chunk_name, chunk_name, 4); | 222 int pass; |
117 /* Reset the crc and run it over the chunk name */ | 223 |
118 png_reset_crc(png_ptr); | 224 for (cb_base=0, pass=0; pass<=6; ++pass) |
119 png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); | 225 { |
120 } | 226 png_uint_32 pw = PNG_PASS_COLS(w, pass); |
121 | 227 |
122 /* Write the data of a PNG chunk started with png_write_chunk_start(). | 228 if (pw > 0) |
123 * Note that multiple calls to this function are allowed, and that the | 229 cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); |
124 * sum of the lengths from these calls *must* add up to the total_length | 230 } |
125 * given to png_write_chunk_start(). | 231 |
126 */ | 232 return cb_base; |
127 void PNGAPI | 233 } |
128 png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) | 234 |
129 { | 235 else |
130 /* Write the data, and run the CRC over it */ | 236 return (png_ptr->rowbytes+1) * h; |
131 if (png_ptr == NULL) | 237 } |
132 return; | 238 |
133 if (data != NULL && length > 0) | 239 else |
134 { | 240 return 0xffffffffU; |
135 png_write_data(png_ptr, data, length); | 241 } |
136 /* Update the CRC after writing the data, | 242 |
137 * in case that the user I/O routine alters it. | 243 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
138 */ | 244 /* This is the code to hack the first two bytes of the deflate stream (the |
139 png_calculate_crc(png_ptr, data, length); | 245 * deflate header) to correct the windowBits value to match the actual data |
140 } | 246 * size. Note that the second argument is the *uncompressed* size but the |
141 } | 247 * first argument is the *compressed* data (and it must be deflate |
142 | 248 * compressed.) |
143 /* Finish a chunk started with png_write_chunk_start(). */ | 249 */ |
144 void PNGAPI | 250 static void |
145 png_write_chunk_end(png_structp png_ptr) | 251 optimize_cmf(png_bytep data, png_alloc_size_t data_size) |
146 { | 252 { |
147 png_byte buf[4]; | 253 /* Optimize the CMF field in the zlib stream. The resultant zlib stream is |
148 | 254 * still compliant to the stream specification. |
149 if (png_ptr == NULL) return; | 255 */ |
150 | 256 if (data_size <= 16384) /* else windowBits must be 15 */ |
151 /* Write the crc in a single operation */ | 257 { |
152 png_save_uint_32(buf, png_ptr->crc); | 258 unsigned int z_cmf = data[0]; /* zlib compression method and flags */ |
153 | 259 |
154 png_write_data(png_ptr, buf, (png_size_t)4); | 260 if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) |
155 } | 261 { |
156 | 262 unsigned int z_cinfo; |
157 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) | 263 unsigned int half_z_window_size; |
| 264 |
| 265 z_cinfo = z_cmf >> 4; |
| 266 half_z_window_size = 1U << (z_cinfo + 7); |
| 267 |
| 268 if (data_size <= half_z_window_size) /* else no change */ |
| 269 { |
| 270 unsigned int tmp; |
| 271 |
| 272 do |
| 273 { |
| 274 half_z_window_size >>= 1; |
| 275 --z_cinfo; |
| 276 } |
| 277 while (z_cinfo > 0 && data_size <= half_z_window_size); |
| 278 |
| 279 z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); |
| 280 |
| 281 data[0] = (png_byte)z_cmf; |
| 282 tmp = data[1] & 0xe0; |
| 283 tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; |
| 284 data[1] = (png_byte)tmp; |
| 285 } |
| 286 } |
| 287 } |
| 288 } |
| 289 #endif /* WRITE_OPTIMIZE_CMF */ |
| 290 |
| 291 /* Initialize the compressor for the appropriate type of compression. */ |
| 292 static int |
| 293 png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, |
| 294 png_alloc_size_t data_size) |
| 295 { |
| 296 if (png_ptr->zowner != 0) |
| 297 { |
| 298 #if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) |
| 299 char msg[64]; |
| 300 |
| 301 PNG_STRING_FROM_CHUNK(msg, owner); |
| 302 msg[4] = ':'; |
| 303 msg[5] = ' '; |
| 304 PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); |
| 305 /* So the message that results is "<chunk> using zstream"; this is an |
| 306 * internal error, but is very useful for debugging. i18n requirements |
| 307 * are minimal. |
| 308 */ |
| 309 (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); |
| 310 #endif |
| 311 #if PNG_RELEASE_BUILD |
| 312 png_warning(png_ptr, msg); |
| 313 |
| 314 /* Attempt sane error recovery */ |
| 315 if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ |
| 316 { |
| 317 png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); |
| 318 return Z_STREAM_ERROR; |
| 319 } |
| 320 |
| 321 png_ptr->zowner = 0; |
| 322 #else |
| 323 png_error(png_ptr, msg); |
| 324 #endif |
| 325 } |
| 326 |
| 327 { |
| 328 int level = png_ptr->zlib_level; |
| 329 int method = png_ptr->zlib_method; |
| 330 int windowBits = png_ptr->zlib_window_bits; |
| 331 int memLevel = png_ptr->zlib_mem_level; |
| 332 int strategy; /* set below */ |
| 333 int ret; /* zlib return code */ |
| 334 |
| 335 if (owner == png_IDAT) |
| 336 { |
| 337 if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0) |
| 338 strategy = png_ptr->zlib_strategy; |
| 339 |
| 340 else if (png_ptr->do_filter != PNG_FILTER_NONE) |
| 341 strategy = PNG_Z_DEFAULT_STRATEGY; |
| 342 |
| 343 else |
| 344 strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; |
| 345 } |
| 346 |
| 347 else |
| 348 { |
| 349 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED |
| 350 level = png_ptr->zlib_text_level; |
| 351 method = png_ptr->zlib_text_method; |
| 352 windowBits = png_ptr->zlib_text_window_bits; |
| 353 memLevel = png_ptr->zlib_text_mem_level; |
| 354 strategy = png_ptr->zlib_text_strategy; |
| 355 #else |
| 356 /* If customization is not supported the values all come from the |
| 357 * IDAT values except for the strategy, which is fixed to the |
| 358 * default. (This is the pre-1.6.0 behavior too, although it was |
| 359 * implemented in a very different way.) |
| 360 */ |
| 361 strategy = Z_DEFAULT_STRATEGY; |
| 362 #endif |
| 363 } |
| 364 |
| 365 /* Adjust 'windowBits' down if larger than 'data_size'; to stop this |
| 366 * happening just pass 32768 as the data_size parameter. Notice that zlib |
| 367 * requires an extra 262 bytes in the window in addition to the data to be |
| 368 * able to see the whole of the data, so if data_size+262 takes us to the |
| 369 * next windowBits size we need to fix up the value later. (Because even |
| 370 * though deflate needs the extra window, inflate does not!) |
| 371 */ |
| 372 if (data_size <= 16384) |
| 373 { |
| 374 /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to |
| 375 * work round a Microsoft Visual C misbehavior which, contrary to C-90, |
| 376 * widens the result of the following shift to 64-bits if (and, |
| 377 * apparently, only if) it is used in a test. |
| 378 */ |
| 379 unsigned int half_window_size = 1U << (windowBits-1); |
| 380 |
| 381 while (data_size + 262 <= half_window_size) |
| 382 { |
| 383 half_window_size >>= 1; |
| 384 --windowBits; |
| 385 } |
| 386 } |
| 387 |
| 388 /* Check against the previous initialized values, if any. */ |
| 389 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 && |
| 390 (png_ptr->zlib_set_level != level || |
| 391 png_ptr->zlib_set_method != method || |
| 392 png_ptr->zlib_set_window_bits != windowBits || |
| 393 png_ptr->zlib_set_mem_level != memLevel || |
| 394 png_ptr->zlib_set_strategy != strategy)) |
| 395 { |
| 396 if (deflateEnd(&png_ptr->zstream) != Z_OK) |
| 397 png_warning(png_ptr, "deflateEnd failed (ignored)"); |
| 398 |
| 399 png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; |
| 400 } |
| 401 |
| 402 /* For safety clear out the input and output pointers (currently zlib |
| 403 * doesn't use them on Init, but it might in the future). |
| 404 */ |
| 405 png_ptr->zstream.next_in = NULL; |
| 406 png_ptr->zstream.avail_in = 0; |
| 407 png_ptr->zstream.next_out = NULL; |
| 408 png_ptr->zstream.avail_out = 0; |
| 409 |
| 410 /* Now initialize if required, setting the new parameters, otherwise just |
| 411 * to a simple reset to the previous parameters. |
| 412 */ |
| 413 if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) |
| 414 ret = deflateReset(&png_ptr->zstream); |
| 415 |
| 416 else |
| 417 { |
| 418 ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, |
| 419 memLevel, strategy); |
| 420 |
| 421 if (ret == Z_OK) |
| 422 png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; |
| 423 } |
| 424 |
| 425 /* The return code is from either deflateReset or deflateInit2; they have |
| 426 * pretty much the same set of error codes. |
| 427 */ |
| 428 if (ret == Z_OK) |
| 429 png_ptr->zowner = owner; |
| 430 |
| 431 else |
| 432 png_zstream_error(png_ptr, ret); |
| 433 |
| 434 return ret; |
| 435 } |
| 436 } |
| 437 |
| 438 /* Clean up (or trim) a linked list of compression buffers. */ |
| 439 void /* PRIVATE */ |
| 440 png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) |
| 441 { |
| 442 png_compression_bufferp list = *listp; |
| 443 |
| 444 if (list != NULL) |
| 445 { |
| 446 *listp = NULL; |
| 447 |
| 448 do |
| 449 { |
| 450 png_compression_bufferp next = list->next; |
| 451 |
| 452 png_free(png_ptr, list); |
| 453 list = next; |
| 454 } |
| 455 while (list != NULL); |
| 456 } |
| 457 } |
| 458 |
| 459 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED |
158 /* This pair of functions encapsulates the operation of (a) compressing a | 460 /* This pair of functions encapsulates the operation of (a) compressing a |
159 * text string, and (b) issuing it later as a series of chunk data writes. | 461 * text string, and (b) issuing it later as a series of chunk data writes. |
160 * The compression_state structure is shared context for these functions | 462 * The compression_state structure is shared context for these functions |
161 * set up by the caller in order to make the whole mess thread-safe. | 463 * set up by the caller to allow access to the relevant local variables. |
| 464 * |
| 465 * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size |
| 466 * temporary buffers. From 1.6.0 it is retained in png_struct so that it will |
| 467 * be correctly freed in the event of a write error (previous implementations |
| 468 * just leaked memory.) |
162 */ | 469 */ |
163 | |
164 typedef struct | 470 typedef struct |
165 { | 471 { |
166 char *input; /* The uncompressed input data */ | 472 png_const_bytep input; /* The uncompressed input data */ |
167 int input_len; /* Its length */ | 473 png_alloc_size_t input_len; /* Its length */ |
168 int num_output_ptr; /* Number of output pointers used */ | 474 png_uint_32 output_len; /* Final compressed length */ |
169 int max_output_ptr; /* Size of output_ptr */ | 475 png_byte output[1024]; /* First block of output */ |
170 png_charpp output_ptr; /* Array of pointers to output */ | |
171 } compression_state; | 476 } compression_state; |
172 | 477 |
173 /* Compress given text into storage in the png_ptr structure */ | 478 static void |
174 static int /* PRIVATE */ | 479 png_text_compress_init(compression_state *comp, png_const_bytep input, |
175 png_text_compress(png_structp png_ptr, | 480 png_alloc_size_t input_len) |
176 png_charp text, png_size_t text_len, int compression, | 481 { |
177 compression_state *comp) | 482 comp->input = input; |
| 483 comp->input_len = input_len; |
| 484 comp->output_len = 0; |
| 485 } |
| 486 |
| 487 /* Compress the data in the compression state input */ |
| 488 static int |
| 489 png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, |
| 490 compression_state *comp, png_uint_32 prefix_len) |
178 { | 491 { |
179 int ret; | 492 int ret; |
180 | 493 |
181 comp->num_output_ptr = 0; | 494 /* To find the length of the output it is necessary to first compress the |
182 comp->max_output_ptr = 0; | 495 * input. The result is buffered rather than using the two-pass algorithm |
183 comp->output_ptr = NULL; | 496 * that is used on the inflate side; deflate is assumed to be slower and a |
184 comp->input = NULL; | 497 * PNG writer is assumed to have more memory available than a PNG reader. |
185 comp->input_len = 0; | |
186 | |
187 /* We may just want to pass the text right through */ | |
188 if (compression == PNG_TEXT_COMPRESSION_NONE) | |
189 { | |
190 comp->input = text; | |
191 comp->input_len = text_len; | |
192 return((int)text_len); | |
193 } | |
194 | |
195 if (compression >= PNG_TEXT_COMPRESSION_LAST) | |
196 { | |
197 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) | |
198 char msg[50]; | |
199 png_snprintf(msg, 50, "Unknown compression type %d", compression); | |
200 png_warning(png_ptr, msg); | |
201 #else | |
202 png_warning(png_ptr, "Unknown compression type"); | |
203 #endif | |
204 } | |
205 | |
206 /* We can't write the chunk until we find out how much data we have, | |
207 * which means we need to run the compressor first and save the | |
208 * output. This shouldn't be a problem, as the vast majority of | |
209 * comments should be reasonable, but we will set up an array of | |
210 * malloc'd pointers to be sure. | |
211 * | 498 * |
212 * If we knew the application was well behaved, we could simplify this | 499 * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an |
213 * greatly by assuming we can always malloc an output buffer large | 500 * upper limit on the output size, but it is always bigger than the input |
214 * enough to hold the compressed text ((1001 * text_len / 1000) + 12) | 501 * size so it is likely to be more efficient to use this linked-list |
215 * and malloc this directly. The only time this would be a bad idea is | 502 * approach. |
216 * if we can't malloc more than 64K and we have 64K of random input | 503 */ |
217 * data, or if the input string is incredibly large (although this | 504 ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); |
218 * wouldn't cause a failure, just a slowdown due to swapping). | 505 |
219 */ | 506 if (ret != Z_OK) |
220 | 507 return ret; |
221 /* Set up the compression buffers */ | 508 |
222 png_ptr->zstream.avail_in = (uInt)text_len; | 509 /* Set up the compression buffers, we need a loop here to avoid overflowing a |
223 png_ptr->zstream.next_in = (Bytef *)text; | 510 * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited |
224 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | 511 * by the output buffer size, so there is no need to check that. Since this |
225 png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; | 512 * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits |
226 | 513 * in size. |
227 /* This is the same compression loop as in png_write_row() */ | 514 */ |
228 do | 515 { |
229 { | 516 png_compression_bufferp *end = &png_ptr->zbuffer_list; |
230 /* Compress the data */ | 517 png_alloc_size_t input_len = comp->input_len; /* may be zero! */ |
231 ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); | 518 png_uint_32 output_len; |
232 if (ret != Z_OK) | 519 |
233 { | 520 /* zlib updates these for us: */ |
234 /* Error */ | 521 png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); |
235 if (png_ptr->zstream.msg != NULL) | 522 png_ptr->zstream.avail_in = 0; /* Set below */ |
236 png_error(png_ptr, png_ptr->zstream.msg); | 523 png_ptr->zstream.next_out = comp->output; |
237 else | 524 png_ptr->zstream.avail_out = (sizeof comp->output); |
238 png_error(png_ptr, "zlib error"); | 525 |
239 } | 526 output_len = png_ptr->zstream.avail_out; |
240 /* Check to see if we need more room */ | 527 |
241 if (!(png_ptr->zstream.avail_out)) | 528 do |
242 { | 529 { |
243 /* Make sure the output array has room */ | 530 uInt avail_in = ZLIB_IO_MAX; |
244 if (comp->num_output_ptr >= comp->max_output_ptr) | 531 |
| 532 if (avail_in > input_len) |
| 533 avail_in = (uInt)input_len; |
| 534 |
| 535 input_len -= avail_in; |
| 536 |
| 537 png_ptr->zstream.avail_in = avail_in; |
| 538 |
| 539 if (png_ptr->zstream.avail_out == 0) |
245 { | 540 { |
246 int old_max; | 541 png_compression_buffer *next; |
247 | 542 |
248 old_max = comp->max_output_ptr; | 543 /* Chunk data is limited to 2^31 bytes in length, so the prefix |
249 comp->max_output_ptr = comp->num_output_ptr + 4; | 544 * length must be counted here. |
250 if (comp->output_ptr != NULL) | 545 */ |
| 546 if (output_len + prefix_len > PNG_UINT_31_MAX) |
251 { | 547 { |
252 png_charpp old_ptr; | 548 ret = Z_MEM_ERROR; |
253 | 549 break; |
254 old_ptr = comp->output_ptr; | |
255 comp->output_ptr = (png_charpp)png_malloc(png_ptr, | |
256 (png_uint_32) | |
257 (comp->max_output_ptr * png_sizeof(png_charp))); | |
258 png_memcpy(comp->output_ptr, old_ptr, old_max | |
259 * png_sizeof(png_charp)); | |
260 png_free(png_ptr, old_ptr); | |
261 } | 550 } |
262 else | 551 |
263 comp->output_ptr = (png_charpp)png_malloc(png_ptr, | 552 /* Need a new (malloc'ed) buffer, but there may be one present |
264 (png_uint_32) | 553 * already. |
265 (comp->max_output_ptr * png_sizeof(png_charp))); | 554 */ |
| 555 next = *end; |
| 556 if (next == NULL) |
| 557 { |
| 558 next = png_voidcast(png_compression_bufferp, png_malloc_base |
| 559 (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); |
| 560 |
| 561 if (next == NULL) |
| 562 { |
| 563 ret = Z_MEM_ERROR; |
| 564 break; |
| 565 } |
| 566 |
| 567 /* Link in this buffer (so that it will be freed later) */ |
| 568 next->next = NULL; |
| 569 *end = next; |
| 570 } |
| 571 |
| 572 png_ptr->zstream.next_out = next->output; |
| 573 png_ptr->zstream.avail_out = png_ptr->zbuffer_size; |
| 574 output_len += png_ptr->zstream.avail_out; |
| 575 |
| 576 /* Move 'end' to the next buffer pointer. */ |
| 577 end = &next->next; |
266 } | 578 } |
267 | 579 |
268 /* Save the data */ | 580 /* Compress the data */ |
269 comp->output_ptr[comp->num_output_ptr] = | 581 ret = deflate(&png_ptr->zstream, |
270 (png_charp)png_malloc(png_ptr, | 582 input_len > 0 ? Z_NO_FLUSH : Z_FINISH); |
271 (png_uint_32)png_ptr->zbuf_size); | 583 |
272 png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, | 584 /* Claw back input data that was not consumed (because avail_in is |
273 png_ptr->zbuf_size); | 585 * reset above every time round the loop). |
274 comp->num_output_ptr++; | 586 */ |
275 | 587 input_len += png_ptr->zstream.avail_in; |
276 /* and reset the buffer */ | 588 png_ptr->zstream.avail_in = 0; /* safety */ |
277 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | 589 } |
278 png_ptr->zstream.next_out = png_ptr->zbuf; | 590 while (ret == Z_OK); |
279 } | 591 |
280 /* Continue until we don't have any more to compress */ | 592 /* There may be some space left in the last output buffer. This needs to |
281 } while (png_ptr->zstream.avail_in); | 593 * be subtracted from output_len. |
282 | 594 */ |
283 /* Finish the compression */ | 595 output_len -= png_ptr->zstream.avail_out; |
284 do | 596 png_ptr->zstream.avail_out = 0; /* safety */ |
285 { | 597 comp->output_len = output_len; |
286 /* Tell zlib we are finished */ | 598 |
287 ret = deflate(&png_ptr->zstream, Z_FINISH); | 599 /* Now double check the output length, put in a custom message if it is |
288 | 600 * too long. Otherwise ensure the z_stream::msg pointer is set to |
289 if (ret == Z_OK) | 601 * something. |
290 { | 602 */ |
291 /* Check to see if we need more room */ | 603 if (output_len + prefix_len >= PNG_UINT_31_MAX) |
292 if (!(png_ptr->zstream.avail_out)) | 604 { |
293 { | 605 png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); |
294 /* Check to make sure our output array has room */ | 606 ret = Z_MEM_ERROR; |
295 if (comp->num_output_ptr >= comp->max_output_ptr) | 607 } |
296 { | 608 |
297 int old_max; | 609 else |
298 | 610 png_zstream_error(png_ptr, ret); |
299 old_max = comp->max_output_ptr; | 611 |
300 comp->max_output_ptr = comp->num_output_ptr + 4; | 612 /* Reset zlib for another zTXt/iTXt or image data */ |
301 if (comp->output_ptr != NULL) | 613 png_ptr->zowner = 0; |
302 { | 614 |
303 png_charpp old_ptr; | 615 /* The only success case is Z_STREAM_END, input_len must be 0; if not this |
304 | 616 * is an internal error. |
305 old_ptr = comp->output_ptr; | 617 */ |
306 /* This could be optimized to realloc() */ | 618 if (ret == Z_STREAM_END && input_len == 0) |
307 comp->output_ptr = (png_charpp)png_malloc(png_ptr, | 619 { |
308 (png_uint_32)(comp->max_output_ptr * | 620 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
309 png_sizeof(png_charp))); | 621 /* Fix up the deflate header, if required */ |
310 png_memcpy(comp->output_ptr, old_ptr, | 622 optimize_cmf(comp->output, comp->input_len); |
311 old_max * png_sizeof(png_charp)); | 623 #endif |
312 png_free(png_ptr, old_ptr); | 624 /* But Z_OK is returned, not Z_STREAM_END; this allows the claim |
313 } | 625 * function above to return Z_STREAM_END on an error (though it never |
314 else | 626 * does in the current versions of zlib.) |
315 comp->output_ptr = (png_charpp)png_malloc(png_ptr, | 627 */ |
316 (png_uint_32)(comp->max_output_ptr * | 628 return Z_OK; |
317 png_sizeof(png_charp))); | 629 } |
318 } | 630 |
319 | 631 else |
320 /* Save the data */ | 632 return ret; |
321 comp->output_ptr[comp->num_output_ptr] = | 633 } |
322 (png_charp)png_malloc(png_ptr, | |
323 (png_uint_32)png_ptr->zbuf_size); | |
324 png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, | |
325 png_ptr->zbuf_size); | |
326 comp->num_output_ptr++; | |
327 | |
328 /* and reset the buffer pointers */ | |
329 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | |
330 png_ptr->zstream.next_out = png_ptr->zbuf; | |
331 } | |
332 } | |
333 else if (ret != Z_STREAM_END) | |
334 { | |
335 /* We got an error */ | |
336 if (png_ptr->zstream.msg != NULL) | |
337 png_error(png_ptr, png_ptr->zstream.msg); | |
338 else | |
339 png_error(png_ptr, "zlib error"); | |
340 } | |
341 } while (ret != Z_STREAM_END); | |
342 | |
343 /* Text length is number of buffers plus last buffer */ | |
344 text_len = png_ptr->zbuf_size * comp->num_output_ptr; | |
345 if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) | |
346 text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; | |
347 | |
348 return((int)text_len); | |
349 } | 634 } |
350 | 635 |
351 /* Ship the compressed text out via chunk writes */ | 636 /* Ship the compressed text out via chunk writes */ |
352 static void /* PRIVATE */ | 637 static void |
353 png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) | 638 png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) |
354 { | 639 { |
355 int i; | 640 png_uint_32 output_len = comp->output_len; |
356 | 641 png_const_bytep output = comp->output; |
357 /* Handle the no-compression case */ | 642 png_uint_32 avail = (sizeof comp->output); |
358 if (comp->input) | 643 png_compression_buffer *next = png_ptr->zbuffer_list; |
359 { | 644 |
360 png_write_chunk_data(png_ptr, (png_bytep)comp->input, | 645 for (;;) |
361 (png_size_t)comp->input_len); | 646 { |
362 return; | 647 if (avail > output_len) |
363 } | 648 avail = output_len; |
364 | 649 |
365 /* Write saved output buffers, if any */ | 650 png_write_chunk_data(png_ptr, output, avail); |
366 for (i = 0; i < comp->num_output_ptr; i++) | 651 |
367 { | 652 output_len -= avail; |
368 png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], | 653 |
369 (png_size_t)png_ptr->zbuf_size); | 654 if (output_len == 0 || next == NULL) |
370 png_free(png_ptr, comp->output_ptr[i]); | 655 break; |
371 comp->output_ptr[i]=NULL; | 656 |
372 } | 657 avail = png_ptr->zbuffer_size; |
373 if (comp->max_output_ptr != 0) | 658 output = next->output; |
374 png_free(png_ptr, comp->output_ptr); | 659 next = next->next; |
375 comp->output_ptr=NULL; | 660 } |
376 /* Write anything left in zbuf */ | 661 |
377 if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) | 662 /* This is an internal error; 'next' must have been NULL! */ |
378 png_write_chunk_data(png_ptr, png_ptr->zbuf, | 663 if (output_len > 0) |
379 (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); | 664 png_error(png_ptr, "error writing ancillary chunked compressed data"); |
380 | 665 } |
381 /* Reset zlib for another zTXt/iTXt or image data */ | 666 #endif /* WRITE_COMPRESSED_TEXT */ |
382 deflateReset(&png_ptr->zstream); | |
383 png_ptr->zstream.data_type = Z_BINARY; | |
384 } | |
385 #endif | |
386 | 667 |
387 /* Write the IHDR chunk, and update the png_struct with the necessary | 668 /* Write the IHDR chunk, and update the png_struct with the necessary |
388 * information. Note that the rest of this code depends upon this | 669 * information. Note that the rest of this code depends upon this |
389 * information being correct. | 670 * information being correct. |
390 */ | 671 */ |
391 void /* PRIVATE */ | 672 void /* PRIVATE */ |
392 png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, | 673 png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, |
393 int bit_depth, int color_type, int compression_type, int filter_type, | 674 int bit_depth, int color_type, int compression_type, int filter_type, |
394 int interlace_type) | 675 int interlace_type) |
395 { | 676 { |
396 #ifdef PNG_USE_LOCAL_ARRAYS | |
397 PNG_IHDR; | |
398 #endif | |
399 int ret; | |
400 | |
401 png_byte buf[13]; /* Buffer to store the IHDR info */ | 677 png_byte buf[13]; /* Buffer to store the IHDR info */ |
402 | 678 |
403 png_debug(1, "in png_write_IHDR"); | 679 png_debug(1, "in png_write_IHDR"); |
404 | 680 |
405 /* Check that we have valid input data from the application info */ | 681 /* Check that we have valid input data from the application info */ |
406 switch (color_type) | 682 switch (color_type) |
407 { | 683 { |
408 case PNG_COLOR_TYPE_GRAY: | 684 case PNG_COLOR_TYPE_GRAY: |
409 switch (bit_depth) | 685 switch (bit_depth) |
410 { | 686 { |
411 case 1: | 687 case 1: |
412 case 2: | 688 case 2: |
413 case 4: | 689 case 4: |
414 case 8: | 690 case 8: |
415 case 16: png_ptr->channels = 1; break; | 691 #ifdef PNG_WRITE_16BIT_SUPPORTED |
416 default: png_error(png_ptr, | 692 case 16: |
417 "Invalid bit depth for grayscale image"); | 693 #endif |
| 694 png_ptr->channels = 1; break; |
| 695 |
| 696 default: |
| 697 png_error(png_ptr, |
| 698 "Invalid bit depth for grayscale image"); |
418 } | 699 } |
419 break; | 700 break; |
| 701 |
420 case PNG_COLOR_TYPE_RGB: | 702 case PNG_COLOR_TYPE_RGB: |
| 703 #ifdef PNG_WRITE_16BIT_SUPPORTED |
421 if (bit_depth != 8 && bit_depth != 16) | 704 if (bit_depth != 8 && bit_depth != 16) |
| 705 #else |
| 706 if (bit_depth != 8) |
| 707 #endif |
422 png_error(png_ptr, "Invalid bit depth for RGB image"); | 708 png_error(png_ptr, "Invalid bit depth for RGB image"); |
| 709 |
423 png_ptr->channels = 3; | 710 png_ptr->channels = 3; |
424 break; | 711 break; |
| 712 |
425 case PNG_COLOR_TYPE_PALETTE: | 713 case PNG_COLOR_TYPE_PALETTE: |
426 switch (bit_depth) | 714 switch (bit_depth) |
427 { | 715 { |
428 case 1: | 716 case 1: |
429 case 2: | 717 case 2: |
430 case 4: | 718 case 4: |
431 case 8: png_ptr->channels = 1; break; | 719 case 8: |
432 default: png_error(png_ptr, "Invalid bit depth for paletted image"); | 720 png_ptr->channels = 1; |
| 721 break; |
| 722 |
| 723 default: |
| 724 png_error(png_ptr, "Invalid bit depth for paletted image"); |
433 } | 725 } |
434 break; | 726 break; |
| 727 |
435 case PNG_COLOR_TYPE_GRAY_ALPHA: | 728 case PNG_COLOR_TYPE_GRAY_ALPHA: |
436 if (bit_depth != 8 && bit_depth != 16) | 729 if (bit_depth != 8 && bit_depth != 16) |
437 png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); | 730 png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); |
| 731 |
438 png_ptr->channels = 2; | 732 png_ptr->channels = 2; |
439 break; | 733 break; |
| 734 |
440 case PNG_COLOR_TYPE_RGB_ALPHA: | 735 case PNG_COLOR_TYPE_RGB_ALPHA: |
| 736 #ifdef PNG_WRITE_16BIT_SUPPORTED |
441 if (bit_depth != 8 && bit_depth != 16) | 737 if (bit_depth != 8 && bit_depth != 16) |
| 738 #else |
| 739 if (bit_depth != 8) |
| 740 #endif |
442 png_error(png_ptr, "Invalid bit depth for RGBA image"); | 741 png_error(png_ptr, "Invalid bit depth for RGBA image"); |
| 742 |
443 png_ptr->channels = 4; | 743 png_ptr->channels = 4; |
444 break; | 744 break; |
| 745 |
445 default: | 746 default: |
446 png_error(png_ptr, "Invalid image color type specified"); | 747 png_error(png_ptr, "Invalid image color type specified"); |
447 } | 748 } |
448 | 749 |
449 if (compression_type != PNG_COMPRESSION_TYPE_BASE) | 750 if (compression_type != PNG_COMPRESSION_TYPE_BASE) |
450 { | 751 { |
451 png_warning(png_ptr, "Invalid compression type specified"); | 752 png_warning(png_ptr, "Invalid compression type specified"); |
452 compression_type = PNG_COMPRESSION_TYPE_BASE; | 753 compression_type = PNG_COMPRESSION_TYPE_BASE; |
453 } | 754 } |
454 | 755 |
455 /* Write filter_method 64 (intrapixel differencing) only if | 756 /* Write filter_method 64 (intrapixel differencing) only if |
456 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and | 757 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and |
457 * 2. Libpng did not write a PNG signature (this filter_method is only | 758 * 2. Libpng did not write a PNG signature (this filter_method is only |
458 * used in PNG datastreams that are embedded in MNG datastreams) and | 759 * used in PNG datastreams that are embedded in MNG datastreams) and |
459 * 3. The application called png_permit_mng_features with a mask that | 760 * 3. The application called png_permit_mng_features with a mask that |
460 * included PNG_FLAG_MNG_FILTER_64 and | 761 * included PNG_FLAG_MNG_FILTER_64 and |
461 * 4. The filter_method is 64 and | 762 * 4. The filter_method is 64 and |
462 * 5. The color_type is RGB or RGBA | 763 * 5. The color_type is RGB or RGBA |
463 */ | 764 */ |
464 if ( | 765 if ( |
465 #ifdef PNG_MNG_FEATURES_SUPPORTED | 766 #ifdef PNG_MNG_FEATURES_SUPPORTED |
466 !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && | 767 !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && |
467 ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && | 768 ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && |
468 (color_type == PNG_COLOR_TYPE_RGB || | 769 (color_type == PNG_COLOR_TYPE_RGB || |
469 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && | 770 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && |
470 (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && | 771 (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && |
471 #endif | 772 #endif |
472 filter_type != PNG_FILTER_TYPE_BASE) | 773 filter_type != PNG_FILTER_TYPE_BASE) |
473 { | 774 { |
474 png_warning(png_ptr, "Invalid filter type specified"); | 775 png_warning(png_ptr, "Invalid filter type specified"); |
475 filter_type = PNG_FILTER_TYPE_BASE; | 776 filter_type = PNG_FILTER_TYPE_BASE; |
476 } | 777 } |
477 | 778 |
478 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 779 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
479 if (interlace_type != PNG_INTERLACE_NONE && | 780 if (interlace_type != PNG_INTERLACE_NONE && |
480 interlace_type != PNG_INTERLACE_ADAM7) | 781 interlace_type != PNG_INTERLACE_ADAM7) |
481 { | 782 { |
482 png_warning(png_ptr, "Invalid interlace type specified"); | 783 png_warning(png_ptr, "Invalid interlace type specified"); |
483 interlace_type = PNG_INTERLACE_ADAM7; | 784 interlace_type = PNG_INTERLACE_ADAM7; |
484 } | 785 } |
485 #else | 786 #else |
486 interlace_type=PNG_INTERLACE_NONE; | 787 interlace_type=PNG_INTERLACE_NONE; |
487 #endif | 788 #endif |
488 | 789 |
489 /* Save the relevent information */ | 790 /* Save the relevant information */ |
490 png_ptr->bit_depth = (png_byte)bit_depth; | 791 png_ptr->bit_depth = (png_byte)bit_depth; |
491 png_ptr->color_type = (png_byte)color_type; | 792 png_ptr->color_type = (png_byte)color_type; |
492 png_ptr->interlaced = (png_byte)interlace_type; | 793 png_ptr->interlaced = (png_byte)interlace_type; |
493 #ifdef PNG_MNG_FEATURES_SUPPORTED | 794 #ifdef PNG_MNG_FEATURES_SUPPORTED |
494 png_ptr->filter_type = (png_byte)filter_type; | 795 png_ptr->filter_type = (png_byte)filter_type; |
495 #endif | 796 #endif |
496 png_ptr->compression_type = (png_byte)compression_type; | 797 png_ptr->compression_type = (png_byte)compression_type; |
497 png_ptr->width = width; | 798 png_ptr->width = width; |
498 png_ptr->height = height; | 799 png_ptr->height = height; |
499 | 800 |
500 png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); | 801 png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); |
501 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); | 802 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); |
502 /* Set the usr info, so any transformations can modify it */ | 803 /* Set the usr info, so any transformations can modify it */ |
503 png_ptr->usr_width = png_ptr->width; | 804 png_ptr->usr_width = png_ptr->width; |
504 png_ptr->usr_bit_depth = png_ptr->bit_depth; | 805 png_ptr->usr_bit_depth = png_ptr->bit_depth; |
505 png_ptr->usr_channels = png_ptr->channels; | 806 png_ptr->usr_channels = png_ptr->channels; |
506 | 807 |
507 /* Pack the header information into the buffer */ | 808 /* Pack the header information into the buffer */ |
508 png_save_uint_32(buf, width); | 809 png_save_uint_32(buf, width); |
509 png_save_uint_32(buf + 4, height); | 810 png_save_uint_32(buf + 4, height); |
510 buf[8] = (png_byte)bit_depth; | 811 buf[8] = (png_byte)bit_depth; |
511 buf[9] = (png_byte)color_type; | 812 buf[9] = (png_byte)color_type; |
512 buf[10] = (png_byte)compression_type; | 813 buf[10] = (png_byte)compression_type; |
513 buf[11] = (png_byte)filter_type; | 814 buf[11] = (png_byte)filter_type; |
514 buf[12] = (png_byte)interlace_type; | 815 buf[12] = (png_byte)interlace_type; |
515 | 816 |
516 /* Write the chunk */ | 817 /* Write the chunk */ |
517 png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); | 818 png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); |
518 | 819 |
519 /* Initialize zlib with PNG info */ | 820 if ((png_ptr->do_filter) == PNG_NO_FILTERS) |
520 png_ptr->zstream.zalloc = png_zalloc; | |
521 png_ptr->zstream.zfree = png_zfree; | |
522 png_ptr->zstream.opaque = (voidpf)png_ptr; | |
523 if (!(png_ptr->do_filter)) | |
524 { | 821 { |
525 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || | 822 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || |
526 png_ptr->bit_depth < 8) | 823 png_ptr->bit_depth < 8) |
527 png_ptr->do_filter = PNG_FILTER_NONE; | 824 png_ptr->do_filter = PNG_FILTER_NONE; |
| 825 |
528 else | 826 else |
529 png_ptr->do_filter = PNG_ALL_FILTERS; | 827 png_ptr->do_filter = PNG_ALL_FILTERS; |
530 } | 828 } |
531 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) | |
532 { | |
533 if (png_ptr->do_filter != PNG_FILTER_NONE) | |
534 png_ptr->zlib_strategy = Z_FILTERED; | |
535 else | |
536 png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; | |
537 } | |
538 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) | |
539 png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; | |
540 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) | |
541 png_ptr->zlib_mem_level = 8; | |
542 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) | |
543 png_ptr->zlib_window_bits = 15; | |
544 if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) | |
545 png_ptr->zlib_method = 8; | |
546 ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, | |
547 png_ptr->zlib_method, png_ptr->zlib_window_bits, | |
548 png_ptr->zlib_mem_level, png_ptr->zlib_strategy); | |
549 if (ret != Z_OK) | |
550 { | |
551 if (ret == Z_VERSION_ERROR) png_error(png_ptr, | |
552 "zlib failed to initialize compressor -- version error"); | |
553 if (ret == Z_STREAM_ERROR) png_error(png_ptr, | |
554 "zlib failed to initialize compressor -- stream error"); | |
555 if (ret == Z_MEM_ERROR) png_error(png_ptr, | |
556 "zlib failed to initialize compressor -- mem error"); | |
557 png_error(png_ptr, "zlib failed to initialize compressor"); | |
558 } | |
559 png_ptr->zstream.next_out = png_ptr->zbuf; | |
560 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | |
561 /* libpng is not interested in zstream.data_type */ | |
562 /* Set it to a predefined value, to avoid its evaluation inside zlib */ | |
563 png_ptr->zstream.data_type = Z_BINARY; | |
564 | 829 |
565 png_ptr->mode = PNG_HAVE_IHDR; | 830 png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ |
566 } | 831 } |
567 | 832 |
568 /* Write the palette. We are careful not to trust png_color to be in the | 833 /* Write the palette. We are careful not to trust png_color to be in the |
569 * correct order for PNG, so people can redefine it to any convenient | 834 * correct order for PNG, so people can redefine it to any convenient |
570 * structure. | 835 * structure. |
571 */ | 836 */ |
572 void /* PRIVATE */ | 837 void /* PRIVATE */ |
573 png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) | 838 png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, |
| 839 png_uint_32 num_pal) |
574 { | 840 { |
575 #ifdef PNG_USE_LOCAL_ARRAYS | |
576 PNG_PLTE; | |
577 #endif | |
578 png_uint_32 max_palette_length, i; | 841 png_uint_32 max_palette_length, i; |
579 png_colorp pal_ptr; | 842 png_const_colorp pal_ptr; |
580 png_byte buf[3]; | 843 png_byte buf[3]; |
581 | 844 |
582 png_debug(1, "in png_write_PLTE"); | 845 png_debug(1, "in png_write_PLTE"); |
583 | 846 |
584 max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? | 847 max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? |
585 (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; | 848 (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; |
586 | 849 |
587 if (( | 850 if (( |
588 #ifdef PNG_MNG_FEATURES_SUPPORTED | 851 #ifdef PNG_MNG_FEATURES_SUPPORTED |
589 !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && | 852 (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 && |
590 #endif | 853 #endif |
591 num_pal == 0) || num_pal > max_palette_length) | 854 num_pal == 0) || num_pal > max_palette_length) |
592 { | 855 { |
593 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) | 856 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
594 { | 857 { |
595 png_error(png_ptr, "Invalid number of colors in palette"); | 858 png_error(png_ptr, "Invalid number of colors in palette"); |
596 } | 859 } |
597 else | 860 |
598 { | 861 else |
599 png_warning(png_ptr, "Invalid number of colors in palette"); | 862 { |
600 return; | 863 png_warning(png_ptr, "Invalid number of colors in palette"); |
601 } | 864 return; |
| 865 } |
602 } | 866 } |
603 | 867 |
604 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) | 868 if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) |
605 { | 869 { |
606 png_warning(png_ptr, | 870 png_warning(png_ptr, |
607 "Ignoring request to write a PLTE chunk in grayscale PNG"); | 871 "Ignoring request to write a PLTE chunk in grayscale PNG"); |
| 872 |
608 return; | 873 return; |
609 } | 874 } |
610 | 875 |
611 png_ptr->num_palette = (png_uint_16)num_pal; | 876 png_ptr->num_palette = (png_uint_16)num_pal; |
612 png_debug1(3, "num_palette = %d", png_ptr->num_palette); | 877 png_debug1(3, "num_palette = %d", png_ptr->num_palette); |
613 | 878 |
614 png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, | 879 png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); |
615 (png_uint_32)(num_pal * 3)); | |
616 #ifdef PNG_POINTER_INDEXING_SUPPORTED | 880 #ifdef PNG_POINTER_INDEXING_SUPPORTED |
| 881 |
617 for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) | 882 for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) |
618 { | 883 { |
619 buf[0] = pal_ptr->red; | 884 buf[0] = pal_ptr->red; |
620 buf[1] = pal_ptr->green; | 885 buf[1] = pal_ptr->green; |
621 buf[2] = pal_ptr->blue; | 886 buf[2] = pal_ptr->blue; |
622 png_write_chunk_data(png_ptr, buf, (png_size_t)3); | 887 png_write_chunk_data(png_ptr, buf, (png_size_t)3); |
623 } | 888 } |
| 889 |
624 #else | 890 #else |
625 /* This is a little slower but some buggy compilers need to do this | 891 /* This is a little slower but some buggy compilers need to do this |
626 * instead | 892 * instead |
627 */ | 893 */ |
628 pal_ptr=palette; | 894 pal_ptr=palette; |
| 895 |
629 for (i = 0; i < num_pal; i++) | 896 for (i = 0; i < num_pal; i++) |
630 { | 897 { |
631 buf[0] = pal_ptr[i].red; | 898 buf[0] = pal_ptr[i].red; |
632 buf[1] = pal_ptr[i].green; | 899 buf[1] = pal_ptr[i].green; |
633 buf[2] = pal_ptr[i].blue; | 900 buf[2] = pal_ptr[i].blue; |
634 png_write_chunk_data(png_ptr, buf, (png_size_t)3); | 901 png_write_chunk_data(png_ptr, buf, (png_size_t)3); |
635 } | 902 } |
| 903 |
636 #endif | 904 #endif |
637 png_write_chunk_end(png_ptr); | 905 png_write_chunk_end(png_ptr); |
638 png_ptr->mode |= PNG_HAVE_PLTE; | 906 png_ptr->mode |= PNG_HAVE_PLTE; |
639 } | 907 } |
640 | 908 |
641 /* Write an IDAT chunk */ | 909 /* This is similar to png_text_compress, above, except that it does not require |
642 void /* PRIVATE */ | 910 * all of the data at once and, instead of buffering the compressed result, |
643 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) | 911 * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out |
644 { | 912 * because it calls the write interface. As a result it does its own error |
645 #ifdef PNG_USE_LOCAL_ARRAYS | 913 * reporting and does not return an error code. In the event of error it will |
646 PNG_IDAT; | 914 * just call png_error. The input data length may exceed 32-bits. The 'flush' |
647 #endif | 915 * parameter is exactly the same as that to deflate, with the following |
648 | 916 * meanings: |
649 png_debug(1, "in png_write_IDAT"); | 917 * |
650 | 918 * Z_NO_FLUSH: normal incremental output of compressed data |
651 /* Optimize the CMF field in the zlib stream. */ | 919 * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush |
652 /* This hack of the zlib stream is compliant to the stream specification. */ | 920 * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up |
653 if (!(png_ptr->mode & PNG_HAVE_IDAT) && | 921 * |
654 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) | 922 * The routine manages the acquire and release of the png_ptr->zstream by |
| 923 * checking and (at the end) clearing png_ptr->zowner; it does some sanity |
| 924 * checks on the 'mode' flags while doing this. |
| 925 */ |
| 926 void /* PRIVATE */ |
| 927 png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, |
| 928 png_alloc_size_t input_len, int flush) |
| 929 { |
| 930 if (png_ptr->zowner != png_IDAT) |
655 { | 931 { |
656 unsigned int z_cmf = data[0]; /* zlib compression method and flags */ | 932 /* First time. Ensure we have a temporary buffer for compression and |
657 if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) | 933 * trim the buffer list if it has more than one entry to free memory. |
658 { | 934 * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been |
659 /* Avoid memory underflows and multiplication overflows. | 935 * created at this point, but the check here is quick and safe. |
660 * | 936 */ |
661 * The conditions below are practically always satisfied; | 937 if (png_ptr->zbuffer_list == NULL) |
662 * however, they still must be checked. | 938 { |
663 */ | 939 png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, |
664 if (length >= 2 && | 940 png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); |
665 png_ptr->height < 16384 && png_ptr->width < 16384) | 941 png_ptr->zbuffer_list->next = NULL; |
| 942 } |
| 943 |
| 944 else |
| 945 png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); |
| 946 |
| 947 /* It is a terminal error if we can't claim the zstream. */ |
| 948 if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) |
| 949 png_error(png_ptr, png_ptr->zstream.msg); |
| 950 |
| 951 /* The output state is maintained in png_ptr->zstream, so it must be |
| 952 * initialized here after the claim. |
| 953 */ |
| 954 png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; |
| 955 png_ptr->zstream.avail_out = png_ptr->zbuffer_size; |
| 956 } |
| 957 |
| 958 /* Now loop reading and writing until all the input is consumed or an error |
| 959 * terminates the operation. The _out values are maintained across calls to |
| 960 * this function, but the input must be reset each time. |
| 961 */ |
| 962 png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); |
| 963 png_ptr->zstream.avail_in = 0; /* set below */ |
| 964 for (;;) |
| 965 { |
| 966 int ret; |
| 967 |
| 968 /* INPUT: from the row data */ |
| 969 uInt avail = ZLIB_IO_MAX; |
| 970 |
| 971 if (avail > input_len) |
| 972 avail = (uInt)input_len; /* safe because of the check */ |
| 973 |
| 974 png_ptr->zstream.avail_in = avail; |
| 975 input_len -= avail; |
| 976 |
| 977 ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); |
| 978 |
| 979 /* Include as-yet unconsumed input */ |
| 980 input_len += png_ptr->zstream.avail_in; |
| 981 png_ptr->zstream.avail_in = 0; |
| 982 |
| 983 /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note |
| 984 * that these two zstream fields are preserved across the calls, therefore |
| 985 * there is no need to set these up on entry to the loop. |
| 986 */ |
| 987 if (png_ptr->zstream.avail_out == 0) |
| 988 { |
| 989 png_bytep data = png_ptr->zbuffer_list->output; |
| 990 uInt size = png_ptr->zbuffer_size; |
| 991 |
| 992 /* Write an IDAT containing the data then reset the buffer. The |
| 993 * first IDAT may need deflate header optimization. |
| 994 */ |
| 995 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
| 996 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 && |
| 997 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) |
| 998 optimize_cmf(data, png_image_size(png_ptr)); |
| 999 #endif |
| 1000 |
| 1001 png_write_complete_chunk(png_ptr, png_IDAT, data, size); |
| 1002 png_ptr->mode |= PNG_HAVE_IDAT; |
| 1003 |
| 1004 png_ptr->zstream.next_out = data; |
| 1005 png_ptr->zstream.avail_out = size; |
| 1006 |
| 1007 /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with |
| 1008 * the same flush parameter until it has finished output, for NO_FLUSH |
| 1009 * it doesn't matter. |
| 1010 */ |
| 1011 if (ret == Z_OK && flush != Z_NO_FLUSH) |
| 1012 continue; |
| 1013 } |
| 1014 |
| 1015 /* The order of these checks doesn't matter much; it just affects which |
| 1016 * possible error might be detected if multiple things go wrong at once. |
| 1017 */ |
| 1018 if (ret == Z_OK) /* most likely return code! */ |
| 1019 { |
| 1020 /* If all the input has been consumed then just return. If Z_FINISH |
| 1021 * was used as the flush parameter something has gone wrong if we get |
| 1022 * here. |
| 1023 */ |
| 1024 if (input_len == 0) |
666 { | 1025 { |
667 png_uint_32 uncompressed_idat_size = png_ptr->height * | 1026 if (flush == Z_FINISH) |
668 ((png_ptr->width * | 1027 png_error(png_ptr, "Z_OK on Z_FINISH with output space"); |
669 png_ptr->channels * png_ptr->bit_depth + 15) >> 3); | 1028 |
670 unsigned int z_cinfo = z_cmf >> 4; | 1029 return; |
671 unsigned int half_z_window_size = 1 << (z_cinfo + 7); | |
672 while (uncompressed_idat_size <= half_z_window_size && | |
673 half_z_window_size >= 256) | |
674 { | |
675 z_cinfo--; | |
676 half_z_window_size >>= 1; | |
677 } | |
678 z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); | |
679 if (data[0] != (png_byte)z_cmf) | |
680 { | |
681 data[0] = (png_byte)z_cmf; | |
682 data[1] &= 0xe0; | |
683 data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); | |
684 } | |
685 } | 1030 } |
686 } | 1031 } |
| 1032 |
| 1033 else if (ret == Z_STREAM_END && flush == Z_FINISH) |
| 1034 { |
| 1035 /* This is the end of the IDAT data; any pending output must be |
| 1036 * flushed. For small PNG files we may still be at the beginning. |
| 1037 */ |
| 1038 png_bytep data = png_ptr->zbuffer_list->output; |
| 1039 uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; |
| 1040 |
| 1041 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED |
| 1042 if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 && |
| 1043 png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) |
| 1044 optimize_cmf(data, png_image_size(png_ptr)); |
| 1045 #endif |
| 1046 |
| 1047 png_write_complete_chunk(png_ptr, png_IDAT, data, size); |
| 1048 png_ptr->zstream.avail_out = 0; |
| 1049 png_ptr->zstream.next_out = NULL; |
| 1050 png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; |
| 1051 |
| 1052 png_ptr->zowner = 0; /* Release the stream */ |
| 1053 return; |
| 1054 } |
| 1055 |
687 else | 1056 else |
688 png_error(png_ptr, | 1057 { |
689 "Invalid zlib compression method or flags in IDAT"); | 1058 /* This is an error condition. */ |
690 } | 1059 png_zstream_error(png_ptr, ret); |
691 | 1060 png_error(png_ptr, png_ptr->zstream.msg); |
692 png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); | 1061 } |
693 png_ptr->mode |= PNG_HAVE_IDAT; | 1062 } |
694 } | 1063 } |
695 | 1064 |
696 /* Write an IEND chunk */ | 1065 /* Write an IEND chunk */ |
697 void /* PRIVATE */ | 1066 void /* PRIVATE */ |
698 png_write_IEND(png_structp png_ptr) | 1067 png_write_IEND(png_structrp png_ptr) |
699 { | 1068 { |
700 #ifdef PNG_USE_LOCAL_ARRAYS | |
701 PNG_IEND; | |
702 #endif | |
703 | |
704 png_debug(1, "in png_write_IEND"); | 1069 png_debug(1, "in png_write_IEND"); |
705 | 1070 |
706 png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL, | 1071 png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); |
707 (png_size_t)0); | |
708 png_ptr->mode |= PNG_HAVE_IEND; | 1072 png_ptr->mode |= PNG_HAVE_IEND; |
709 } | 1073 } |
710 | 1074 |
711 #ifdef PNG_WRITE_gAMA_SUPPORTED | 1075 #ifdef PNG_WRITE_gAMA_SUPPORTED |
712 /* Write a gAMA chunk */ | 1076 /* Write a gAMA chunk */ |
713 #ifdef PNG_FLOATING_POINT_SUPPORTED | 1077 void /* PRIVATE */ |
714 void /* PRIVATE */ | 1078 png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) |
715 png_write_gAMA(png_structp png_ptr, double file_gamma) | 1079 { |
716 { | |
717 #ifdef PNG_USE_LOCAL_ARRAYS | |
718 PNG_gAMA; | |
719 #endif | |
720 png_uint_32 igamma; | |
721 png_byte buf[4]; | |
722 | |
723 png_debug(1, "in png_write_gAMA"); | |
724 | |
725 /* file_gamma is saved in 1/100,000ths */ | |
726 igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); | |
727 png_save_uint_32(buf, igamma); | |
728 png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); | |
729 } | |
730 #endif | |
731 #ifdef PNG_FIXED_POINT_SUPPORTED | |
732 void /* PRIVATE */ | |
733 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) | |
734 { | |
735 #ifdef PNG_USE_LOCAL_ARRAYS | |
736 PNG_gAMA; | |
737 #endif | |
738 png_byte buf[4]; | 1080 png_byte buf[4]; |
739 | 1081 |
740 png_debug(1, "in png_write_gAMA"); | 1082 png_debug(1, "in png_write_gAMA"); |
741 | 1083 |
742 /* file_gamma is saved in 1/100,000ths */ | 1084 /* file_gamma is saved in 1/100,000ths */ |
743 png_save_uint_32(buf, (png_uint_32)file_gamma); | 1085 png_save_uint_32(buf, (png_uint_32)file_gamma); |
744 png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); | 1086 png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); |
745 } | 1087 } |
746 #endif | |
747 #endif | 1088 #endif |
748 | 1089 |
749 #ifdef PNG_WRITE_sRGB_SUPPORTED | 1090 #ifdef PNG_WRITE_sRGB_SUPPORTED |
750 /* Write a sRGB chunk */ | 1091 /* Write a sRGB chunk */ |
751 void /* PRIVATE */ | 1092 void /* PRIVATE */ |
752 png_write_sRGB(png_structp png_ptr, int srgb_intent) | 1093 png_write_sRGB(png_structrp png_ptr, int srgb_intent) |
753 { | 1094 { |
754 #ifdef PNG_USE_LOCAL_ARRAYS | |
755 PNG_sRGB; | |
756 #endif | |
757 png_byte buf[1]; | 1095 png_byte buf[1]; |
758 | 1096 |
759 png_debug(1, "in png_write_sRGB"); | 1097 png_debug(1, "in png_write_sRGB"); |
760 | 1098 |
761 if (srgb_intent >= PNG_sRGB_INTENT_LAST) | 1099 if (srgb_intent >= PNG_sRGB_INTENT_LAST) |
762 png_warning(png_ptr, | 1100 png_warning(png_ptr, |
763 "Invalid sRGB rendering intent specified"); | 1101 "Invalid sRGB rendering intent specified"); |
| 1102 |
764 buf[0]=(png_byte)srgb_intent; | 1103 buf[0]=(png_byte)srgb_intent; |
765 png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); | 1104 png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); |
766 } | 1105 } |
767 #endif | 1106 #endif |
768 | 1107 |
769 #ifdef PNG_WRITE_iCCP_SUPPORTED | 1108 #ifdef PNG_WRITE_iCCP_SUPPORTED |
770 /* Write an iCCP chunk */ | 1109 /* Write an iCCP chunk */ |
771 void /* PRIVATE */ | 1110 void /* PRIVATE */ |
772 png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, | 1111 png_write_iCCP(png_structrp png_ptr, png_const_charp name, |
773 png_charp profile, int profile_len) | 1112 png_const_bytep profile) |
774 { | 1113 { |
775 #ifdef PNG_USE_LOCAL_ARRAYS | 1114 png_uint_32 name_len; |
776 PNG_iCCP; | 1115 png_uint_32 profile_len; |
777 #endif | 1116 png_byte new_name[81]; /* 1 byte for the compression byte */ |
778 png_size_t name_len; | |
779 png_charp new_name; | |
780 compression_state comp; | 1117 compression_state comp; |
781 int embedded_profile_len = 0; | 1118 png_uint_32 temp; |
782 | 1119 |
783 png_debug(1, "in png_write_iCCP"); | 1120 png_debug(1, "in png_write_iCCP"); |
784 | 1121 |
785 comp.num_output_ptr = 0; | 1122 /* These are all internal problems: the profile should have been checked |
786 comp.max_output_ptr = 0; | 1123 * before when it was stored. |
787 comp.output_ptr = NULL; | 1124 */ |
788 comp.input = NULL; | |
789 comp.input_len = 0; | |
790 | |
791 if ((name_len = png_check_keyword(png_ptr, name, | |
792 &new_name)) == 0) | |
793 return; | |
794 | |
795 if (compression_type != PNG_COMPRESSION_TYPE_BASE) | |
796 png_warning(png_ptr, "Unknown compression type in iCCP chunk"); | |
797 | |
798 if (profile == NULL) | 1125 if (profile == NULL) |
799 profile_len = 0; | 1126 png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ |
800 | 1127 |
801 if (profile_len > 3) | 1128 profile_len = png_get_uint_32(profile); |
802 embedded_profile_len = | 1129 |
803 ((*( (png_bytep)profile ))<<24) | | 1130 if (profile_len < 132) |
804 ((*( (png_bytep)profile + 1))<<16) | | 1131 png_error(png_ptr, "ICC profile too short"); |
805 ((*( (png_bytep)profile + 2))<< 8) | | 1132 |
806 ((*( (png_bytep)profile + 3)) ); | 1133 temp = (png_uint_32) (*(profile+8)); |
807 | 1134 if (temp > 3 && (profile_len & 0x03)) |
808 if (embedded_profile_len < 0) | 1135 png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); |
| 1136 |
809 { | 1137 { |
810 png_warning(png_ptr, | 1138 png_uint_32 embedded_profile_len = png_get_uint_32(profile); |
811 "Embedded profile length in iCCP chunk is negative"); | 1139 |
812 png_free(png_ptr, new_name); | 1140 if (profile_len != embedded_profile_len) |
813 return; | 1141 png_error(png_ptr, "Profile length does not match profile"); |
814 } | 1142 } |
815 | 1143 |
816 if (profile_len < embedded_profile_len) | 1144 name_len = png_check_keyword(png_ptr, name, new_name); |
817 { | 1145 |
818 png_warning(png_ptr, | 1146 if (name_len == 0) |
819 "Embedded profile length too large in iCCP chunk"); | 1147 png_error(png_ptr, "iCCP: invalid keyword"); |
820 png_free(png_ptr, new_name); | 1148 |
821 return; | 1149 new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; |
822 } | |
823 | |
824 if (profile_len > embedded_profile_len) | |
825 { | |
826 png_warning(png_ptr, | |
827 "Truncating profile to actual length in iCCP chunk"); | |
828 profile_len = embedded_profile_len; | |
829 } | |
830 | |
831 if (profile_len) | |
832 profile_len = png_text_compress(png_ptr, profile, | |
833 (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); | |
834 | 1150 |
835 /* Make sure we include the NULL after the name and the compression type */ | 1151 /* Make sure we include the NULL after the name and the compression type */ |
836 png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, | 1152 ++name_len; |
837 (png_uint_32)(name_len + profile_len + 2)); | 1153 |
838 new_name[name_len + 1] = 0x00; | 1154 png_text_compress_init(&comp, profile, profile_len); |
839 png_write_chunk_data(png_ptr, (png_bytep)new_name, | 1155 |
840 (png_size_t)(name_len + 2)); | 1156 /* Allow for keyword terminator and compression byte */ |
841 | 1157 if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) |
842 if (profile_len) | 1158 png_error(png_ptr, png_ptr->zstream.msg); |
843 png_write_compressed_data_out(png_ptr, &comp); | 1159 |
| 1160 png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); |
| 1161 |
| 1162 png_write_chunk_data(png_ptr, new_name, name_len); |
| 1163 |
| 1164 png_write_compressed_data_out(png_ptr, &comp); |
844 | 1165 |
845 png_write_chunk_end(png_ptr); | 1166 png_write_chunk_end(png_ptr); |
846 png_free(png_ptr, new_name); | |
847 } | 1167 } |
848 #endif | 1168 #endif |
849 | 1169 |
850 #ifdef PNG_WRITE_sPLT_SUPPORTED | 1170 #ifdef PNG_WRITE_sPLT_SUPPORTED |
851 /* Write a sPLT chunk */ | 1171 /* Write a sPLT chunk */ |
852 void /* PRIVATE */ | 1172 void /* PRIVATE */ |
853 png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) | 1173 png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) |
854 { | 1174 { |
855 #ifdef PNG_USE_LOCAL_ARRAYS | 1175 png_uint_32 name_len; |
856 PNG_sPLT; | 1176 png_byte new_name[80]; |
857 #endif | |
858 png_size_t name_len; | |
859 png_charp new_name; | |
860 png_byte entrybuf[10]; | 1177 png_byte entrybuf[10]; |
861 int entry_size = (spalette->depth == 8 ? 6 : 10); | 1178 png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); |
862 int palette_size = entry_size * spalette->nentries; | 1179 png_size_t palette_size = entry_size * spalette->nentries; |
863 png_sPLT_entryp ep; | 1180 png_sPLT_entryp ep; |
864 #ifndef PNG_POINTER_INDEXING_SUPPORTED | 1181 #ifndef PNG_POINTER_INDEXING_SUPPORTED |
865 int i; | 1182 int i; |
866 #endif | 1183 #endif |
867 | 1184 |
868 png_debug(1, "in png_write_sPLT"); | 1185 png_debug(1, "in png_write_sPLT"); |
869 | 1186 |
870 if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) | 1187 name_len = png_check_keyword(png_ptr, spalette->name, new_name); |
871 return; | 1188 |
| 1189 if (name_len == 0) |
| 1190 png_error(png_ptr, "sPLT: invalid keyword"); |
872 | 1191 |
873 /* Make sure we include the NULL after the name */ | 1192 /* Make sure we include the NULL after the name */ |
874 png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, | 1193 png_write_chunk_header(png_ptr, png_sPLT, |
875 (png_uint_32)(name_len + 2 + palette_size)); | 1194 (png_uint_32)(name_len + 2 + palette_size)); |
| 1195 |
876 png_write_chunk_data(png_ptr, (png_bytep)new_name, | 1196 png_write_chunk_data(png_ptr, (png_bytep)new_name, |
877 (png_size_t)(name_len + 1)); | 1197 (png_size_t)(name_len + 1)); |
878 png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); | 1198 |
| 1199 png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); |
879 | 1200 |
880 /* Loop through each palette entry, writing appropriately */ | 1201 /* Loop through each palette entry, writing appropriately */ |
881 #ifdef PNG_POINTER_INDEXING_SUPPORTED | 1202 #ifdef PNG_POINTER_INDEXING_SUPPORTED |
882 for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) | 1203 for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) |
883 { | 1204 { |
884 if (spalette->depth == 8) | 1205 if (spalette->depth == 8) |
885 { | 1206 { |
886 entrybuf[0] = (png_byte)ep->red; | 1207 entrybuf[0] = (png_byte)ep->red; |
887 entrybuf[1] = (png_byte)ep->green; | 1208 entrybuf[1] = (png_byte)ep->green; |
888 entrybuf[2] = (png_byte)ep->blue; | 1209 entrybuf[2] = (png_byte)ep->blue; |
889 entrybuf[3] = (png_byte)ep->alpha; | 1210 entrybuf[3] = (png_byte)ep->alpha; |
890 png_save_uint_16(entrybuf + 4, ep->frequency); | 1211 png_save_uint_16(entrybuf + 4, ep->frequency); |
891 } | 1212 } |
| 1213 |
892 else | 1214 else |
893 { | 1215 { |
894 png_save_uint_16(entrybuf + 0, ep->red); | 1216 png_save_uint_16(entrybuf + 0, ep->red); |
895 png_save_uint_16(entrybuf + 2, ep->green); | 1217 png_save_uint_16(entrybuf + 2, ep->green); |
896 png_save_uint_16(entrybuf + 4, ep->blue); | 1218 png_save_uint_16(entrybuf + 4, ep->blue); |
897 png_save_uint_16(entrybuf + 6, ep->alpha); | 1219 png_save_uint_16(entrybuf + 6, ep->alpha); |
898 png_save_uint_16(entrybuf + 8, ep->frequency); | 1220 png_save_uint_16(entrybuf + 8, ep->frequency); |
899 } | 1221 } |
900 png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); | 1222 |
| 1223 png_write_chunk_data(png_ptr, entrybuf, entry_size); |
901 } | 1224 } |
902 #else | 1225 #else |
903 ep=spalette->entries; | 1226 ep=spalette->entries; |
904 for (i=0; i>spalette->nentries; i++) | 1227 for (i = 0; i>spalette->nentries; i++) |
905 { | 1228 { |
906 if (spalette->depth == 8) | 1229 if (spalette->depth == 8) |
907 { | 1230 { |
908 entrybuf[0] = (png_byte)ep[i].red; | 1231 entrybuf[0] = (png_byte)ep[i].red; |
909 entrybuf[1] = (png_byte)ep[i].green; | 1232 entrybuf[1] = (png_byte)ep[i].green; |
910 entrybuf[2] = (png_byte)ep[i].blue; | 1233 entrybuf[2] = (png_byte)ep[i].blue; |
911 entrybuf[3] = (png_byte)ep[i].alpha; | 1234 entrybuf[3] = (png_byte)ep[i].alpha; |
912 png_save_uint_16(entrybuf + 4, ep[i].frequency); | 1235 png_save_uint_16(entrybuf + 4, ep[i].frequency); |
913 } | 1236 } |
| 1237 |
914 else | 1238 else |
915 { | 1239 { |
916 png_save_uint_16(entrybuf + 0, ep[i].red); | 1240 png_save_uint_16(entrybuf + 0, ep[i].red); |
917 png_save_uint_16(entrybuf + 2, ep[i].green); | 1241 png_save_uint_16(entrybuf + 2, ep[i].green); |
918 png_save_uint_16(entrybuf + 4, ep[i].blue); | 1242 png_save_uint_16(entrybuf + 4, ep[i].blue); |
919 png_save_uint_16(entrybuf + 6, ep[i].alpha); | 1243 png_save_uint_16(entrybuf + 6, ep[i].alpha); |
920 png_save_uint_16(entrybuf + 8, ep[i].frequency); | 1244 png_save_uint_16(entrybuf + 8, ep[i].frequency); |
921 } | 1245 } |
922 png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); | 1246 |
| 1247 png_write_chunk_data(png_ptr, entrybuf, entry_size); |
923 } | 1248 } |
924 #endif | 1249 #endif |
925 | 1250 |
926 png_write_chunk_end(png_ptr); | 1251 png_write_chunk_end(png_ptr); |
927 png_free(png_ptr, new_name); | |
928 } | 1252 } |
929 #endif | 1253 #endif |
930 | 1254 |
931 #ifdef PNG_WRITE_sBIT_SUPPORTED | 1255 #ifdef PNG_WRITE_sBIT_SUPPORTED |
932 /* Write the sBIT chunk */ | 1256 /* Write the sBIT chunk */ |
933 void /* PRIVATE */ | 1257 void /* PRIVATE */ |
934 png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) | 1258 png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) |
935 { | 1259 { |
936 #ifdef PNG_USE_LOCAL_ARRAYS | |
937 PNG_sBIT; | |
938 #endif | |
939 png_byte buf[4]; | 1260 png_byte buf[4]; |
940 png_size_t size; | 1261 png_size_t size; |
941 | 1262 |
942 png_debug(1, "in png_write_sBIT"); | 1263 png_debug(1, "in png_write_sBIT"); |
943 | 1264 |
944 /* Make sure we don't depend upon the order of PNG_COLOR_8 */ | 1265 /* Make sure we don't depend upon the order of PNG_COLOR_8 */ |
945 if (color_type & PNG_COLOR_MASK_COLOR) | 1266 if ((color_type & PNG_COLOR_MASK_COLOR) != 0) |
946 { | 1267 { |
947 png_byte maxbits; | 1268 png_byte maxbits; |
948 | 1269 |
949 maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : | 1270 maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : |
950 png_ptr->usr_bit_depth); | 1271 png_ptr->usr_bit_depth); |
| 1272 |
951 if (sbit->red == 0 || sbit->red > maxbits || | 1273 if (sbit->red == 0 || sbit->red > maxbits || |
952 sbit->green == 0 || sbit->green > maxbits || | 1274 sbit->green == 0 || sbit->green > maxbits || |
953 sbit->blue == 0 || sbit->blue > maxbits) | 1275 sbit->blue == 0 || sbit->blue > maxbits) |
954 { | 1276 { |
955 png_warning(png_ptr, "Invalid sBIT depth specified"); | 1277 png_warning(png_ptr, "Invalid sBIT depth specified"); |
956 return; | 1278 return; |
957 } | 1279 } |
| 1280 |
958 buf[0] = sbit->red; | 1281 buf[0] = sbit->red; |
959 buf[1] = sbit->green; | 1282 buf[1] = sbit->green; |
960 buf[2] = sbit->blue; | 1283 buf[2] = sbit->blue; |
961 size = 3; | 1284 size = 3; |
962 } | 1285 } |
| 1286 |
963 else | 1287 else |
964 { | 1288 { |
965 if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) | 1289 if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) |
966 { | 1290 { |
967 png_warning(png_ptr, "Invalid sBIT depth specified"); | 1291 png_warning(png_ptr, "Invalid sBIT depth specified"); |
968 return; | 1292 return; |
969 } | 1293 } |
| 1294 |
970 buf[0] = sbit->gray; | 1295 buf[0] = sbit->gray; |
971 size = 1; | 1296 size = 1; |
972 } | 1297 } |
973 | 1298 |
974 if (color_type & PNG_COLOR_MASK_ALPHA) | 1299 if ((color_type & PNG_COLOR_MASK_ALPHA) != 0) |
975 { | 1300 { |
976 if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) | 1301 if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) |
977 { | 1302 { |
978 png_warning(png_ptr, "Invalid sBIT depth specified"); | 1303 png_warning(png_ptr, "Invalid sBIT depth specified"); |
979 return; | 1304 return; |
980 } | 1305 } |
| 1306 |
981 buf[size++] = sbit->alpha; | 1307 buf[size++] = sbit->alpha; |
982 } | 1308 } |
983 | 1309 |
984 png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); | 1310 png_write_complete_chunk(png_ptr, png_sBIT, buf, size); |
985 } | 1311 } |
986 #endif | 1312 #endif |
987 | 1313 |
988 #ifdef PNG_WRITE_cHRM_SUPPORTED | 1314 #ifdef PNG_WRITE_cHRM_SUPPORTED |
989 /* Write the cHRM chunk */ | 1315 /* Write the cHRM chunk */ |
990 #ifdef PNG_FLOATING_POINT_SUPPORTED | |
991 void /* PRIVATE */ | 1316 void /* PRIVATE */ |
992 png_write_cHRM(png_structp png_ptr, double white_x, double white_y, | 1317 png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) |
993 double red_x, double red_y, double green_x, double green_y, | |
994 double blue_x, double blue_y) | |
995 { | 1318 { |
996 #ifdef PNG_USE_LOCAL_ARRAYS | |
997 PNG_cHRM; | |
998 #endif | |
999 png_byte buf[32]; | |
1000 | |
1001 png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, | |
1002 int_green_x, int_green_y, int_blue_x, int_blue_y; | |
1003 | |
1004 png_debug(1, "in png_write_cHRM"); | |
1005 | |
1006 int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5); | |
1007 int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5); | |
1008 int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5); | |
1009 int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5); | |
1010 int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5); | |
1011 int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5); | |
1012 int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5); | |
1013 int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5); | |
1014 | |
1015 #ifdef PNG_CHECK_cHRM_SUPPORTED | |
1016 if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y, | |
1017 int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y)) | |
1018 #endif | |
1019 { | |
1020 /* Each value is saved in 1/100,000ths */ | |
1021 | |
1022 png_save_uint_32(buf, int_white_x); | |
1023 png_save_uint_32(buf + 4, int_white_y); | |
1024 | |
1025 png_save_uint_32(buf + 8, int_red_x); | |
1026 png_save_uint_32(buf + 12, int_red_y); | |
1027 | |
1028 png_save_uint_32(buf + 16, int_green_x); | |
1029 png_save_uint_32(buf + 20, int_green_y); | |
1030 | |
1031 png_save_uint_32(buf + 24, int_blue_x); | |
1032 png_save_uint_32(buf + 28, int_blue_y); | |
1033 | |
1034 png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); | |
1035 } | |
1036 } | |
1037 #endif | |
1038 #ifdef PNG_FIXED_POINT_SUPPORTED | |
1039 void /* PRIVATE */ | |
1040 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, | |
1041 png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, | |
1042 png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, | |
1043 png_fixed_point blue_y) | |
1044 { | |
1045 #ifdef PNG_USE_LOCAL_ARRAYS | |
1046 PNG_cHRM; | |
1047 #endif | |
1048 png_byte buf[32]; | 1319 png_byte buf[32]; |
1049 | 1320 |
1050 png_debug(1, "in png_write_cHRM"); | 1321 png_debug(1, "in png_write_cHRM"); |
1051 | 1322 |
1052 /* Each value is saved in 1/100,000ths */ | 1323 /* Each value is saved in 1/100,000ths */ |
1053 #ifdef PNG_CHECK_cHRM_SUPPORTED | 1324 png_save_int_32(buf, xy->whitex); |
1054 if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, | 1325 png_save_int_32(buf + 4, xy->whitey); |
1055 green_x, green_y, blue_x, blue_y)) | |
1056 #endif | |
1057 { | |
1058 png_save_uint_32(buf, (png_uint_32)white_x); | |
1059 png_save_uint_32(buf + 4, (png_uint_32)white_y); | |
1060 | 1326 |
1061 png_save_uint_32(buf + 8, (png_uint_32)red_x); | 1327 png_save_int_32(buf + 8, xy->redx); |
1062 png_save_uint_32(buf + 12, (png_uint_32)red_y); | 1328 png_save_int_32(buf + 12, xy->redy); |
1063 | 1329 |
1064 png_save_uint_32(buf + 16, (png_uint_32)green_x); | 1330 png_save_int_32(buf + 16, xy->greenx); |
1065 png_save_uint_32(buf + 20, (png_uint_32)green_y); | 1331 png_save_int_32(buf + 20, xy->greeny); |
1066 | 1332 |
1067 png_save_uint_32(buf + 24, (png_uint_32)blue_x); | 1333 png_save_int_32(buf + 24, xy->bluex); |
1068 png_save_uint_32(buf + 28, (png_uint_32)blue_y); | 1334 png_save_int_32(buf + 28, xy->bluey); |
1069 | 1335 |
1070 png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); | 1336 png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); |
1071 } | |
1072 } | 1337 } |
1073 #endif | 1338 #endif |
1074 #endif | |
1075 | 1339 |
1076 #ifdef PNG_WRITE_tRNS_SUPPORTED | 1340 #ifdef PNG_WRITE_tRNS_SUPPORTED |
1077 /* Write the tRNS chunk */ | 1341 /* Write the tRNS chunk */ |
1078 void /* PRIVATE */ | 1342 void /* PRIVATE */ |
1079 png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, | 1343 png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, |
1080 int num_trans, int color_type) | 1344 png_const_color_16p tran, int num_trans, int color_type) |
1081 { | 1345 { |
1082 #ifdef PNG_USE_LOCAL_ARRAYS | |
1083 PNG_tRNS; | |
1084 #endif | |
1085 png_byte buf[6]; | 1346 png_byte buf[6]; |
1086 | 1347 |
1087 png_debug(1, "in png_write_tRNS"); | 1348 png_debug(1, "in png_write_tRNS"); |
1088 | 1349 |
1089 if (color_type == PNG_COLOR_TYPE_PALETTE) | 1350 if (color_type == PNG_COLOR_TYPE_PALETTE) |
1090 { | 1351 { |
1091 if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) | 1352 if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) |
1092 { | 1353 { |
1093 png_warning(png_ptr, "Invalid number of transparent colors specified"); | 1354 png_app_warning(png_ptr, |
| 1355 "Invalid number of transparent colors specified"); |
1094 return; | 1356 return; |
1095 } | 1357 } |
| 1358 |
1096 /* Write the chunk out as it is */ | 1359 /* Write the chunk out as it is */ |
1097 png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, | 1360 png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, |
1098 (png_size_t)num_trans); | 1361 (png_size_t)num_trans); |
1099 } | 1362 } |
| 1363 |
1100 else if (color_type == PNG_COLOR_TYPE_GRAY) | 1364 else if (color_type == PNG_COLOR_TYPE_GRAY) |
1101 { | 1365 { |
1102 /* One 16 bit value */ | 1366 /* One 16-bit value */ |
1103 if (tran->gray >= (1 << png_ptr->bit_depth)) | 1367 if (tran->gray >= (1 << png_ptr->bit_depth)) |
1104 { | 1368 { |
1105 png_warning(png_ptr, | 1369 png_app_warning(png_ptr, |
1106 "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); | 1370 "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); |
| 1371 |
1107 return; | 1372 return; |
1108 } | 1373 } |
| 1374 |
1109 png_save_uint_16(buf, tran->gray); | 1375 png_save_uint_16(buf, tran->gray); |
1110 png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); | 1376 png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); |
1111 } | 1377 } |
| 1378 |
1112 else if (color_type == PNG_COLOR_TYPE_RGB) | 1379 else if (color_type == PNG_COLOR_TYPE_RGB) |
1113 { | 1380 { |
1114 /* Three 16 bit values */ | 1381 /* Three 16-bit values */ |
1115 png_save_uint_16(buf, tran->red); | 1382 png_save_uint_16(buf, tran->red); |
1116 png_save_uint_16(buf + 2, tran->green); | 1383 png_save_uint_16(buf + 2, tran->green); |
1117 png_save_uint_16(buf + 4, tran->blue); | 1384 png_save_uint_16(buf + 4, tran->blue); |
1118 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) | 1385 #ifdef PNG_WRITE_16BIT_SUPPORTED |
| 1386 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0) |
| 1387 #else |
| 1388 if ((buf[0] | buf[2] | buf[4]) != 0) |
| 1389 #endif |
1119 { | 1390 { |
1120 png_warning(png_ptr, | 1391 png_app_warning(png_ptr, |
1121 "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); | 1392 "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); |
1122 return; | 1393 return; |
1123 } | 1394 } |
1124 png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); | 1395 |
| 1396 png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); |
1125 } | 1397 } |
| 1398 |
1126 else | 1399 else |
1127 { | 1400 { |
1128 png_warning(png_ptr, "Can't write tRNS with an alpha channel"); | 1401 png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); |
1129 } | 1402 } |
1130 } | 1403 } |
1131 #endif | 1404 #endif |
1132 | 1405 |
1133 #ifdef PNG_WRITE_bKGD_SUPPORTED | 1406 #ifdef PNG_WRITE_bKGD_SUPPORTED |
1134 /* Write the background chunk */ | 1407 /* Write the background chunk */ |
1135 void /* PRIVATE */ | 1408 void /* PRIVATE */ |
1136 png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) | 1409 png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) |
1137 { | 1410 { |
1138 #ifdef PNG_USE_LOCAL_ARRAYS | |
1139 PNG_bKGD; | |
1140 #endif | |
1141 png_byte buf[6]; | 1411 png_byte buf[6]; |
1142 | 1412 |
1143 png_debug(1, "in png_write_bKGD"); | 1413 png_debug(1, "in png_write_bKGD"); |
1144 | 1414 |
1145 if (color_type == PNG_COLOR_TYPE_PALETTE) | 1415 if (color_type == PNG_COLOR_TYPE_PALETTE) |
1146 { | 1416 { |
1147 if ( | 1417 if ( |
1148 #ifdef PNG_MNG_FEATURES_SUPPORTED | 1418 #ifdef PNG_MNG_FEATURES_SUPPORTED |
1149 (png_ptr->num_palette || | 1419 (png_ptr->num_palette != 0 || |
1150 (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && | 1420 (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) && |
1151 #endif | 1421 #endif |
1152 back->index >= png_ptr->num_palette) | 1422 back->index >= png_ptr->num_palette) |
1153 { | 1423 { |
1154 png_warning(png_ptr, "Invalid background palette index"); | 1424 png_warning(png_ptr, "Invalid background palette index"); |
1155 return; | 1425 return; |
1156 } | 1426 } |
| 1427 |
1157 buf[0] = back->index; | 1428 buf[0] = back->index; |
1158 png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); | 1429 png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); |
1159 } | 1430 } |
1160 else if (color_type & PNG_COLOR_MASK_COLOR) | 1431 |
| 1432 else if ((color_type & PNG_COLOR_MASK_COLOR) != 0) |
1161 { | 1433 { |
1162 png_save_uint_16(buf, back->red); | 1434 png_save_uint_16(buf, back->red); |
1163 png_save_uint_16(buf + 2, back->green); | 1435 png_save_uint_16(buf + 2, back->green); |
1164 png_save_uint_16(buf + 4, back->blue); | 1436 png_save_uint_16(buf + 4, back->blue); |
1165 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) | 1437 #ifdef PNG_WRITE_16BIT_SUPPORTED |
| 1438 if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0) |
| 1439 #else |
| 1440 if ((buf[0] | buf[2] | buf[4]) != 0) |
| 1441 #endif |
1166 { | 1442 { |
1167 png_warning(png_ptr, | 1443 png_warning(png_ptr, |
1168 "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); | 1444 "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); |
| 1445 |
1169 return; | 1446 return; |
1170 } | 1447 } |
1171 png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); | 1448 |
| 1449 png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); |
1172 } | 1450 } |
| 1451 |
1173 else | 1452 else |
1174 { | 1453 { |
1175 if (back->gray >= (1 << png_ptr->bit_depth)) | 1454 if (back->gray >= (1 << png_ptr->bit_depth)) |
1176 { | 1455 { |
1177 png_warning(png_ptr, | 1456 png_warning(png_ptr, |
1178 "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); | 1457 "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); |
| 1458 |
1179 return; | 1459 return; |
1180 } | 1460 } |
| 1461 |
1181 png_save_uint_16(buf, back->gray); | 1462 png_save_uint_16(buf, back->gray); |
1182 png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); | 1463 png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); |
1183 } | 1464 } |
1184 } | 1465 } |
1185 #endif | 1466 #endif |
1186 | 1467 |
1187 #ifdef PNG_WRITE_hIST_SUPPORTED | 1468 #ifdef PNG_WRITE_hIST_SUPPORTED |
1188 /* Write the histogram */ | 1469 /* Write the histogram */ |
1189 void /* PRIVATE */ | 1470 void /* PRIVATE */ |
1190 png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) | 1471 png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) |
1191 { | 1472 { |
1192 #ifdef PNG_USE_LOCAL_ARRAYS | |
1193 PNG_hIST; | |
1194 #endif | |
1195 int i; | 1473 int i; |
1196 png_byte buf[3]; | 1474 png_byte buf[3]; |
1197 | 1475 |
1198 png_debug(1, "in png_write_hIST"); | 1476 png_debug(1, "in png_write_hIST"); |
1199 | 1477 |
1200 if (num_hist > (int)png_ptr->num_palette) | 1478 if (num_hist > (int)png_ptr->num_palette) |
1201 { | 1479 { |
1202 png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, | 1480 png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, |
1203 png_ptr->num_palette); | 1481 png_ptr->num_palette); |
| 1482 |
1204 png_warning(png_ptr, "Invalid number of histogram entries specified"); | 1483 png_warning(png_ptr, "Invalid number of histogram entries specified"); |
1205 return; | 1484 return; |
1206 } | 1485 } |
1207 | 1486 |
1208 png_write_chunk_start(png_ptr, (png_bytep)png_hIST, | 1487 png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); |
1209 (png_uint_32)(num_hist * 2)); | 1488 |
1210 for (i = 0; i < num_hist; i++) | 1489 for (i = 0; i < num_hist; i++) |
1211 { | 1490 { |
1212 png_save_uint_16(buf, hist[i]); | 1491 png_save_uint_16(buf, hist[i]); |
1213 png_write_chunk_data(png_ptr, buf, (png_size_t)2); | 1492 png_write_chunk_data(png_ptr, buf, (png_size_t)2); |
1214 } | 1493 } |
| 1494 |
1215 png_write_chunk_end(png_ptr); | 1495 png_write_chunk_end(png_ptr); |
1216 } | 1496 } |
1217 #endif | 1497 #endif |
1218 | 1498 |
1219 #ifdef PNG_WRITE_tEXt_SUPPORTED | 1499 #ifdef PNG_WRITE_tEXt_SUPPORTED |
1220 /* Write a tEXt chunk */ | 1500 /* Write a tEXt chunk */ |
1221 void /* PRIVATE */ | 1501 void /* PRIVATE */ |
1222 png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, | 1502 png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, |
1223 png_size_t text_len) | 1503 png_size_t text_len) |
1224 { | 1504 { |
1225 #ifdef PNG_USE_LOCAL_ARRAYS | 1505 png_uint_32 key_len; |
1226 PNG_tEXt; | 1506 png_byte new_key[80]; |
1227 #endif | |
1228 png_size_t key_len; | |
1229 png_charp new_key; | |
1230 | 1507 |
1231 png_debug(1, "in png_write_tEXt"); | 1508 png_debug(1, "in png_write_tEXt"); |
1232 | 1509 |
1233 if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) | 1510 key_len = png_check_keyword(png_ptr, key, new_key); |
1234 return; | 1511 |
| 1512 if (key_len == 0) |
| 1513 png_error(png_ptr, "tEXt: invalid keyword"); |
1235 | 1514 |
1236 if (text == NULL || *text == '\0') | 1515 if (text == NULL || *text == '\0') |
1237 text_len = 0; | 1516 text_len = 0; |
| 1517 |
1238 else | 1518 else |
1239 text_len = png_strlen(text); | 1519 text_len = strlen(text); |
| 1520 |
| 1521 if (text_len > PNG_UINT_31_MAX - (key_len+1)) |
| 1522 png_error(png_ptr, "tEXt: text too long"); |
1240 | 1523 |
1241 /* Make sure we include the 0 after the key */ | 1524 /* Make sure we include the 0 after the key */ |
1242 png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, | 1525 png_write_chunk_header(png_ptr, png_tEXt, |
1243 (png_uint_32)(key_len + text_len + 1)); | 1526 (png_uint_32)/*checked above*/(key_len + text_len + 1)); |
1244 /* | 1527 /* |
1245 * We leave it to the application to meet PNG-1.0 requirements on the | 1528 * We leave it to the application to meet PNG-1.0 requirements on the |
1246 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of | 1529 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of |
1247 * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. | 1530 * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. |
1248 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. | 1531 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. |
1249 */ | 1532 */ |
1250 png_write_chunk_data(png_ptr, (png_bytep)new_key, | 1533 png_write_chunk_data(png_ptr, new_key, key_len + 1); |
1251 (png_size_t)(key_len + 1)); | 1534 |
1252 if (text_len) | 1535 if (text_len != 0) |
1253 png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); | 1536 png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); |
1254 | 1537 |
1255 png_write_chunk_end(png_ptr); | 1538 png_write_chunk_end(png_ptr); |
1256 png_free(png_ptr, new_key); | |
1257 } | 1539 } |
1258 #endif | 1540 #endif |
1259 | 1541 |
1260 #ifdef PNG_WRITE_zTXt_SUPPORTED | 1542 #ifdef PNG_WRITE_zTXt_SUPPORTED |
1261 /* Write a compressed text chunk */ | 1543 /* Write a compressed text chunk */ |
1262 void /* PRIVATE */ | 1544 void /* PRIVATE */ |
1263 png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, | 1545 png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, |
1264 png_size_t text_len, int compression) | 1546 int compression) |
1265 { | 1547 { |
1266 #ifdef PNG_USE_LOCAL_ARRAYS | 1548 png_uint_32 key_len; |
1267 PNG_zTXt; | 1549 png_byte new_key[81]; |
1268 #endif | |
1269 png_size_t key_len; | |
1270 char buf[1]; | |
1271 png_charp new_key; | |
1272 compression_state comp; | 1550 compression_state comp; |
1273 | 1551 |
1274 png_debug(1, "in png_write_zTXt"); | 1552 png_debug(1, "in png_write_zTXt"); |
1275 | 1553 |
1276 comp.num_output_ptr = 0; | 1554 if (compression == PNG_TEXT_COMPRESSION_NONE) |
1277 comp.max_output_ptr = 0; | |
1278 comp.output_ptr = NULL; | |
1279 comp.input = NULL; | |
1280 comp.input_len = 0; | |
1281 | |
1282 if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) | |
1283 { | 1555 { |
1284 png_free(png_ptr, new_key); | 1556 png_write_tEXt(png_ptr, key, text, 0); |
1285 return; | 1557 return; |
1286 } | 1558 } |
1287 | 1559 |
1288 if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) | 1560 if (compression != PNG_TEXT_COMPRESSION_zTXt) |
1289 { | 1561 png_error(png_ptr, "zTXt: invalid compression type"); |
1290 png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); | |
1291 png_free(png_ptr, new_key); | |
1292 return; | |
1293 } | |
1294 | 1562 |
1295 text_len = png_strlen(text); | 1563 key_len = png_check_keyword(png_ptr, key, new_key); |
| 1564 |
| 1565 if (key_len == 0) |
| 1566 png_error(png_ptr, "zTXt: invalid keyword"); |
| 1567 |
| 1568 /* Add the compression method and 1 for the keyword separator. */ |
| 1569 new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; |
| 1570 ++key_len; |
1296 | 1571 |
1297 /* Compute the compressed data; do it now for the length */ | 1572 /* Compute the compressed data; do it now for the length */ |
1298 text_len = png_text_compress(png_ptr, text, text_len, compression, | 1573 png_text_compress_init(&comp, (png_const_bytep)text, |
1299 &comp); | 1574 text == NULL ? 0 : strlen(text)); |
| 1575 |
| 1576 if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) |
| 1577 png_error(png_ptr, png_ptr->zstream.msg); |
1300 | 1578 |
1301 /* Write start of chunk */ | 1579 /* Write start of chunk */ |
1302 png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, | 1580 png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len); |
1303 (png_uint_32)(key_len+text_len + 2)); | 1581 |
1304 /* Write key */ | 1582 /* Write key */ |
1305 png_write_chunk_data(png_ptr, (png_bytep)new_key, | 1583 png_write_chunk_data(png_ptr, new_key, key_len); |
1306 (png_size_t)(key_len + 1)); | |
1307 png_free(png_ptr, new_key); | |
1308 | 1584 |
1309 buf[0] = (png_byte)compression; | |
1310 /* Write compression */ | |
1311 png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); | |
1312 /* Write the compressed data */ | 1585 /* Write the compressed data */ |
1313 png_write_compressed_data_out(png_ptr, &comp); | 1586 png_write_compressed_data_out(png_ptr, &comp); |
1314 | 1587 |
1315 /* Close the chunk */ | 1588 /* Close the chunk */ |
1316 png_write_chunk_end(png_ptr); | 1589 png_write_chunk_end(png_ptr); |
1317 } | 1590 } |
1318 #endif | 1591 #endif |
1319 | 1592 |
1320 #ifdef PNG_WRITE_iTXt_SUPPORTED | 1593 #ifdef PNG_WRITE_iTXt_SUPPORTED |
1321 /* Write an iTXt chunk */ | 1594 /* Write an iTXt chunk */ |
1322 void /* PRIVATE */ | 1595 void /* PRIVATE */ |
1323 png_write_iTXt(png_structp png_ptr, int compression, png_charp key, | 1596 png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, |
1324 png_charp lang, png_charp lang_key, png_charp text) | 1597 png_const_charp lang, png_const_charp lang_key, png_const_charp text) |
1325 { | 1598 { |
1326 #ifdef PNG_USE_LOCAL_ARRAYS | 1599 png_uint_32 key_len, prefix_len; |
1327 PNG_iTXt; | 1600 png_size_t lang_len, lang_key_len; |
1328 #endif | 1601 png_byte new_key[82]; |
1329 png_size_t lang_len, key_len, lang_key_len, text_len; | |
1330 png_charp new_lang; | |
1331 png_charp new_key = NULL; | |
1332 png_byte cbuf[2]; | |
1333 compression_state comp; | 1602 compression_state comp; |
1334 | 1603 |
1335 png_debug(1, "in png_write_iTXt"); | 1604 png_debug(1, "in png_write_iTXt"); |
1336 | 1605 |
1337 comp.num_output_ptr = 0; | 1606 key_len = png_check_keyword(png_ptr, key, new_key); |
1338 comp.max_output_ptr = 0; | |
1339 comp.output_ptr = NULL; | |
1340 comp.input = NULL; | |
1341 | 1607 |
1342 if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) | 1608 if (key_len == 0) |
1343 return; | 1609 png_error(png_ptr, "iTXt: invalid keyword"); |
1344 | 1610 |
1345 if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) | 1611 /* Set the compression flag */ |
| 1612 switch (compression) |
1346 { | 1613 { |
1347 png_warning(png_ptr, "Empty language field in iTXt chunk"); | 1614 case PNG_ITXT_COMPRESSION_NONE: |
1348 new_lang = NULL; | 1615 case PNG_TEXT_COMPRESSION_NONE: |
1349 lang_len = 0; | 1616 compression = new_key[++key_len] = 0; /* no compression */ |
| 1617 break; |
| 1618 |
| 1619 case PNG_TEXT_COMPRESSION_zTXt: |
| 1620 case PNG_ITXT_COMPRESSION_zTXt: |
| 1621 compression = new_key[++key_len] = 1; /* compressed */ |
| 1622 break; |
| 1623 |
| 1624 default: |
| 1625 png_error(png_ptr, "iTXt: invalid compression"); |
1350 } | 1626 } |
1351 | 1627 |
1352 if (lang_key == NULL) | 1628 new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; |
1353 lang_key_len = 0; | 1629 ++key_len; /* for the keywod separator */ |
1354 else | |
1355 lang_key_len = png_strlen(lang_key); | |
1356 | |
1357 if (text == NULL) | |
1358 text_len = 0; | |
1359 else | |
1360 text_len = png_strlen(text); | |
1361 | |
1362 /* Compute the compressed data; do it now for the length */ | |
1363 text_len = png_text_compress(png_ptr, text, text_len, compression-2, | |
1364 &comp); | |
1365 | |
1366 | |
1367 /* Make sure we include the compression flag, the compression byte, | |
1368 * and the NULs after the key, lang, and lang_key parts */ | |
1369 | |
1370 png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, | |
1371 (png_uint_32)( | |
1372 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ | |
1373 + key_len | |
1374 + lang_len | |
1375 + lang_key_len | |
1376 + text_len)); | |
1377 | 1630 |
1378 /* We leave it to the application to meet PNG-1.0 requirements on the | 1631 /* We leave it to the application to meet PNG-1.0 requirements on the |
1379 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of | 1632 * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of |
1380 * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. | 1633 * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, |
| 1634 * specifies that the text is UTF-8 and this really doesn't require any |
| 1635 * checking. |
| 1636 * |
1381 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. | 1637 * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. |
| 1638 * |
| 1639 * TODO: validate the language tag correctly (see the spec.) |
1382 */ | 1640 */ |
1383 png_write_chunk_data(png_ptr, (png_bytep)new_key, | 1641 if (lang == NULL) lang = ""; /* empty language is valid */ |
1384 (png_size_t)(key_len + 1)); | 1642 lang_len = strlen(lang)+1; |
| 1643 if (lang_key == NULL) lang_key = ""; /* may be empty */ |
| 1644 lang_key_len = strlen(lang_key)+1; |
| 1645 if (text == NULL) text = ""; /* may be empty */ |
1385 | 1646 |
1386 /* Set the compression flag */ | 1647 prefix_len = key_len; |
1387 if (compression == PNG_ITXT_COMPRESSION_NONE || \ | 1648 if (lang_len > PNG_UINT_31_MAX-prefix_len) |
1388 compression == PNG_TEXT_COMPRESSION_NONE) | 1649 prefix_len = PNG_UINT_31_MAX; |
1389 cbuf[0] = 0; | 1650 else |
1390 else /* compression == PNG_ITXT_COMPRESSION_zTXt */ | 1651 prefix_len = (png_uint_32)(prefix_len + lang_len); |
1391 cbuf[0] = 1; | |
1392 /* Set the compression method */ | |
1393 cbuf[1] = 0; | |
1394 png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); | |
1395 | 1652 |
1396 cbuf[0] = 0; | 1653 if (lang_key_len > PNG_UINT_31_MAX-prefix_len) |
1397 png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), | 1654 prefix_len = PNG_UINT_31_MAX; |
1398 (png_size_t)(lang_len + 1)); | 1655 else |
1399 png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), | 1656 prefix_len = (png_uint_32)(prefix_len + lang_key_len); |
1400 (png_size_t)(lang_key_len + 1)); | 1657 |
1401 png_write_compressed_data_out(png_ptr, &comp); | 1658 png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); |
| 1659 |
| 1660 if (compression != 0) |
| 1661 { |
| 1662 if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) |
| 1663 png_error(png_ptr, png_ptr->zstream.msg); |
| 1664 } |
| 1665 |
| 1666 else |
| 1667 { |
| 1668 if (comp.input_len > PNG_UINT_31_MAX-prefix_len) |
| 1669 png_error(png_ptr, "iTXt: uncompressed text too long"); |
| 1670 |
| 1671 /* So the string will fit in a chunk: */ |
| 1672 comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; |
| 1673 } |
| 1674 |
| 1675 png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); |
| 1676 |
| 1677 png_write_chunk_data(png_ptr, new_key, key_len); |
| 1678 |
| 1679 png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); |
| 1680 |
| 1681 png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); |
| 1682 |
| 1683 if (compression != 0) |
| 1684 png_write_compressed_data_out(png_ptr, &comp); |
| 1685 |
| 1686 else |
| 1687 png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len); |
1402 | 1688 |
1403 png_write_chunk_end(png_ptr); | 1689 png_write_chunk_end(png_ptr); |
1404 png_free(png_ptr, new_key); | |
1405 png_free(png_ptr, new_lang); | |
1406 } | 1690 } |
1407 #endif | 1691 #endif |
1408 | 1692 |
1409 #ifdef PNG_WRITE_oFFs_SUPPORTED | 1693 #ifdef PNG_WRITE_oFFs_SUPPORTED |
1410 /* Write the oFFs chunk */ | 1694 /* Write the oFFs chunk */ |
1411 void /* PRIVATE */ | 1695 void /* PRIVATE */ |
1412 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, | 1696 png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, |
1413 int unit_type) | 1697 int unit_type) |
1414 { | 1698 { |
1415 #ifdef PNG_USE_LOCAL_ARRAYS | |
1416 PNG_oFFs; | |
1417 #endif | |
1418 png_byte buf[9]; | 1699 png_byte buf[9]; |
1419 | 1700 |
1420 png_debug(1, "in png_write_oFFs"); | 1701 png_debug(1, "in png_write_oFFs"); |
1421 | 1702 |
1422 if (unit_type >= PNG_OFFSET_LAST) | 1703 if (unit_type >= PNG_OFFSET_LAST) |
1423 png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); | 1704 png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); |
1424 | 1705 |
1425 png_save_int_32(buf, x_offset); | 1706 png_save_int_32(buf, x_offset); |
1426 png_save_int_32(buf + 4, y_offset); | 1707 png_save_int_32(buf + 4, y_offset); |
1427 buf[8] = (png_byte)unit_type; | 1708 buf[8] = (png_byte)unit_type; |
1428 | 1709 |
1429 png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); | 1710 png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); |
1430 } | 1711 } |
1431 #endif | 1712 #endif |
1432 #ifdef PNG_WRITE_pCAL_SUPPORTED | 1713 #ifdef PNG_WRITE_pCAL_SUPPORTED |
1433 /* Write the pCAL chunk (described in the PNG extensions document) */ | 1714 /* Write the pCAL chunk (described in the PNG extensions document) */ |
1434 void /* PRIVATE */ | 1715 void /* PRIVATE */ |
1435 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, | 1716 png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, |
1436 png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) | 1717 png_int_32 X1, int type, int nparams, png_const_charp units, |
| 1718 png_charpp params) |
1437 { | 1719 { |
1438 #ifdef PNG_USE_LOCAL_ARRAYS | 1720 png_uint_32 purpose_len; |
1439 PNG_pCAL; | 1721 png_size_t units_len, total_len; |
1440 #endif | 1722 png_size_tp params_len; |
1441 png_size_t purpose_len, units_len, total_len; | |
1442 png_uint_32p params_len; | |
1443 png_byte buf[10]; | 1723 png_byte buf[10]; |
1444 png_charp new_purpose; | 1724 png_byte new_purpose[80]; |
1445 int i; | 1725 int i; |
1446 | 1726 |
1447 png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); | 1727 png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); |
1448 | 1728 |
1449 if (type >= PNG_EQUATION_LAST) | 1729 if (type >= PNG_EQUATION_LAST) |
1450 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); | 1730 png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); |
1451 | 1731 |
1452 purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; | 1732 purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); |
| 1733 |
| 1734 if (purpose_len == 0) |
| 1735 png_error(png_ptr, "pCAL: invalid keyword"); |
| 1736 |
| 1737 ++purpose_len; /* terminator */ |
| 1738 |
1453 png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); | 1739 png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); |
1454 units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); | 1740 units_len = strlen(units) + (nparams == 0 ? 0 : 1); |
1455 png_debug1(3, "pCAL units length = %d", (int)units_len); | 1741 png_debug1(3, "pCAL units length = %d", (int)units_len); |
1456 total_len = purpose_len + units_len + 10; | 1742 total_len = purpose_len + units_len + 10; |
1457 | 1743 |
1458 params_len = (png_uint_32p)png_malloc(png_ptr, | 1744 params_len = (png_size_tp)png_malloc(png_ptr, |
1459 (png_uint_32)(nparams * png_sizeof(png_uint_32))); | 1745 (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); |
1460 | 1746 |
1461 /* Find the length of each parameter, making sure we don't count the | 1747 /* Find the length of each parameter, making sure we don't count the |
1462 null terminator for the last parameter. */ | 1748 * null terminator for the last parameter. |
| 1749 */ |
1463 for (i = 0; i < nparams; i++) | 1750 for (i = 0; i < nparams; i++) |
1464 { | 1751 { |
1465 params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); | 1752 params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); |
1466 png_debug2(3, "pCAL parameter %d length = %lu", i, | 1753 png_debug2(3, "pCAL parameter %d length = %lu", i, |
1467 (unsigned long) params_len[i]); | 1754 (unsigned long)params_len[i]); |
1468 total_len += (png_size_t)params_len[i]; | 1755 total_len += params_len[i]; |
1469 } | 1756 } |
1470 | 1757 |
1471 png_debug1(3, "pCAL total length = %d", (int)total_len); | 1758 png_debug1(3, "pCAL total length = %d", (int)total_len); |
1472 png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); | 1759 png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); |
1473 png_write_chunk_data(png_ptr, (png_bytep)new_purpose, | 1760 png_write_chunk_data(png_ptr, new_purpose, purpose_len); |
1474 (png_size_t)purpose_len); | |
1475 png_save_int_32(buf, X0); | 1761 png_save_int_32(buf, X0); |
1476 png_save_int_32(buf + 4, X1); | 1762 png_save_int_32(buf + 4, X1); |
1477 buf[8] = (png_byte)type; | 1763 buf[8] = (png_byte)type; |
1478 buf[9] = (png_byte)nparams; | 1764 buf[9] = (png_byte)nparams; |
1479 png_write_chunk_data(png_ptr, buf, (png_size_t)10); | 1765 png_write_chunk_data(png_ptr, buf, (png_size_t)10); |
1480 png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); | 1766 png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); |
1481 | |
1482 png_free(png_ptr, new_purpose); | |
1483 | 1767 |
1484 for (i = 0; i < nparams; i++) | 1768 for (i = 0; i < nparams; i++) |
1485 { | 1769 { |
1486 png_write_chunk_data(png_ptr, (png_bytep)params[i], | 1770 png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); |
1487 (png_size_t)params_len[i]); | |
1488 } | 1771 } |
1489 | 1772 |
1490 png_free(png_ptr, params_len); | 1773 png_free(png_ptr, params_len); |
1491 png_write_chunk_end(png_ptr); | 1774 png_write_chunk_end(png_ptr); |
1492 } | 1775 } |
1493 #endif | 1776 #endif |
1494 | 1777 |
1495 #ifdef PNG_WRITE_sCAL_SUPPORTED | 1778 #ifdef PNG_WRITE_sCAL_SUPPORTED |
1496 /* Write the sCAL chunk */ | 1779 /* Write the sCAL chunk */ |
1497 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) | |
1498 void /* PRIVATE */ | 1780 void /* PRIVATE */ |
1499 png_write_sCAL(png_structp png_ptr, int unit, double width, double height) | 1781 png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, |
| 1782 png_const_charp height) |
1500 { | 1783 { |
1501 #ifdef PNG_USE_LOCAL_ARRAYS | |
1502 PNG_sCAL; | |
1503 #endif | |
1504 char buf[64]; | |
1505 png_size_t total_len; | |
1506 | |
1507 png_debug(1, "in png_write_sCAL"); | |
1508 | |
1509 buf[0] = (char)unit; | |
1510 #ifdef _WIN32_WCE | |
1511 /* sprintf() function is not supported on WindowsCE */ | |
1512 { | |
1513 wchar_t wc_buf[32]; | |
1514 size_t wc_len; | |
1515 swprintf(wc_buf, TEXT("%12.12e"), width); | |
1516 wc_len = wcslen(wc_buf); | |
1517 WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, | |
1518 NULL); | |
1519 total_len = wc_len + 2; | |
1520 swprintf(wc_buf, TEXT("%12.12e"), height); | |
1521 wc_len = wcslen(wc_buf); | |
1522 WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, | |
1523 NULL, NULL); | |
1524 total_len += wc_len; | |
1525 } | |
1526 #else | |
1527 png_snprintf(buf + 1, 63, "%12.12e", width); | |
1528 total_len = 1 + png_strlen(buf + 1) + 1; | |
1529 png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); | |
1530 total_len += png_strlen(buf + total_len); | |
1531 #endif | |
1532 | |
1533 png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); | |
1534 png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len); | |
1535 } | |
1536 #else | |
1537 #ifdef PNG_FIXED_POINT_SUPPORTED | |
1538 void /* PRIVATE */ | |
1539 png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, | |
1540 png_charp height) | |
1541 { | |
1542 #ifdef PNG_USE_LOCAL_ARRAYS | |
1543 PNG_sCAL; | |
1544 #endif | |
1545 png_byte buf[64]; | 1784 png_byte buf[64]; |
1546 png_size_t wlen, hlen, total_len; | 1785 png_size_t wlen, hlen, total_len; |
1547 | 1786 |
1548 png_debug(1, "in png_write_sCAL_s"); | 1787 png_debug(1, "in png_write_sCAL_s"); |
1549 | 1788 |
1550 wlen = png_strlen(width); | 1789 wlen = strlen(width); |
1551 hlen = png_strlen(height); | 1790 hlen = strlen(height); |
1552 total_len = wlen + hlen + 2; | 1791 total_len = wlen + hlen + 2; |
| 1792 |
1553 if (total_len > 64) | 1793 if (total_len > 64) |
1554 { | 1794 { |
1555 png_warning(png_ptr, "Can't write sCAL (buffer too small)"); | 1795 png_warning(png_ptr, "Can't write sCAL (buffer too small)"); |
1556 return; | 1796 return; |
1557 } | 1797 } |
1558 | 1798 |
1559 buf[0] = (png_byte)unit; | 1799 buf[0] = (png_byte)unit; |
1560 png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ | 1800 memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ |
1561 png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ | 1801 memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ |
1562 | 1802 |
1563 png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); | 1803 png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); |
1564 png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len); | 1804 png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len); |
1565 } | 1805 } |
1566 #endif | 1806 #endif |
1567 #endif | |
1568 #endif | |
1569 | 1807 |
1570 #ifdef PNG_WRITE_pHYs_SUPPORTED | 1808 #ifdef PNG_WRITE_pHYs_SUPPORTED |
1571 /* Write the pHYs chunk */ | 1809 /* Write the pHYs chunk */ |
1572 void /* PRIVATE */ | 1810 void /* PRIVATE */ |
1573 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, | 1811 png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, |
1574 png_uint_32 y_pixels_per_unit, | 1812 png_uint_32 y_pixels_per_unit, |
1575 int unit_type) | 1813 int unit_type) |
1576 { | 1814 { |
1577 #ifdef PNG_USE_LOCAL_ARRAYS | |
1578 PNG_pHYs; | |
1579 #endif | |
1580 png_byte buf[9]; | 1815 png_byte buf[9]; |
1581 | 1816 |
1582 png_debug(1, "in png_write_pHYs"); | 1817 png_debug(1, "in png_write_pHYs"); |
1583 | 1818 |
1584 if (unit_type >= PNG_RESOLUTION_LAST) | 1819 if (unit_type >= PNG_RESOLUTION_LAST) |
1585 png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); | 1820 png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); |
1586 | 1821 |
1587 png_save_uint_32(buf, x_pixels_per_unit); | 1822 png_save_uint_32(buf, x_pixels_per_unit); |
1588 png_save_uint_32(buf + 4, y_pixels_per_unit); | 1823 png_save_uint_32(buf + 4, y_pixels_per_unit); |
1589 buf[8] = (png_byte)unit_type; | 1824 buf[8] = (png_byte)unit_type; |
1590 | 1825 |
1591 png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); | 1826 png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); |
1592 } | 1827 } |
1593 #endif | 1828 #endif |
1594 | 1829 |
1595 #ifdef PNG_WRITE_tIME_SUPPORTED | 1830 #ifdef PNG_WRITE_tIME_SUPPORTED |
1596 /* Write the tIME chunk. Use either png_convert_from_struct_tm() | 1831 /* Write the tIME chunk. Use either png_convert_from_struct_tm() |
1597 * or png_convert_from_time_t(), or fill in the structure yourself. | 1832 * or png_convert_from_time_t(), or fill in the structure yourself. |
1598 */ | 1833 */ |
1599 void /* PRIVATE */ | 1834 void /* PRIVATE */ |
1600 png_write_tIME(png_structp png_ptr, png_timep mod_time) | 1835 png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) |
1601 { | 1836 { |
1602 #ifdef PNG_USE_LOCAL_ARRAYS | |
1603 PNG_tIME; | |
1604 #endif | |
1605 png_byte buf[7]; | 1837 png_byte buf[7]; |
1606 | 1838 |
1607 png_debug(1, "in png_write_tIME"); | 1839 png_debug(1, "in png_write_tIME"); |
1608 | 1840 |
1609 if (mod_time->month > 12 || mod_time->month < 1 || | 1841 if (mod_time->month > 12 || mod_time->month < 1 || |
1610 mod_time->day > 31 || mod_time->day < 1 || | 1842 mod_time->day > 31 || mod_time->day < 1 || |
1611 mod_time->hour > 23 || mod_time->second > 60) | 1843 mod_time->hour > 23 || mod_time->second > 60) |
1612 { | 1844 { |
1613 png_warning(png_ptr, "Invalid time specified for tIME chunk"); | 1845 png_warning(png_ptr, "Invalid time specified for tIME chunk"); |
1614 return; | 1846 return; |
1615 } | 1847 } |
1616 | 1848 |
1617 png_save_uint_16(buf, mod_time->year); | 1849 png_save_uint_16(buf, mod_time->year); |
1618 buf[2] = mod_time->month; | 1850 buf[2] = mod_time->month; |
1619 buf[3] = mod_time->day; | 1851 buf[3] = mod_time->day; |
1620 buf[4] = mod_time->hour; | 1852 buf[4] = mod_time->hour; |
1621 buf[5] = mod_time->minute; | 1853 buf[5] = mod_time->minute; |
1622 buf[6] = mod_time->second; | 1854 buf[6] = mod_time->second; |
1623 | 1855 |
1624 png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); | 1856 png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); |
1625 } | 1857 } |
1626 #endif | 1858 #endif |
1627 | 1859 |
1628 /* Initializes the row writing capability of libpng */ | 1860 /* Initializes the row writing capability of libpng */ |
1629 void /* PRIVATE */ | 1861 void /* PRIVATE */ |
1630 png_write_start_row(png_structp png_ptr) | 1862 png_write_start_row(png_structrp png_ptr) |
1631 { | 1863 { |
1632 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 1864 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1633 #ifndef PNG_USE_GLOBAL_ARRAYS | |
1634 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ | 1865 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1635 | 1866 |
1636 /* Start of interlace block */ | 1867 /* Start of interlace block */ |
1637 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; | 1868 static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1638 | 1869 |
1639 /* Offset to next interlace block */ | 1870 /* Offset to next interlace block */ |
1640 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; | 1871 static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1641 | 1872 |
1642 /* Start of interlace block in the y direction */ | 1873 /* Start of interlace block in the y direction */ |
1643 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; | 1874 static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
1644 | 1875 |
1645 /* Offset to next interlace block in the y direction */ | 1876 /* Offset to next interlace block in the y direction */ |
1646 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; | 1877 static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
1647 #endif | |
1648 #endif | 1878 #endif |
1649 | 1879 |
1650 png_size_t buf_size; | 1880 png_alloc_size_t buf_size; |
| 1881 int usr_pixel_depth; |
| 1882 |
| 1883 #ifdef PNG_WRITE_FILTER_SUPPORTED |
| 1884 png_byte filters; |
| 1885 #endif |
1651 | 1886 |
1652 png_debug(1, "in png_write_start_row"); | 1887 png_debug(1, "in png_write_start_row"); |
1653 | 1888 |
1654 buf_size = (png_size_t)(PNG_ROWBYTES( | 1889 usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; |
1655 png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); | 1890 buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; |
| 1891 |
| 1892 /* 1.5.6: added to allow checking in the row write code. */ |
| 1893 png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; |
| 1894 png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; |
1656 | 1895 |
1657 /* Set up row buffer */ | 1896 /* Set up row buffer */ |
1658 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, | 1897 png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); |
1659 (png_uint_32)buf_size); | 1898 |
1660 png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; | 1899 png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; |
1661 | 1900 |
1662 #ifdef PNG_WRITE_FILTER_SUPPORTED | 1901 #ifdef PNG_WRITE_FILTER_SUPPORTED |
1663 /* Set up filtering buffer, if using this filter */ | 1902 filters = png_ptr->do_filter; |
1664 if (png_ptr->do_filter & PNG_FILTER_SUB) | 1903 |
| 1904 if (png_ptr->height == 1) |
| 1905 filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); |
| 1906 |
| 1907 if (png_ptr->width == 1) |
| 1908 filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); |
| 1909 |
| 1910 if (filters == 0) |
| 1911 filters = PNG_FILTER_NONE; |
| 1912 |
| 1913 png_ptr->do_filter = filters; |
| 1914 |
| 1915 if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG | |
| 1916 PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL) |
1665 { | 1917 { |
1666 png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, | 1918 int num_filters = 0; |
1667 (png_uint_32)(png_ptr->rowbytes + 1)); | 1919 |
1668 png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; | 1920 png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); |
| 1921 |
| 1922 if (filters & PNG_FILTER_SUB) |
| 1923 num_filters++; |
| 1924 |
| 1925 if (filters & PNG_FILTER_UP) |
| 1926 num_filters++; |
| 1927 |
| 1928 if (filters & PNG_FILTER_AVG) |
| 1929 num_filters++; |
| 1930 |
| 1931 if (filters & PNG_FILTER_PAETH) |
| 1932 num_filters++; |
| 1933 |
| 1934 if (num_filters > 1) |
| 1935 png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr, |
| 1936 buf_size)); |
1669 } | 1937 } |
1670 | 1938 |
1671 /* We only need to keep the previous row if we are using one of these. */ | 1939 /* We only need to keep the previous row if we are using one of the following |
1672 if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) | 1940 * filters. |
1673 { | 1941 */ |
1674 /* Set up previous row buffer */ | 1942 if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) |
1675 png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, | 1943 png_ptr->prev_row = png_voidcast(png_bytep, |
1676 (png_uint_32)buf_size); | 1944 png_calloc(png_ptr, buf_size)); |
1677 | 1945 #endif /* WRITE_FILTER */ |
1678 if (png_ptr->do_filter & PNG_FILTER_UP) | |
1679 { | |
1680 png_ptr->up_row = (png_bytep)png_malloc(png_ptr, | |
1681 (png_uint_32)(png_ptr->rowbytes + 1)); | |
1682 png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; | |
1683 } | |
1684 | |
1685 if (png_ptr->do_filter & PNG_FILTER_AVG) | |
1686 { | |
1687 png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, | |
1688 (png_uint_32)(png_ptr->rowbytes + 1)); | |
1689 png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; | |
1690 } | |
1691 | |
1692 if (png_ptr->do_filter & PNG_FILTER_PAETH) | |
1693 { | |
1694 png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, | |
1695 (png_uint_32)(png_ptr->rowbytes + 1)); | |
1696 png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; | |
1697 } | |
1698 } | |
1699 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | |
1700 | 1946 |
1701 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 1947 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1702 /* If interlaced, we need to set up width and height of pass */ | 1948 /* If interlaced, we need to set up width and height of pass */ |
1703 if (png_ptr->interlaced) | 1949 if (png_ptr->interlaced != 0) |
1704 { | 1950 { |
1705 if (!(png_ptr->transformations & PNG_INTERLACE)) | 1951 if ((png_ptr->transformations & PNG_INTERLACE) == 0) |
1706 { | 1952 { |
1707 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - | 1953 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - |
1708 png_pass_ystart[0]) / png_pass_yinc[0]; | 1954 png_pass_ystart[0]) / png_pass_yinc[0]; |
| 1955 |
1709 png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - | 1956 png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - |
1710 png_pass_start[0]) / png_pass_inc[0]; | 1957 png_pass_start[0]) / png_pass_inc[0]; |
1711 } | 1958 } |
| 1959 |
1712 else | 1960 else |
1713 { | 1961 { |
1714 png_ptr->num_rows = png_ptr->height; | 1962 png_ptr->num_rows = png_ptr->height; |
1715 png_ptr->usr_width = png_ptr->width; | 1963 png_ptr->usr_width = png_ptr->width; |
1716 } | 1964 } |
1717 } | 1965 } |
| 1966 |
1718 else | 1967 else |
1719 #endif | 1968 #endif |
1720 { | 1969 { |
1721 png_ptr->num_rows = png_ptr->height; | 1970 png_ptr->num_rows = png_ptr->height; |
1722 png_ptr->usr_width = png_ptr->width; | 1971 png_ptr->usr_width = png_ptr->width; |
1723 } | 1972 } |
1724 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | |
1725 png_ptr->zstream.next_out = png_ptr->zbuf; | |
1726 } | 1973 } |
1727 | 1974 |
1728 /* Internal use only. Called when finished processing a row of data. */ | 1975 /* Internal use only. Called when finished processing a row of data. */ |
1729 void /* PRIVATE */ | 1976 void /* PRIVATE */ |
1730 png_write_finish_row(png_structp png_ptr) | 1977 png_write_finish_row(png_structrp png_ptr) |
1731 { | 1978 { |
1732 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 1979 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1733 #ifndef PNG_USE_GLOBAL_ARRAYS | |
1734 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ | 1980 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1735 | 1981 |
1736 /* Start of interlace block */ | 1982 /* Start of interlace block */ |
1737 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; | 1983 static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1738 | 1984 |
1739 /* Offset to next interlace block */ | 1985 /* Offset to next interlace block */ |
1740 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; | 1986 static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1741 | 1987 |
1742 /* Start of interlace block in the y direction */ | 1988 /* Start of interlace block in the y direction */ |
1743 int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; | 1989 static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; |
1744 | 1990 |
1745 /* Offset to next interlace block in the y direction */ | 1991 /* Offset to next interlace block in the y direction */ |
1746 int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; | 1992 static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; |
1747 #endif | 1993 #endif |
1748 #endif | |
1749 | |
1750 int ret; | |
1751 | 1994 |
1752 png_debug(1, "in png_write_finish_row"); | 1995 png_debug(1, "in png_write_finish_row"); |
1753 | 1996 |
1754 /* Next row */ | 1997 /* Next row */ |
1755 png_ptr->row_number++; | 1998 png_ptr->row_number++; |
1756 | 1999 |
1757 /* See if we are done */ | 2000 /* See if we are done */ |
1758 if (png_ptr->row_number < png_ptr->num_rows) | 2001 if (png_ptr->row_number < png_ptr->num_rows) |
1759 return; | 2002 return; |
1760 | 2003 |
1761 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 2004 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1762 /* If interlaced, go to next pass */ | 2005 /* If interlaced, go to next pass */ |
1763 if (png_ptr->interlaced) | 2006 if (png_ptr->interlaced != 0) |
1764 { | 2007 { |
1765 png_ptr->row_number = 0; | 2008 png_ptr->row_number = 0; |
1766 if (png_ptr->transformations & PNG_INTERLACE) | 2009 if ((png_ptr->transformations & PNG_INTERLACE) != 0) |
1767 { | 2010 { |
1768 png_ptr->pass++; | 2011 png_ptr->pass++; |
1769 } | 2012 } |
| 2013 |
1770 else | 2014 else |
1771 { | 2015 { |
1772 /* Loop until we find a non-zero width or height pass */ | 2016 /* Loop until we find a non-zero width or height pass */ |
1773 do | 2017 do |
1774 { | 2018 { |
1775 png_ptr->pass++; | 2019 png_ptr->pass++; |
| 2020 |
1776 if (png_ptr->pass >= 7) | 2021 if (png_ptr->pass >= 7) |
1777 break; | 2022 break; |
| 2023 |
1778 png_ptr->usr_width = (png_ptr->width + | 2024 png_ptr->usr_width = (png_ptr->width + |
1779 png_pass_inc[png_ptr->pass] - 1 - | 2025 png_pass_inc[png_ptr->pass] - 1 - |
1780 png_pass_start[png_ptr->pass]) / | 2026 png_pass_start[png_ptr->pass]) / |
1781 png_pass_inc[png_ptr->pass]; | 2027 png_pass_inc[png_ptr->pass]; |
| 2028 |
1782 png_ptr->num_rows = (png_ptr->height + | 2029 png_ptr->num_rows = (png_ptr->height + |
1783 png_pass_yinc[png_ptr->pass] - 1 - | 2030 png_pass_yinc[png_ptr->pass] - 1 - |
1784 png_pass_ystart[png_ptr->pass]) / | 2031 png_pass_ystart[png_ptr->pass]) / |
1785 png_pass_yinc[png_ptr->pass]; | 2032 png_pass_yinc[png_ptr->pass]; |
1786 if (png_ptr->transformations & PNG_INTERLACE) | 2033 |
| 2034 if ((png_ptr->transformations & PNG_INTERLACE) != 0) |
1787 break; | 2035 break; |
| 2036 |
1788 } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); | 2037 } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); |
1789 | 2038 |
1790 } | 2039 } |
1791 | 2040 |
1792 /* Reset the row above the image for the next pass */ | 2041 /* Reset the row above the image for the next pass */ |
1793 if (png_ptr->pass < 7) | 2042 if (png_ptr->pass < 7) |
1794 { | 2043 { |
1795 if (png_ptr->prev_row != NULL) | 2044 if (png_ptr->prev_row != NULL) |
1796 png_memset(png_ptr->prev_row, 0, | 2045 memset(png_ptr->prev_row, 0, |
1797 (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* | 2046 (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* |
1798 png_ptr->usr_bit_depth, png_ptr->width)) + 1); | 2047 png_ptr->usr_bit_depth, png_ptr->width)) + 1); |
| 2048 |
1799 return; | 2049 return; |
1800 } | 2050 } |
1801 } | 2051 } |
1802 #endif | 2052 #endif |
1803 | 2053 |
1804 /* If we get here, we've just written the last row, so we need | 2054 /* If we get here, we've just written the last row, so we need |
1805 to flush the compressor */ | 2055 to flush the compressor */ |
1806 do | 2056 png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); |
1807 { | |
1808 /* Tell the compressor we are done */ | |
1809 ret = deflate(&png_ptr->zstream, Z_FINISH); | |
1810 /* Check for an error */ | |
1811 if (ret == Z_OK) | |
1812 { | |
1813 /* Check to see if we need more room */ | |
1814 if (!(png_ptr->zstream.avail_out)) | |
1815 { | |
1816 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); | |
1817 png_ptr->zstream.next_out = png_ptr->zbuf; | |
1818 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | |
1819 } | |
1820 } | |
1821 else if (ret != Z_STREAM_END) | |
1822 { | |
1823 if (png_ptr->zstream.msg != NULL) | |
1824 png_error(png_ptr, png_ptr->zstream.msg); | |
1825 else | |
1826 png_error(png_ptr, "zlib error"); | |
1827 } | |
1828 } while (ret != Z_STREAM_END); | |
1829 | |
1830 /* Write any extra space */ | |
1831 if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) | |
1832 { | |
1833 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - | |
1834 png_ptr->zstream.avail_out); | |
1835 } | |
1836 | |
1837 deflateReset(&png_ptr->zstream); | |
1838 png_ptr->zstream.data_type = Z_BINARY; | |
1839 } | 2057 } |
1840 | 2058 |
1841 #ifdef PNG_WRITE_INTERLACING_SUPPORTED | 2059 #ifdef PNG_WRITE_INTERLACING_SUPPORTED |
1842 /* Pick out the correct pixels for the interlace pass. | 2060 /* Pick out the correct pixels for the interlace pass. |
1843 * The basic idea here is to go through the row with a source | 2061 * The basic idea here is to go through the row with a source |
1844 * pointer and a destination pointer (sp and dp), and copy the | 2062 * pointer and a destination pointer (sp and dp), and copy the |
1845 * correct pixels for the pass. As the row gets compacted, | 2063 * correct pixels for the pass. As the row gets compacted, |
1846 * sp will always be >= dp, so we should never overwrite anything. | 2064 * sp will always be >= dp, so we should never overwrite anything. |
1847 * See the default: case for the easiest code to understand. | 2065 * See the default: case for the easiest code to understand. |
1848 */ | 2066 */ |
1849 void /* PRIVATE */ | 2067 void /* PRIVATE */ |
1850 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) | 2068 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) |
1851 { | 2069 { |
1852 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ | 2070 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1853 | 2071 |
1854 #ifndef PNG_USE_GLOBAL_ARRAYS | |
1855 /* Start of interlace block */ | 2072 /* Start of interlace block */ |
1856 int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; | 2073 static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; |
1857 | 2074 |
1858 /* Offset to next interlace block */ | 2075 /* Offset to next interlace block */ |
1859 int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; | 2076 static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; |
1860 #endif | |
1861 | 2077 |
1862 png_debug(1, "in png_do_write_interlace"); | 2078 png_debug(1, "in png_do_write_interlace"); |
1863 | 2079 |
1864 /* We don't have to do anything on the last pass (6) */ | 2080 /* We don't have to do anything on the last pass (6) */ |
1865 #ifdef PNG_USELESS_TESTS_SUPPORTED | |
1866 if (row != NULL && row_info != NULL && pass < 6) | |
1867 #else | |
1868 if (pass < 6) | 2081 if (pass < 6) |
1869 #endif | |
1870 { | 2082 { |
1871 /* Each pixel depth is handled separately */ | 2083 /* Each pixel depth is handled separately */ |
1872 switch (row_info->pixel_depth) | 2084 switch (row_info->pixel_depth) |
1873 { | 2085 { |
1874 case 1: | 2086 case 1: |
1875 { | 2087 { |
1876 png_bytep sp; | 2088 png_bytep sp; |
1877 png_bytep dp; | 2089 png_bytep dp; |
1878 int shift; | 2090 unsigned int shift; |
1879 int d; | 2091 int d; |
1880 int value; | 2092 int value; |
1881 png_uint_32 i; | 2093 png_uint_32 i; |
1882 png_uint_32 row_width = row_info->width; | 2094 png_uint_32 row_width = row_info->width; |
1883 | 2095 |
1884 dp = row; | 2096 dp = row; |
1885 d = 0; | 2097 d = 0; |
1886 shift = 7; | 2098 shift = 7; |
| 2099 |
1887 for (i = png_pass_start[pass]; i < row_width; | 2100 for (i = png_pass_start[pass]; i < row_width; |
1888 i += png_pass_inc[pass]) | 2101 i += png_pass_inc[pass]) |
1889 { | 2102 { |
1890 sp = row + (png_size_t)(i >> 3); | 2103 sp = row + (png_size_t)(i >> 3); |
1891 value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; | 2104 value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; |
1892 d |= (value << shift); | 2105 d |= (value << shift); |
1893 | 2106 |
1894 if (shift == 0) | 2107 if (shift == 0) |
1895 { | 2108 { |
1896 shift = 7; | 2109 shift = 7; |
1897 *dp++ = (png_byte)d; | 2110 *dp++ = (png_byte)d; |
1898 d = 0; | 2111 d = 0; |
1899 } | 2112 } |
| 2113 |
1900 else | 2114 else |
1901 shift--; | 2115 shift--; |
1902 | 2116 |
1903 } | 2117 } |
1904 if (shift != 7) | 2118 if (shift != 7) |
1905 *dp = (png_byte)d; | 2119 *dp = (png_byte)d; |
| 2120 |
1906 break; | 2121 break; |
1907 } | 2122 } |
| 2123 |
1908 case 2: | 2124 case 2: |
1909 { | 2125 { |
1910 png_bytep sp; | 2126 png_bytep sp; |
1911 png_bytep dp; | 2127 png_bytep dp; |
1912 int shift; | 2128 unsigned int shift; |
1913 int d; | 2129 int d; |
1914 int value; | 2130 int value; |
1915 png_uint_32 i; | 2131 png_uint_32 i; |
1916 png_uint_32 row_width = row_info->width; | 2132 png_uint_32 row_width = row_info->width; |
1917 | 2133 |
1918 dp = row; | 2134 dp = row; |
1919 shift = 6; | 2135 shift = 6; |
1920 d = 0; | 2136 d = 0; |
| 2137 |
1921 for (i = png_pass_start[pass]; i < row_width; | 2138 for (i = png_pass_start[pass]; i < row_width; |
1922 i += png_pass_inc[pass]) | 2139 i += png_pass_inc[pass]) |
1923 { | 2140 { |
1924 sp = row + (png_size_t)(i >> 2); | 2141 sp = row + (png_size_t)(i >> 2); |
1925 value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; | 2142 value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; |
1926 d |= (value << shift); | 2143 d |= (value << shift); |
1927 | 2144 |
1928 if (shift == 0) | 2145 if (shift == 0) |
1929 { | 2146 { |
1930 shift = 6; | 2147 shift = 6; |
1931 *dp++ = (png_byte)d; | 2148 *dp++ = (png_byte)d; |
1932 d = 0; | 2149 d = 0; |
1933 } | 2150 } |
| 2151 |
1934 else | 2152 else |
1935 shift -= 2; | 2153 shift -= 2; |
1936 } | 2154 } |
1937 if (shift != 6) | 2155 if (shift != 6) |
1938 *dp = (png_byte)d; | 2156 *dp = (png_byte)d; |
| 2157 |
1939 break; | 2158 break; |
1940 } | 2159 } |
| 2160 |
1941 case 4: | 2161 case 4: |
1942 { | 2162 { |
1943 png_bytep sp; | 2163 png_bytep sp; |
1944 png_bytep dp; | 2164 png_bytep dp; |
1945 int shift; | 2165 unsigned int shift; |
1946 int d; | 2166 int d; |
1947 int value; | 2167 int value; |
1948 png_uint_32 i; | 2168 png_uint_32 i; |
1949 png_uint_32 row_width = row_info->width; | 2169 png_uint_32 row_width = row_info->width; |
1950 | 2170 |
1951 dp = row; | 2171 dp = row; |
1952 shift = 4; | 2172 shift = 4; |
1953 d = 0; | 2173 d = 0; |
1954 for (i = png_pass_start[pass]; i < row_width; | 2174 for (i = png_pass_start[pass]; i < row_width; |
1955 i += png_pass_inc[pass]) | 2175 i += png_pass_inc[pass]) |
1956 { | 2176 { |
1957 sp = row + (png_size_t)(i >> 1); | 2177 sp = row + (png_size_t)(i >> 1); |
1958 value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; | 2178 value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; |
1959 d |= (value << shift); | 2179 d |= (value << shift); |
1960 | 2180 |
1961 if (shift == 0) | 2181 if (shift == 0) |
1962 { | 2182 { |
1963 shift = 4; | 2183 shift = 4; |
1964 *dp++ = (png_byte)d; | 2184 *dp++ = (png_byte)d; |
1965 d = 0; | 2185 d = 0; |
1966 } | 2186 } |
| 2187 |
1967 else | 2188 else |
1968 shift -= 4; | 2189 shift -= 4; |
1969 } | 2190 } |
1970 if (shift != 4) | 2191 if (shift != 4) |
1971 *dp = (png_byte)d; | 2192 *dp = (png_byte)d; |
| 2193 |
1972 break; | 2194 break; |
1973 } | 2195 } |
| 2196 |
1974 default: | 2197 default: |
1975 { | 2198 { |
1976 png_bytep sp; | 2199 png_bytep sp; |
1977 png_bytep dp; | 2200 png_bytep dp; |
1978 png_uint_32 i; | 2201 png_uint_32 i; |
1979 png_uint_32 row_width = row_info->width; | 2202 png_uint_32 row_width = row_info->width; |
1980 png_size_t pixel_bytes; | 2203 png_size_t pixel_bytes; |
1981 | 2204 |
1982 /* Start at the beginning */ | 2205 /* Start at the beginning */ |
1983 dp = row; | 2206 dp = row; |
| 2207 |
1984 /* Find out how many bytes each pixel takes up */ | 2208 /* Find out how many bytes each pixel takes up */ |
1985 pixel_bytes = (row_info->pixel_depth >> 3); | 2209 pixel_bytes = (row_info->pixel_depth >> 3); |
1986 /* Loop through the row, only looking at the pixels that | 2210 |
1987 matter */ | 2211 /* Loop through the row, only looking at the pixels that matter */ |
1988 for (i = png_pass_start[pass]; i < row_width; | 2212 for (i = png_pass_start[pass]; i < row_width; |
1989 i += png_pass_inc[pass]) | 2213 i += png_pass_inc[pass]) |
1990 { | 2214 { |
1991 /* Find out where the original pixel is */ | 2215 /* Find out where the original pixel is */ |
1992 sp = row + (png_size_t)i * pixel_bytes; | 2216 sp = row + (png_size_t)i * pixel_bytes; |
| 2217 |
1993 /* Move the pixel */ | 2218 /* Move the pixel */ |
1994 if (dp != sp) | 2219 if (dp != sp) |
1995 png_memcpy(dp, sp, pixel_bytes); | 2220 memcpy(dp, sp, pixel_bytes); |
| 2221 |
1996 /* Next pixel */ | 2222 /* Next pixel */ |
1997 dp += pixel_bytes; | 2223 dp += pixel_bytes; |
1998 } | 2224 } |
1999 break; | 2225 break; |
2000 } | 2226 } |
2001 } | 2227 } |
2002 /* Set new row width */ | 2228 /* Set new row width */ |
2003 row_info->width = (row_info->width + | 2229 row_info->width = (row_info->width + |
2004 png_pass_inc[pass] - 1 - | 2230 png_pass_inc[pass] - 1 - |
2005 png_pass_start[pass]) / | 2231 png_pass_start[pass]) / |
2006 png_pass_inc[pass]; | 2232 png_pass_inc[pass]; |
2007 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, | 2233 |
2008 row_info->width); | 2234 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, |
| 2235 row_info->width); |
2009 } | 2236 } |
2010 } | 2237 } |
2011 #endif | 2238 #endif |
2012 | 2239 |
| 2240 |
2013 /* This filters the row, chooses which filter to use, if it has not already | 2241 /* This filters the row, chooses which filter to use, if it has not already |
2014 * been specified by the application, and then writes the row out with the | 2242 * been specified by the application, and then writes the row out with the |
2015 * chosen filter. | 2243 * chosen filter. |
2016 */ | 2244 */ |
2017 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) | 2245 static void /* PRIVATE */ |
2018 #define PNG_HISHIFT 10 | 2246 png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, |
2019 #define PNG_LOMASK ((png_uint_32)0xffffL) | 2247 png_size_t row_bytes); |
2020 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) | 2248 |
| 2249 #ifdef PNG_WRITE_FILTER_SUPPORTED |
| 2250 static png_size_t /* PRIVATE */ |
| 2251 png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, |
| 2252 const png_size_t row_bytes, const png_size_t lmins) |
| 2253 { |
| 2254 png_bytep rp, dp, lp; |
| 2255 png_size_t i; |
| 2256 png_size_t sum = 0; |
| 2257 int v; |
| 2258 |
| 2259 png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; |
| 2260 |
| 2261 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; |
| 2262 i++, rp++, dp++) |
| 2263 { |
| 2264 v = *dp = *rp; |
| 2265 sum += (v < 128) ? v : 256 - v; |
| 2266 } |
| 2267 |
| 2268 for (lp = png_ptr->row_buf + 1; i < row_bytes; |
| 2269 i++, rp++, lp++, dp++) |
| 2270 { |
| 2271 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); |
| 2272 sum += (v < 128) ? v : 256 - v; |
| 2273 |
| 2274 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2275 break; |
| 2276 } |
| 2277 |
| 2278 return (sum); |
| 2279 } |
| 2280 |
| 2281 static png_size_t /* PRIVATE */ |
| 2282 png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, |
| 2283 const png_size_t lmins) |
| 2284 { |
| 2285 png_bytep rp, dp, pp; |
| 2286 png_size_t i; |
| 2287 png_size_t sum = 0; |
| 2288 int v; |
| 2289 |
| 2290 png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; |
| 2291 |
| 2292 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2293 pp = png_ptr->prev_row + 1; i < row_bytes; |
| 2294 i++, rp++, pp++, dp++) |
| 2295 { |
| 2296 v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); |
| 2297 sum += (v < 128) ? v : 256 - v; |
| 2298 |
| 2299 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2300 break; |
| 2301 } |
| 2302 |
| 2303 return (sum); |
| 2304 } |
| 2305 |
| 2306 static png_size_t /* PRIVATE */ |
| 2307 png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, |
| 2308 const png_size_t row_bytes, const png_size_t lmins) |
| 2309 { |
| 2310 png_bytep rp, dp, pp, lp; |
| 2311 png_uint_32 i; |
| 2312 png_size_t sum = 0; |
| 2313 int v; |
| 2314 |
| 2315 png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; |
| 2316 |
| 2317 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2318 pp = png_ptr->prev_row + 1; i < bpp; i++) |
| 2319 { |
| 2320 v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); |
| 2321 |
| 2322 sum += (v < 128) ? v : 256 - v; |
| 2323 } |
| 2324 |
| 2325 for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) |
| 2326 { |
| 2327 v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) |
| 2328 & 0xff); |
| 2329 |
| 2330 sum += (v < 128) ? v : 256 - v; |
| 2331 |
| 2332 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2333 break; |
| 2334 } |
| 2335 |
| 2336 return (sum); |
| 2337 } |
| 2338 |
| 2339 static png_size_t /* PRIVATE */ |
| 2340 png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, |
| 2341 const png_size_t row_bytes, const png_size_t lmins) |
| 2342 { |
| 2343 png_bytep rp, dp, pp, cp, lp; |
| 2344 png_size_t i; |
| 2345 png_size_t sum = 0; |
| 2346 int v; |
| 2347 |
| 2348 png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; |
| 2349 |
| 2350 for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, |
| 2351 pp = png_ptr->prev_row + 1; i < bpp; i++) |
| 2352 { |
| 2353 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); |
| 2354 |
| 2355 sum += (v < 128) ? v : 256 - v; |
| 2356 } |
| 2357 |
| 2358 for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; |
| 2359 i++) |
| 2360 { |
| 2361 int a, b, c, pa, pb, pc, p; |
| 2362 |
| 2363 b = *pp++; |
| 2364 c = *cp++; |
| 2365 a = *lp++; |
| 2366 |
| 2367 p = b - c; |
| 2368 pc = a - c; |
| 2369 |
| 2370 #ifdef PNG_USE_ABS |
| 2371 pa = abs(p); |
| 2372 pb = abs(pc); |
| 2373 pc = abs(p + pc); |
| 2374 #else |
| 2375 pa = p < 0 ? -p : p; |
| 2376 pb = pc < 0 ? -pc : pc; |
| 2377 pc = (p + pc) < 0 ? -(p + pc) : p + pc; |
| 2378 #endif |
| 2379 |
| 2380 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; |
| 2381 |
| 2382 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); |
| 2383 |
| 2384 sum += (v < 128) ? v : 256 - v; |
| 2385 |
| 2386 if (sum > lmins) /* We are already worse, don't continue. */ |
| 2387 break; |
| 2388 } |
| 2389 |
| 2390 return (sum); |
| 2391 } |
| 2392 #endif /* WRITE_FILTER */ |
| 2393 |
2021 void /* PRIVATE */ | 2394 void /* PRIVATE */ |
2022 png_write_find_filter(png_structp png_ptr, png_row_infop row_info) | 2395 png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) |
2023 { | 2396 { |
| 2397 #ifndef PNG_WRITE_FILTER_SUPPORTED |
| 2398 png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); |
| 2399 #else |
| 2400 png_byte filter_to_do = png_ptr->do_filter; |
| 2401 png_bytep row_buf; |
2024 png_bytep best_row; | 2402 png_bytep best_row; |
2025 #ifdef PNG_WRITE_FILTER_SUPPORTED | 2403 png_uint_32 bpp; |
2026 png_bytep prev_row, row_buf; | 2404 png_size_t mins; |
2027 png_uint_32 mins, bpp; | 2405 png_size_t row_bytes = row_info->rowbytes; |
2028 png_byte filter_to_do = png_ptr->do_filter; | |
2029 png_uint_32 row_bytes = row_info->rowbytes; | |
2030 | 2406 |
2031 png_debug(1, "in png_write_find_filter"); | 2407 png_debug(1, "in png_write_find_filter"); |
2032 | 2408 |
2033 /* Find out how many bytes offset each pixel is */ | 2409 /* Find out how many bytes offset each pixel is */ |
2034 bpp = (row_info->pixel_depth + 7) >> 3; | 2410 bpp = (row_info->pixel_depth + 7) >> 3; |
2035 | 2411 |
2036 prev_row = png_ptr->prev_row; | 2412 row_buf = png_ptr->row_buf; |
2037 #endif | 2413 mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the |
2038 best_row = png_ptr->row_buf; | 2414 running sum */; |
2039 #ifdef PNG_WRITE_FILTER_SUPPORTED | |
2040 row_buf = best_row; | |
2041 mins = PNG_MAXSUM; | |
2042 | 2415 |
2043 /* The prediction method we use is to find which method provides the | 2416 /* The prediction method we use is to find which method provides the |
2044 * smallest value when summing the absolute values of the distances | 2417 * smallest value when summing the absolute values of the distances |
2045 * from zero, using anything >= 128 as negative numbers. This is known | 2418 * from zero, using anything >= 128 as negative numbers. This is known |
2046 * as the "minimum sum of absolute differences" heuristic. Other | 2419 * as the "minimum sum of absolute differences" heuristic. Other |
2047 * heuristics are the "weighted minimum sum of absolute differences" | 2420 * heuristics are the "weighted minimum sum of absolute differences" |
2048 * (experimental and can in theory improve compression), and the "zlib | 2421 * (experimental and can in theory improve compression), and the "zlib |
2049 * predictive" method (not implemented yet), which does test compressions | 2422 * predictive" method (not implemented yet), which does test compressions |
2050 * of lines using different filter methods, and then chooses the | 2423 * of lines using different filter methods, and then chooses the |
2051 * (series of) filter(s) that give minimum compressed data size (VERY | 2424 * (series of) filter(s) that give minimum compressed data size (VERY |
2052 * computationally expensive). | 2425 * computationally expensive). |
2053 * | 2426 * |
2054 * GRR 980525: consider also | 2427 * GRR 980525: consider also |
| 2428 * |
2055 * (1) minimum sum of absolute differences from running average (i.e., | 2429 * (1) minimum sum of absolute differences from running average (i.e., |
2056 * keep running sum of non-absolute differences & count of bytes) | 2430 * keep running sum of non-absolute differences & count of bytes) |
2057 * [track dispersion, too? restart average if dispersion too large?] | 2431 * [track dispersion, too? restart average if dispersion too large?] |
| 2432 * |
2058 * (1b) minimum sum of absolute differences from sliding average, probably | 2433 * (1b) minimum sum of absolute differences from sliding average, probably |
2059 * with window size <= deflate window (usually 32K) | 2434 * with window size <= deflate window (usually 32K) |
| 2435 * |
2060 * (2) minimum sum of squared differences from zero or running average | 2436 * (2) minimum sum of squared differences from zero or running average |
2061 * (i.e., ~ root-mean-square approach) | 2437 * (i.e., ~ root-mean-square approach) |
2062 */ | 2438 */ |
2063 | 2439 |
2064 | 2440 |
2065 /* We don't need to test the 'no filter' case if this is the only filter | 2441 /* We don't need to test the 'no filter' case if this is the only filter |
2066 * that has been chosen, as it doesn't actually do anything to the data. | 2442 * that has been chosen, as it doesn't actually do anything to the data. |
2067 */ | 2443 */ |
2068 if ((filter_to_do & PNG_FILTER_NONE) && | 2444 best_row = png_ptr->row_buf; |
2069 filter_to_do != PNG_FILTER_NONE) | 2445 |
| 2446 |
| 2447 if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE) |
2070 { | 2448 { |
2071 png_bytep rp; | 2449 png_bytep rp; |
2072 png_uint_32 sum = 0; | 2450 png_size_t sum = 0; |
2073 png_uint_32 i; | 2451 png_size_t i; |
2074 int v; | 2452 int v; |
2075 | 2453 |
2076 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) | 2454 if (PNG_SIZE_MAX/128 <= row_bytes) |
2077 { | 2455 { |
2078 v = *rp; | 2456 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) |
2079 sum += (v < 128) ? v : 256 - v; | 2457 { |
| 2458 /* Check for overflow */ |
| 2459 if (sum > PNG_SIZE_MAX/128 - 256) |
| 2460 break; |
| 2461 |
| 2462 v = *rp; |
| 2463 sum += (v < 128) ? v : 256 - v; |
| 2464 } |
| 2465 } |
| 2466 else /* Overflow is not possible */ |
| 2467 { |
| 2468 for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) |
| 2469 { |
| 2470 v = *rp; |
| 2471 sum += (v < 128) ? v : 256 - v; |
| 2472 } |
2080 } | 2473 } |
2081 | 2474 |
2082 mins = sum; | 2475 mins = sum; |
2083 } | 2476 } |
2084 | 2477 |
2085 /* Sub filter */ | 2478 /* Sub filter */ |
2086 if (filter_to_do == PNG_FILTER_SUB) | 2479 if (filter_to_do == PNG_FILTER_SUB) |
2087 /* It's the only filter so no testing is needed */ | 2480 /* It's the only filter so no testing is needed */ |
2088 { | 2481 { |
2089 png_bytep rp, lp, dp; | 2482 (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); |
2090 png_uint_32 i; | 2483 best_row = png_ptr->try_row; |
2091 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; | |
2092 i++, rp++, dp++) | |
2093 { | |
2094 *dp = *rp; | |
2095 } | |
2096 for (lp = row_buf + 1; i < row_bytes; | |
2097 i++, rp++, lp++, dp++) | |
2098 { | |
2099 *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); | |
2100 } | |
2101 best_row = png_ptr->sub_row; | |
2102 } | 2484 } |
2103 | 2485 |
2104 else if (filter_to_do & PNG_FILTER_SUB) | 2486 else if ((filter_to_do & PNG_FILTER_SUB) != 0) |
2105 { | 2487 { |
2106 png_bytep rp, dp, lp; | 2488 png_size_t sum; |
2107 png_uint_32 sum = 0, lmins = mins; | 2489 png_size_t lmins = mins; |
2108 png_uint_32 i; | |
2109 int v; | |
2110 | 2490 |
2111 for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; | 2491 sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); |
2112 i++, rp++, dp++) | |
2113 { | |
2114 v = *dp = *rp; | |
2115 | |
2116 sum += (v < 128) ? v : 256 - v; | |
2117 } | |
2118 for (lp = row_buf + 1; i < row_bytes; | |
2119 i++, rp++, lp++, dp++) | |
2120 { | |
2121 v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); | |
2122 | |
2123 sum += (v < 128) ? v : 256 - v; | |
2124 | |
2125 if (sum > lmins) /* We are already worse, don't continue. */ | |
2126 break; | |
2127 } | |
2128 | 2492 |
2129 if (sum < mins) | 2493 if (sum < mins) |
2130 { | 2494 { |
2131 mins = sum; | 2495 mins = sum; |
2132 best_row = png_ptr->sub_row; | 2496 best_row = png_ptr->try_row; |
| 2497 if (png_ptr->tst_row != NULL) |
| 2498 { |
| 2499 png_ptr->try_row = png_ptr->tst_row; |
| 2500 png_ptr->tst_row = best_row; |
| 2501 } |
2133 } | 2502 } |
2134 } | 2503 } |
2135 | 2504 |
2136 /* Up filter */ | 2505 /* Up filter */ |
2137 if (filter_to_do == PNG_FILTER_UP) | 2506 if (filter_to_do == PNG_FILTER_UP) |
2138 { | 2507 { |
2139 png_bytep rp, dp, pp; | 2508 (void) png_setup_up_row(png_ptr, row_bytes, mins); |
2140 png_uint_32 i; | 2509 best_row = png_ptr->try_row; |
2141 | |
2142 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, | |
2143 pp = prev_row + 1; i < row_bytes; | |
2144 i++, rp++, pp++, dp++) | |
2145 { | |
2146 *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); | |
2147 } | |
2148 best_row = png_ptr->up_row; | |
2149 } | 2510 } |
2150 | 2511 |
2151 else if (filter_to_do & PNG_FILTER_UP) | 2512 else if ((filter_to_do & PNG_FILTER_UP) != 0) |
2152 { | 2513 { |
2153 png_bytep rp, dp, pp; | 2514 png_size_t sum; |
2154 png_uint_32 sum = 0, lmins = mins; | 2515 png_size_t lmins = mins; |
2155 png_uint_32 i; | |
2156 int v; | |
2157 | 2516 |
2158 for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, | 2517 sum = png_setup_up_row(png_ptr, row_bytes, lmins); |
2159 pp = prev_row + 1; i < row_bytes; i++) | |
2160 { | |
2161 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); | |
2162 | |
2163 sum += (v < 128) ? v : 256 - v; | |
2164 | |
2165 if (sum > lmins) /* We are already worse, don't continue. */ | |
2166 break; | |
2167 } | |
2168 | 2518 |
2169 if (sum < mins) | 2519 if (sum < mins) |
2170 { | 2520 { |
2171 mins = sum; | 2521 mins = sum; |
2172 best_row = png_ptr->up_row; | 2522 best_row = png_ptr->try_row; |
| 2523 if (png_ptr->tst_row != NULL) |
| 2524 { |
| 2525 png_ptr->try_row = png_ptr->tst_row; |
| 2526 png_ptr->tst_row = best_row; |
| 2527 } |
2173 } | 2528 } |
2174 } | 2529 } |
2175 | 2530 |
2176 /* Avg filter */ | 2531 /* Avg filter */ |
2177 if (filter_to_do == PNG_FILTER_AVG) | 2532 if (filter_to_do == PNG_FILTER_AVG) |
2178 { | 2533 { |
2179 png_bytep rp, dp, pp, lp; | 2534 (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins); |
2180 png_uint_32 i; | 2535 best_row = png_ptr->try_row; |
2181 for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, | |
2182 pp = prev_row + 1; i < bpp; i++) | |
2183 { | |
2184 *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); | |
2185 } | |
2186 for (lp = row_buf + 1; i < row_bytes; i++) | |
2187 { | |
2188 *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) | |
2189 & 0xff); | |
2190 } | |
2191 best_row = png_ptr->avg_row; | |
2192 } | 2536 } |
2193 | 2537 |
2194 else if (filter_to_do & PNG_FILTER_AVG) | 2538 else if ((filter_to_do & PNG_FILTER_AVG) != 0) |
2195 { | 2539 { |
2196 png_bytep rp, dp, pp, lp; | 2540 png_size_t sum; |
2197 png_uint_32 sum = 0, lmins = mins; | 2541 png_size_t lmins = mins; |
2198 png_uint_32 i; | |
2199 int v; | |
2200 | 2542 |
2201 for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, | 2543 sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); |
2202 pp = prev_row + 1; i < bpp; i++) | |
2203 { | |
2204 v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); | |
2205 | |
2206 sum += (v < 128) ? v : 256 - v; | |
2207 } | |
2208 for (lp = row_buf + 1; i < row_bytes; i++) | |
2209 { | |
2210 v = *dp++ = | |
2211 (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); | |
2212 | |
2213 sum += (v < 128) ? v : 256 - v; | |
2214 | |
2215 if (sum > lmins) /* We are already worse, don't continue. */ | |
2216 break; | |
2217 } | |
2218 | 2544 |
2219 if (sum < mins) | 2545 if (sum < mins) |
2220 { | 2546 { |
2221 mins = sum; | 2547 mins = sum; |
2222 best_row = png_ptr->avg_row; | 2548 best_row = png_ptr->try_row; |
| 2549 if (png_ptr->tst_row != NULL) |
| 2550 { |
| 2551 png_ptr->try_row = png_ptr->tst_row; |
| 2552 png_ptr->tst_row = best_row; |
| 2553 } |
2223 } | 2554 } |
2224 } | 2555 } |
2225 | 2556 |
2226 /* Paeth filter */ | 2557 /* Paeth filter */ |
2227 if (filter_to_do == PNG_FILTER_PAETH) | 2558 if ((filter_to_do == PNG_FILTER_PAETH) != 0) |
2228 { | 2559 { |
2229 png_bytep rp, dp, pp, cp, lp; | 2560 (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins); |
2230 png_uint_32 i; | 2561 best_row = png_ptr->try_row; |
2231 for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, | |
2232 pp = prev_row + 1; i < bpp; i++) | |
2233 { | |
2234 *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); | |
2235 } | |
2236 | |
2237 for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) | |
2238 { | |
2239 int a, b, c, pa, pb, pc, p; | |
2240 | |
2241 b = *pp++; | |
2242 c = *cp++; | |
2243 a = *lp++; | |
2244 | |
2245 p = b - c; | |
2246 pc = a - c; | |
2247 | |
2248 #ifdef PNG_USE_ABS | |
2249 pa = abs(p); | |
2250 pb = abs(pc); | |
2251 pc = abs(p + pc); | |
2252 #else | |
2253 pa = p < 0 ? -p : p; | |
2254 pb = pc < 0 ? -pc : pc; | |
2255 pc = (p + pc) < 0 ? -(p + pc) : p + pc; | |
2256 #endif | |
2257 | |
2258 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; | |
2259 | |
2260 *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); | |
2261 } | |
2262 best_row = png_ptr->paeth_row; | |
2263 } | 2562 } |
2264 | 2563 |
2265 else if (filter_to_do & PNG_FILTER_PAETH) | 2564 else if ((filter_to_do & PNG_FILTER_PAETH) != 0) |
2266 { | 2565 { |
2267 png_bytep rp, dp, pp, cp, lp; | 2566 png_size_t sum; |
2268 png_uint_32 sum = 0, lmins = mins; | 2567 png_size_t lmins = mins; |
2269 png_uint_32 i; | |
2270 int v; | |
2271 | 2568 |
2272 for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, | 2569 sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); |
2273 pp = prev_row + 1; i < bpp; i++) | |
2274 { | |
2275 v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); | |
2276 | |
2277 sum += (v < 128) ? v : 256 - v; | |
2278 } | |
2279 | |
2280 for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) | |
2281 { | |
2282 int a, b, c, pa, pb, pc, p; | |
2283 | |
2284 b = *pp++; | |
2285 c = *cp++; | |
2286 a = *lp++; | |
2287 | |
2288 #ifndef PNG_SLOW_PAETH | |
2289 p = b - c; | |
2290 pc = a - c; | |
2291 #ifdef PNG_USE_ABS | |
2292 pa = abs(p); | |
2293 pb = abs(pc); | |
2294 pc = abs(p + pc); | |
2295 #else | |
2296 pa = p < 0 ? -p : p; | |
2297 pb = pc < 0 ? -pc : pc; | |
2298 pc = (p + pc) < 0 ? -(p + pc) : p + pc; | |
2299 #endif | |
2300 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; | |
2301 #else /* PNG_SLOW_PAETH */ | |
2302 p = a + b - c; | |
2303 pa = abs(p - a); | |
2304 pb = abs(p - b); | |
2305 pc = abs(p - c); | |
2306 if (pa <= pb && pa <= pc) | |
2307 p = a; | |
2308 else if (pb <= pc) | |
2309 p = b; | |
2310 else | |
2311 p = c; | |
2312 #endif /* PNG_SLOW_PAETH */ | |
2313 | |
2314 v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); | |
2315 | |
2316 sum += (v < 128) ? v : 256 - v; | |
2317 | |
2318 if (sum > lmins) /* We are already worse, don't continue. */ | |
2319 break; | |
2320 } | |
2321 | 2570 |
2322 if (sum < mins) | 2571 if (sum < mins) |
2323 { | 2572 { |
2324 best_row = png_ptr->paeth_row; | 2573 best_row = png_ptr->try_row; |
| 2574 if (png_ptr->tst_row != NULL) |
| 2575 { |
| 2576 png_ptr->try_row = png_ptr->tst_row; |
| 2577 png_ptr->tst_row = best_row; |
| 2578 } |
2325 } | 2579 } |
2326 } | 2580 } |
2327 #endif /* PNG_WRITE_FILTER_SUPPORTED */ | 2581 |
2328 /* Do the actual writing of the filtered row data from the chosen filter. */ | 2582 /* Do the actual writing of the filtered row data from the chosen filter. */ |
| 2583 png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); |
2329 | 2584 |
2330 png_write_filtered_row(png_ptr, best_row); | 2585 #endif /* WRITE_FILTER */ |
2331 } | 2586 } |
2332 | 2587 |
2333 | 2588 |
2334 /* Do the actual writing of a previously filtered row. */ | 2589 /* Do the actual writing of a previously filtered row. */ |
2335 void /* PRIVATE */ | 2590 static void |
2336 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) | 2591 png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, |
| 2592 png_size_t full_row_length/*includes filter byte*/) |
2337 { | 2593 { |
2338 png_debug(1, "in png_write_filtered_row"); | 2594 png_debug(1, "in png_write_filtered_row"); |
2339 | 2595 |
2340 png_debug1(2, "filter = %d", filtered_row[0]); | 2596 png_debug1(2, "filter = %d", filtered_row[0]); |
2341 /* Set up the zlib input buffer */ | |
2342 | 2597 |
2343 png_ptr->zstream.next_in = filtered_row; | 2598 png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); |
2344 png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; | |
2345 /* Repeat until we have compressed all the data */ | |
2346 do | |
2347 { | |
2348 int ret; /* Return of zlib */ | |
2349 | 2599 |
2350 /* Compress the data */ | 2600 #ifdef PNG_WRITE_FILTER_SUPPORTED |
2351 ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); | |
2352 /* Check for compression errors */ | |
2353 if (ret != Z_OK) | |
2354 { | |
2355 if (png_ptr->zstream.msg != NULL) | |
2356 png_error(png_ptr, png_ptr->zstream.msg); | |
2357 else | |
2358 png_error(png_ptr, "zlib error"); | |
2359 } | |
2360 | |
2361 /* See if it is time to write another IDAT */ | |
2362 if (!(png_ptr->zstream.avail_out)) | |
2363 { | |
2364 /* Write the IDAT and reset the zlib output buffer */ | |
2365 png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); | |
2366 png_ptr->zstream.next_out = png_ptr->zbuf; | |
2367 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; | |
2368 } | |
2369 /* Repeat until all data has been compressed */ | |
2370 } while (png_ptr->zstream.avail_in); | |
2371 | |
2372 /* Swap the current and previous rows */ | 2601 /* Swap the current and previous rows */ |
2373 if (png_ptr->prev_row != NULL) | 2602 if (png_ptr->prev_row != NULL) |
2374 { | 2603 { |
2375 png_bytep tptr; | 2604 png_bytep tptr; |
2376 | 2605 |
2377 tptr = png_ptr->prev_row; | 2606 tptr = png_ptr->prev_row; |
2378 png_ptr->prev_row = png_ptr->row_buf; | 2607 png_ptr->prev_row = png_ptr->row_buf; |
2379 png_ptr->row_buf = tptr; | 2608 png_ptr->row_buf = tptr; |
2380 } | 2609 } |
| 2610 #endif /* WRITE_FILTER */ |
2381 | 2611 |
2382 /* Finish row - updates counters and flushes zlib if last row */ | 2612 /* Finish row - updates counters and flushes zlib if last row */ |
2383 png_write_finish_row(png_ptr); | 2613 png_write_finish_row(png_ptr); |
2384 | 2614 |
2385 #ifdef PNG_WRITE_FLUSH_SUPPORTED | 2615 #ifdef PNG_WRITE_FLUSH_SUPPORTED |
2386 png_ptr->flush_rows++; | 2616 png_ptr->flush_rows++; |
2387 | 2617 |
2388 if (png_ptr->flush_dist > 0 && | 2618 if (png_ptr->flush_dist > 0 && |
2389 png_ptr->flush_rows >= png_ptr->flush_dist) | 2619 png_ptr->flush_rows >= png_ptr->flush_dist) |
2390 { | 2620 { |
2391 png_write_flush(png_ptr); | 2621 png_write_flush(png_ptr); |
2392 } | 2622 } |
2393 #endif | 2623 #endif /* WRITE_FLUSH */ |
2394 } | 2624 } |
2395 #endif /* PNG_WRITE_SUPPORTED */ | 2625 #endif /* WRITE */ |
OLD | NEW |