1 :
2 : /* pngwutil.c - utilities to write a PNG file
3 : *
4 : * Last changed in libpng 1.5.6 [November 3, 2011]
5 : * Copyright (c) 1998-2011 Glenn Randers-Pehrson
6 : * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 : * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8 : *
9 : * This code is released under the libpng license.
10 : * For conditions of distribution and use, see the disclaimer
11 : * and license in png.h
12 : */
13 :
14 : #include "pngpriv.h"
15 :
16 : #ifdef PNG_WRITE_SUPPORTED
17 :
18 : #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
19 : /* Place a 32-bit number into a buffer in PNG byte order. We work
20 : * with unsigned numbers for convenience, although one supported
21 : * ancillary chunk uses signed (two's complement) numbers.
22 : */
23 : void PNGAPI
24 512 : png_save_uint_32(png_bytep buf, png_uint_32 i)
25 : {
26 512 : buf[0] = (png_byte)((i >> 24) & 0xff);
27 512 : buf[1] = (png_byte)((i >> 16) & 0xff);
28 512 : buf[2] = (png_byte)((i >> 8) & 0xff);
29 512 : buf[3] = (png_byte)(i & 0xff);
30 512 : }
31 :
32 : #ifdef PNG_SAVE_INT_32_SUPPORTED
33 : /* The png_save_int_32 function assumes integers are stored in two's
34 : * complement format. If this isn't the case, then this routine needs to
35 : * be modified to write data in two's complement format. Note that,
36 : * the following works correctly even if png_int_32 has more than 32 bits
37 : * (compare the more complex code required on read for sign extention.)
38 : */
39 : void PNGAPI
40 : png_save_int_32(png_bytep buf, png_int_32 i)
41 : {
42 : buf[0] = (png_byte)((i >> 24) & 0xff);
43 : buf[1] = (png_byte)((i >> 16) & 0xff);
44 : buf[2] = (png_byte)((i >> 8) & 0xff);
45 : buf[3] = (png_byte)(i & 0xff);
46 : }
47 : #endif
48 :
49 : /* Place a 16-bit number into a buffer in PNG byte order.
50 : * The parameter is declared unsigned int, not png_uint_16,
51 : * just to avoid potential problems on pre-ANSI C compilers.
52 : */
53 : void PNGAPI
54 36 : png_save_uint_16(png_bytep buf, unsigned int i)
55 : {
56 36 : buf[0] = (png_byte)((i >> 8) & 0xff);
57 36 : buf[1] = (png_byte)(i & 0xff);
58 36 : }
59 : #endif
60 :
61 : /* Simple function to write the signature. If we have already written
62 : * the magic bytes of the signature, or more likely, the PNG stream is
63 : * being embedded into another stream and doesn't need its own signature,
64 : * we should call png_set_sig_bytes() to tell libpng how many of the
65 : * bytes have already been written.
66 : */
67 : void PNGAPI
68 26 : png_write_sig(png_structp png_ptr)
69 : {
70 26 : png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
71 :
72 : #ifdef PNG_IO_STATE_SUPPORTED
73 : /* Inform the I/O callback that the signature is being written */
74 : png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
75 : #endif
76 :
77 : /* Write the rest of the 8 byte signature */
78 26 : png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
79 26 : (png_size_t)(8 - png_ptr->sig_bytes));
80 :
81 26 : if (png_ptr->sig_bytes < 3)
82 26 : png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
83 26 : }
84 :
85 : /* Write the start of a PNG chunk. The type is the chunk type.
86 : * The total_length is the sum of the lengths of all the data you will be
87 : * passing in png_write_chunk_data().
88 : */
89 : static void
90 115 : png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
91 : png_uint_32 length)
92 : {
93 : png_byte buf[8];
94 :
95 : #if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
96 : PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
97 : png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
98 : #endif
99 :
100 115 : if (png_ptr == NULL)
101 0 : return;
102 :
103 : #ifdef PNG_IO_STATE_SUPPORTED
104 : /* Inform the I/O callback that the chunk header is being written.
105 : * PNG_IO_CHUNK_HDR requires a single I/O call.
106 : */
107 : png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
108 : #endif
109 :
110 : /* Write the length and the chunk name */
111 115 : png_save_uint_32(buf, length);
112 115 : png_save_uint_32(buf + 4, chunk_name);
113 115 : png_write_data(png_ptr, buf, 8);
114 :
115 : /* Put the chunk name into png_ptr->chunk_name */
116 115 : png_ptr->chunk_name = chunk_name;
117 :
118 : /* Reset the crc and run it over the chunk name */
119 115 : png_reset_crc(png_ptr);
120 :
121 115 : png_calculate_crc(png_ptr, buf + 4, 4);
122 :
123 : #ifdef PNG_IO_STATE_SUPPORTED
124 : /* Inform the I/O callback that chunk data will (possibly) be written.
125 : * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
126 : */
127 : png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
128 : #endif
129 : }
130 :
131 : void PNGAPI
132 0 : png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
133 : png_uint_32 length)
134 : {
135 0 : png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
136 0 : }
137 :
138 : /* Write the data of a PNG chunk started with png_write_chunk_header().
139 : * Note that multiple calls to this function are allowed, and that the
140 : * sum of the lengths from these calls *must* add up to the total_length
141 : * given to png_write_chunk_header().
142 : */
143 : void PNGAPI
144 128 : png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
145 : png_size_t length)
146 : {
147 : /* Write the data, and run the CRC over it */
148 128 : if (png_ptr == NULL)
149 0 : return;
150 :
151 128 : if (data != NULL && length > 0)
152 : {
153 102 : png_write_data(png_ptr, data, length);
154 :
155 : /* Update the CRC after writing the data,
156 : * in case that the user I/O routine alters it.
157 : */
158 102 : png_calculate_crc(png_ptr, data, length);
159 : }
160 : }
161 :
162 : /* Finish a chunk started with png_write_chunk_header(). */
163 : void PNGAPI
164 115 : png_write_chunk_end(png_structp png_ptr)
165 : {
166 : png_byte buf[4];
167 :
168 115 : if (png_ptr == NULL) return;
169 :
170 : #ifdef PNG_IO_STATE_SUPPORTED
171 : /* Inform the I/O callback that the chunk CRC is being written.
172 : * PNG_IO_CHUNK_CRC requires a single I/O function call.
173 : */
174 : png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
175 : #endif
176 :
177 : /* Write the crc in a single operation */
178 115 : png_save_uint_32(buf, png_ptr->crc);
179 :
180 115 : png_write_data(png_ptr, buf, (png_size_t)4);
181 : }
182 :
183 : /* Write a PNG chunk all at once. The type is an array of ASCII characters
184 : * representing the chunk name. The array must be at least 4 bytes in
185 : * length, and does not need to be null terminated. To be safe, pass the
186 : * pre-defined chunk names here, and if you need a new one, define it
187 : * where the others are defined. The length is the length of the data.
188 : * All the data must be present. If that is not possible, use the
189 : * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
190 : * functions instead.
191 : */
192 : static void
193 102 : png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
194 : png_const_bytep data, png_size_t length)
195 : {
196 102 : if (png_ptr == NULL)
197 0 : return;
198 :
199 : /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
200 : if (length > PNG_UINT_32_MAX)
201 : png_error(png_ptr, "length exceeds PNG maxima");
202 :
203 102 : png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
204 102 : png_write_chunk_data(png_ptr, data, length);
205 102 : png_write_chunk_end(png_ptr);
206 : }
207 :
208 : /* This is the API that calls the internal function above. */
209 : void PNGAPI
210 0 : png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string,
211 : png_const_bytep data, png_size_t length)
212 : {
213 0 : png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
214 : length);
215 0 : }
216 :
217 : /* Initialize the compressor for the appropriate type of compression. */
218 : static void
219 39 : png_zlib_claim(png_structp png_ptr, png_uint_32 state)
220 : {
221 39 : if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE))
222 : {
223 : /* If already initialized for 'state' do not re-init. */
224 39 : if (png_ptr->zlib_state != state)
225 : {
226 26 : int ret = Z_OK;
227 26 : png_const_charp who = "-";
228 :
229 : /* If actually initialized for another state do a deflateEnd. */
230 26 : if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
231 : {
232 0 : ret = deflateEnd(&png_ptr->zstream);
233 0 : who = "end";
234 0 : png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
235 : }
236 :
237 : /* zlib itself detects an incomplete state on deflateEnd */
238 26 : if (ret == Z_OK) switch (state)
239 : {
240 : # ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
241 : case PNG_ZLIB_FOR_TEXT:
242 : ret = deflateInit2(&png_ptr->zstream,
243 : png_ptr->zlib_text_level, png_ptr->zlib_text_method,
244 : png_ptr->zlib_text_window_bits,
245 : png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);
246 : who = "text";
247 : break;
248 : # endif
249 :
250 : case PNG_ZLIB_FOR_IDAT:
251 26 : ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
252 : png_ptr->zlib_method, png_ptr->zlib_window_bits,
253 : png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
254 26 : who = "IDAT";
255 26 : break;
256 :
257 : default:
258 0 : png_error(png_ptr, "invalid zlib state");
259 : }
260 :
261 26 : if (ret == Z_OK)
262 26 : png_ptr->zlib_state = state;
263 :
264 : else /* an error in deflateEnd or deflateInit2 */
265 : {
266 0 : size_t pos = 0;
267 : char msg[64];
268 :
269 0 : pos = png_safecat(msg, sizeof msg, pos,
270 : "zlib failed to initialize compressor (");
271 0 : pos = png_safecat(msg, sizeof msg, pos, who);
272 :
273 0 : switch (ret)
274 : {
275 : case Z_VERSION_ERROR:
276 0 : pos = png_safecat(msg, sizeof msg, pos, ") version error");
277 0 : break;
278 :
279 : case Z_STREAM_ERROR:
280 0 : pos = png_safecat(msg, sizeof msg, pos, ") stream error");
281 0 : break;
282 :
283 : case Z_MEM_ERROR:
284 0 : pos = png_safecat(msg, sizeof msg, pos, ") memory error");
285 0 : break;
286 :
287 : default:
288 0 : pos = png_safecat(msg, sizeof msg, pos, ") unknown error");
289 0 : break;
290 : }
291 :
292 0 : png_error(png_ptr, msg);
293 : }
294 : }
295 :
296 : /* Here on success, claim the zstream: */
297 39 : png_ptr->zlib_state |= PNG_ZLIB_IN_USE;
298 : }
299 :
300 : else
301 0 : png_error(png_ptr, "zstream already in use (internal error)");
302 39 : }
303 :
304 : /* The opposite: release the stream. It is also reset, this API will warn on
305 : * error but will not fail.
306 : */
307 : static void
308 39 : png_zlib_release(png_structp png_ptr)
309 : {
310 39 : if (png_ptr->zlib_state & PNG_ZLIB_IN_USE)
311 : {
312 39 : int ret = deflateReset(&png_ptr->zstream);
313 :
314 39 : png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE;
315 :
316 39 : if (ret != Z_OK)
317 : {
318 : png_const_charp err;
319 : PNG_WARNING_PARAMETERS(p)
320 :
321 0 : switch (ret)
322 : {
323 : case Z_VERSION_ERROR:
324 0 : err = "version";
325 0 : break;
326 :
327 : case Z_STREAM_ERROR:
328 0 : err = "stream";
329 0 : break;
330 :
331 : case Z_MEM_ERROR:
332 0 : err = "memory";
333 0 : break;
334 :
335 : default:
336 0 : err = "unknown";
337 0 : break;
338 : }
339 :
340 : png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret);
341 : png_warning_parameter(p, 2, err);
342 :
343 0 : if (png_ptr->zstream.msg)
344 0 : err = png_ptr->zstream.msg;
345 : else
346 0 : err = "[no zlib message]";
347 :
348 : png_warning_parameter(p, 3, err);
349 :
350 : png_formatted_warning(png_ptr, p,
351 : "zlib failed to reset compressor: @1(@2): @3");
352 : }
353 : }
354 :
355 : else
356 : png_warning(png_ptr, "zstream not in use (internal error)");
357 39 : }
358 :
359 : #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
360 : /* This pair of functions encapsulates the operation of (a) compressing a
361 : * text string, and (b) issuing it later as a series of chunk data writes.
362 : * The compression_state structure is shared context for these functions
363 : * set up by the caller in order to make the whole mess thread-safe.
364 : */
365 :
366 : typedef struct
367 : {
368 : png_const_bytep input; /* The uncompressed input data */
369 : png_size_t input_len; /* Its length */
370 : int num_output_ptr; /* Number of output pointers used */
371 : int max_output_ptr; /* Size of output_ptr */
372 : png_bytep *output_ptr; /* Array of pointers to output */
373 : } compression_state;
374 :
375 : /* Compress given text into storage in the png_ptr structure */
376 : static int /* PRIVATE */
377 : png_text_compress(png_structp png_ptr,
378 : png_const_charp text, png_size_t text_len, int compression,
379 : compression_state *comp)
380 : {
381 : int ret;
382 :
383 : comp->num_output_ptr = 0;
384 : comp->max_output_ptr = 0;
385 : comp->output_ptr = NULL;
386 : comp->input = NULL;
387 : comp->input_len = text_len;
388 :
389 : /* We may just want to pass the text right through */
390 : if (compression == PNG_TEXT_COMPRESSION_NONE)
391 : {
392 : comp->input = (png_const_bytep)text;
393 : return((int)text_len);
394 : }
395 :
396 : if (compression >= PNG_TEXT_COMPRESSION_LAST)
397 : {
398 : PNG_WARNING_PARAMETERS(p)
399 :
400 : png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
401 : compression);
402 : png_formatted_warning(png_ptr, p, "Unknown compression type @1");
403 : }
404 :
405 : /* We can't write the chunk until we find out how much data we have,
406 : * which means we need to run the compressor first and save the
407 : * output. This shouldn't be a problem, as the vast majority of
408 : * comments should be reasonable, but we will set up an array of
409 : * malloc'd pointers to be sure.
410 : *
411 : * If we knew the application was well behaved, we could simplify this
412 : * greatly by assuming we can always malloc an output buffer large
413 : * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
414 : * and malloc this directly. The only time this would be a bad idea is
415 : * if we can't malloc more than 64K and we have 64K of random input
416 : * data, or if the input string is incredibly large (although this
417 : * wouldn't cause a failure, just a slowdown due to swapping).
418 : */
419 : png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT);
420 :
421 : /* Set up the compression buffers */
422 : /* TODO: the following cast hides a potential overflow problem. */
423 : png_ptr->zstream.avail_in = (uInt)text_len;
424 :
425 : /* NOTE: assume zlib doesn't overwrite the input */
426 : png_ptr->zstream.next_in = (Bytef *)text;
427 : png_ptr->zstream.avail_out = png_ptr->zbuf_size;
428 : png_ptr->zstream.next_out = png_ptr->zbuf;
429 :
430 : /* This is the same compression loop as in png_write_row() */
431 : do
432 : {
433 : /* Compress the data */
434 : ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
435 :
436 : if (ret != Z_OK)
437 : {
438 : /* Error */
439 : if (png_ptr->zstream.msg != NULL)
440 : png_error(png_ptr, png_ptr->zstream.msg);
441 :
442 : else
443 : png_error(png_ptr, "zlib error");
444 : }
445 :
446 : /* Check to see if we need more room */
447 : if (!(png_ptr->zstream.avail_out))
448 : {
449 : /* Make sure the output array has room */
450 : if (comp->num_output_ptr >= comp->max_output_ptr)
451 : {
452 : int old_max;
453 :
454 : old_max = comp->max_output_ptr;
455 : comp->max_output_ptr = comp->num_output_ptr + 4;
456 : if (comp->output_ptr != NULL)
457 : {
458 : png_bytepp old_ptr;
459 :
460 : old_ptr = comp->output_ptr;
461 :
462 : comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
463 : (png_alloc_size_t)
464 : (comp->max_output_ptr * png_sizeof(png_charpp)));
465 :
466 : png_memcpy(comp->output_ptr, old_ptr, old_max
467 : * png_sizeof(png_charp));
468 :
469 : png_free(png_ptr, old_ptr);
470 : }
471 : else
472 : comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
473 : (png_alloc_size_t)
474 : (comp->max_output_ptr * png_sizeof(png_charp)));
475 : }
476 :
477 : /* Save the data */
478 : comp->output_ptr[comp->num_output_ptr] =
479 : (png_bytep)png_malloc(png_ptr,
480 : (png_alloc_size_t)png_ptr->zbuf_size);
481 :
482 : png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
483 : png_ptr->zbuf_size);
484 :
485 : comp->num_output_ptr++;
486 :
487 : /* and reset the buffer */
488 : png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
489 : png_ptr->zstream.next_out = png_ptr->zbuf;
490 : }
491 : /* Continue until we don't have any more to compress */
492 : } while (png_ptr->zstream.avail_in);
493 :
494 : /* Finish the compression */
495 : do
496 : {
497 : /* Tell zlib we are finished */
498 : ret = deflate(&png_ptr->zstream, Z_FINISH);
499 :
500 : if (ret == Z_OK)
501 : {
502 : /* Check to see if we need more room */
503 : if (!(png_ptr->zstream.avail_out))
504 : {
505 : /* Check to make sure our output array has room */
506 : if (comp->num_output_ptr >= comp->max_output_ptr)
507 : {
508 : int old_max;
509 :
510 : old_max = comp->max_output_ptr;
511 : comp->max_output_ptr = comp->num_output_ptr + 4;
512 : if (comp->output_ptr != NULL)
513 : {
514 : png_bytepp old_ptr;
515 :
516 : old_ptr = comp->output_ptr;
517 :
518 : /* This could be optimized to realloc() */
519 : comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
520 : (png_alloc_size_t)(comp->max_output_ptr *
521 : png_sizeof(png_charp)));
522 :
523 : png_memcpy(comp->output_ptr, old_ptr,
524 : old_max * png_sizeof(png_charp));
525 :
526 : png_free(png_ptr, old_ptr);
527 : }
528 :
529 : else
530 : comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
531 : (png_alloc_size_t)(comp->max_output_ptr *
532 : png_sizeof(png_charp)));
533 : }
534 :
535 : /* Save the data */
536 : comp->output_ptr[comp->num_output_ptr] =
537 : (png_bytep)png_malloc(png_ptr,
538 : (png_alloc_size_t)png_ptr->zbuf_size);
539 :
540 : png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
541 : png_ptr->zbuf_size);
542 :
543 : comp->num_output_ptr++;
544 :
545 : /* and reset the buffer pointers */
546 : png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
547 : png_ptr->zstream.next_out = png_ptr->zbuf;
548 : }
549 : }
550 : else if (ret != Z_STREAM_END)
551 : {
552 : /* We got an error */
553 : if (png_ptr->zstream.msg != NULL)
554 : png_error(png_ptr, png_ptr->zstream.msg);
555 :
556 : else
557 : png_error(png_ptr, "zlib error");
558 : }
559 : } while (ret != Z_STREAM_END);
560 :
561 : /* Text length is number of buffers plus last buffer */
562 : text_len = png_ptr->zbuf_size * comp->num_output_ptr;
563 :
564 : if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
565 : text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
566 :
567 : return((int)text_len);
568 : }
569 :
570 : /* Ship the compressed text out via chunk writes */
571 : static void /* PRIVATE */
572 : png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
573 : {
574 : int i;
575 :
576 : /* Handle the no-compression case */
577 : if (comp->input)
578 : {
579 : png_write_chunk_data(png_ptr, comp->input, comp->input_len);
580 :
581 : return;
582 : }
583 :
584 : #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
585 : /* The zbuf_size test is because the code below doesn't work if zbuf_size is
586 : * '1'; simply skip it to avoid memory overwrite.
587 : */
588 : if (comp->input_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
589 : {
590 : unsigned int z_cmf; /* zlib compression method and flags */
591 :
592 : /* Optimize the CMF field in the zlib stream. This hack of the zlib
593 : * stream is compliant to the stream specification.
594 : */
595 :
596 : if (comp->num_output_ptr)
597 : z_cmf = comp->output_ptr[0][0];
598 : else
599 : z_cmf = png_ptr->zbuf[0];
600 :
601 : if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
602 : {
603 : unsigned int z_cinfo;
604 : unsigned int half_z_window_size;
605 : png_size_t uncompressed_text_size = comp->input_len;
606 :
607 : z_cinfo = z_cmf >> 4;
608 : half_z_window_size = 1 << (z_cinfo + 7);
609 :
610 : while (uncompressed_text_size <= half_z_window_size &&
611 : half_z_window_size >= 256)
612 : {
613 : z_cinfo--;
614 : half_z_window_size >>= 1;
615 : }
616 :
617 : z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
618 :
619 : if (comp->num_output_ptr)
620 : {
621 :
622 : if (comp->output_ptr[0][0] != z_cmf)
623 : {
624 : int tmp;
625 :
626 : comp->output_ptr[0][0] = (png_byte)z_cmf;
627 : tmp = comp->output_ptr[0][1] & 0xe0;
628 : tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
629 : comp->output_ptr[0][1] = (png_byte)tmp;
630 : }
631 : }
632 : else
633 : {
634 : int tmp;
635 :
636 : png_ptr->zbuf[0] = (png_byte)z_cmf;
637 : tmp = png_ptr->zbuf[1] & 0xe0;
638 : tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
639 : png_ptr->zbuf[1] = (png_byte)tmp;
640 : }
641 : }
642 :
643 : else
644 : png_error(png_ptr,
645 : "Invalid zlib compression method or flags in non-IDAT chunk");
646 : }
647 : #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
648 :
649 : /* Write saved output buffers, if any */
650 : for (i = 0; i < comp->num_output_ptr; i++)
651 : {
652 : png_write_chunk_data(png_ptr, comp->output_ptr[i],
653 : (png_size_t)png_ptr->zbuf_size);
654 :
655 : png_free(png_ptr, comp->output_ptr[i]);
656 : }
657 :
658 : if (comp->max_output_ptr != 0)
659 : png_free(png_ptr, comp->output_ptr);
660 :
661 : /* Write anything left in zbuf */
662 : if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
663 : png_write_chunk_data(png_ptr, png_ptr->zbuf,
664 : (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
665 :
666 : /* Reset zlib for another zTXt/iTXt or image data */
667 : png_zlib_release(png_ptr);
668 : }
669 : #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
670 :
671 : /* Write the IHDR chunk, and update the png_struct with the necessary
672 : * information. Note that the rest of this code depends upon this
673 : * information being correct.
674 : */
675 : void /* PRIVATE */
676 26 : png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
677 : int bit_depth, int color_type, int compression_type, int filter_type,
678 : int interlace_type)
679 : {
680 : png_byte buf[13]; /* Buffer to store the IHDR info */
681 :
682 : png_debug(1, "in png_write_IHDR");
683 :
684 : /* Check that we have valid input data from the application info */
685 26 : switch (color_type)
686 : {
687 : case PNG_COLOR_TYPE_GRAY:
688 0 : switch (bit_depth)
689 : {
690 : case 1:
691 : case 2:
692 : case 4:
693 : case 8:
694 : #ifdef PNG_WRITE_16BIT_SUPPORTED
695 : case 16:
696 : #endif
697 0 : png_ptr->channels = 1; break;
698 :
699 : default:
700 0 : png_error(png_ptr,
701 : "Invalid bit depth for grayscale image");
702 : }
703 0 : break;
704 :
705 : case PNG_COLOR_TYPE_RGB:
706 : #ifdef PNG_WRITE_16BIT_SUPPORTED
707 7 : if (bit_depth != 8 && bit_depth != 16)
708 : #else
709 : if (bit_depth != 8)
710 : #endif
711 0 : png_error(png_ptr, "Invalid bit depth for RGB image");
712 :
713 7 : png_ptr->channels = 3;
714 7 : break;
715 :
716 : case PNG_COLOR_TYPE_PALETTE:
717 0 : switch (bit_depth)
718 : {
719 : case 1:
720 : case 2:
721 : case 4:
722 : case 8:
723 0 : png_ptr->channels = 1;
724 : break;
725 :
726 : default:
727 0 : png_error(png_ptr, "Invalid bit depth for paletted image");
728 : }
729 0 : break;
730 :
731 : case PNG_COLOR_TYPE_GRAY_ALPHA:
732 0 : if (bit_depth != 8 && bit_depth != 16)
733 0 : png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
734 :
735 0 : png_ptr->channels = 2;
736 0 : break;
737 :
738 : case PNG_COLOR_TYPE_RGB_ALPHA:
739 : #ifdef PNG_WRITE_16BIT_SUPPORTED
740 19 : if (bit_depth != 8 && bit_depth != 16)
741 : #else
742 : if (bit_depth != 8)
743 : #endif
744 0 : png_error(png_ptr, "Invalid bit depth for RGBA image");
745 :
746 19 : png_ptr->channels = 4;
747 19 : break;
748 :
749 : default:
750 0 : png_error(png_ptr, "Invalid image color type specified");
751 : }
752 :
753 26 : if (compression_type != PNG_COMPRESSION_TYPE_BASE)
754 : {
755 : png_warning(png_ptr, "Invalid compression type specified");
756 0 : compression_type = PNG_COMPRESSION_TYPE_BASE;
757 : }
758 :
759 : /* Write filter_method 64 (intrapixel differencing) only if
760 : * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
761 : * 2. Libpng did not write a PNG signature (this filter_method is only
762 : * used in PNG datastreams that are embedded in MNG datastreams) and
763 : * 3. The application called png_permit_mng_features with a mask that
764 : * included PNG_FLAG_MNG_FILTER_64 and
765 : * 4. The filter_method is 64 and
766 : * 5. The color_type is RGB or RGBA
767 : */
768 26 : if (
769 : #ifdef PNG_MNG_FEATURES_SUPPORTED
770 : !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
771 : ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
772 : (color_type == PNG_COLOR_TYPE_RGB ||
773 : color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
774 : (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
775 : #endif
776 : filter_type != PNG_FILTER_TYPE_BASE)
777 : {
778 : png_warning(png_ptr, "Invalid filter type specified");
779 0 : filter_type = PNG_FILTER_TYPE_BASE;
780 : }
781 :
782 : #ifdef PNG_WRITE_INTERLACING_SUPPORTED
783 : if (interlace_type != PNG_INTERLACE_NONE &&
784 : interlace_type != PNG_INTERLACE_ADAM7)
785 : {
786 : png_warning(png_ptr, "Invalid interlace type specified");
787 : interlace_type = PNG_INTERLACE_ADAM7;
788 : }
789 : #else
790 26 : interlace_type=PNG_INTERLACE_NONE;
791 : #endif
792 :
793 : /* Save the relevent information */
794 26 : png_ptr->bit_depth = (png_byte)bit_depth;
795 26 : png_ptr->color_type = (png_byte)color_type;
796 26 : png_ptr->interlaced = (png_byte)interlace_type;
797 : #ifdef PNG_MNG_FEATURES_SUPPORTED
798 : png_ptr->filter_type = (png_byte)filter_type;
799 : #endif
800 26 : png_ptr->compression_type = (png_byte)compression_type;
801 26 : png_ptr->width = width;
802 26 : png_ptr->height = height;
803 :
804 26 : png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
805 26 : png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
806 : /* Set the usr info, so any transformations can modify it */
807 26 : png_ptr->usr_width = png_ptr->width;
808 26 : png_ptr->usr_bit_depth = png_ptr->bit_depth;
809 26 : png_ptr->usr_channels = png_ptr->channels;
810 :
811 : /* Pack the header information into the buffer */
812 26 : png_save_uint_32(buf, width);
813 26 : png_save_uint_32(buf + 4, height);
814 26 : buf[8] = (png_byte)bit_depth;
815 26 : buf[9] = (png_byte)color_type;
816 26 : buf[10] = (png_byte)compression_type;
817 26 : buf[11] = (png_byte)filter_type;
818 26 : buf[12] = (png_byte)interlace_type;
819 :
820 : /* Write the chunk */
821 26 : png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
822 :
823 : #ifdef PNG_WRITE_APNG_SUPPORTED
824 26 : png_ptr->first_frame_width = width;
825 26 : png_ptr->first_frame_height = height;
826 : #endif
827 :
828 : /* Initialize zlib with PNG info */
829 26 : png_ptr->zstream.zalloc = png_zalloc;
830 26 : png_ptr->zstream.zfree = png_zfree;
831 26 : png_ptr->zstream.opaque = (voidpf)png_ptr;
832 :
833 26 : if (!(png_ptr->do_filter))
834 : {
835 52 : if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
836 26 : png_ptr->bit_depth < 8)
837 0 : png_ptr->do_filter = PNG_FILTER_NONE;
838 :
839 : else
840 26 : png_ptr->do_filter = PNG_ALL_FILTERS;
841 : }
842 :
843 26 : if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
844 : {
845 26 : if (png_ptr->do_filter != PNG_FILTER_NONE)
846 26 : png_ptr->zlib_strategy = Z_FILTERED;
847 :
848 : else
849 0 : png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
850 : }
851 :
852 26 : if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
853 26 : png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
854 :
855 26 : if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
856 26 : png_ptr->zlib_mem_level = 8;
857 :
858 26 : if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
859 26 : png_ptr->zlib_window_bits = 15;
860 :
861 26 : if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
862 26 : png_ptr->zlib_method = 8;
863 :
864 : #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
865 : #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
866 : if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
867 : png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
868 :
869 : if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
870 : png_ptr->zlib_text_level = png_ptr->zlib_level;
871 :
872 : if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
873 : png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
874 :
875 : if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
876 : png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
877 :
878 : if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
879 : png_ptr->zlib_text_method = png_ptr->zlib_method;
880 : #else
881 : png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
882 : png_ptr->zlib_text_level = png_ptr->zlib_level;
883 : png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
884 : png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
885 : png_ptr->zlib_text_method = png_ptr->zlib_method;
886 : #endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
887 : #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
888 :
889 : /* Record that the compressor has not yet been initialized. */
890 26 : png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
891 :
892 26 : png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
893 26 : }
894 :
895 : /* Write the palette. We are careful not to trust png_color to be in the
896 : * correct order for PNG, so people can redefine it to any convenient
897 : * structure.
898 : */
899 : void /* PRIVATE */
900 0 : png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
901 : png_uint_32 num_pal)
902 : {
903 : png_uint_32 i;
904 : png_const_colorp pal_ptr;
905 : png_byte buf[3];
906 :
907 : png_debug(1, "in png_write_PLTE");
908 :
909 0 : if ((
910 : #ifdef PNG_MNG_FEATURES_SUPPORTED
911 : !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
912 : #endif
913 0 : num_pal == 0) || num_pal > 256)
914 : {
915 0 : if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
916 : {
917 0 : png_error(png_ptr, "Invalid number of colors in palette");
918 : }
919 :
920 : else
921 : {
922 : png_warning(png_ptr, "Invalid number of colors in palette");
923 0 : return;
924 : }
925 : }
926 :
927 0 : if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
928 : {
929 : png_warning(png_ptr,
930 : "Ignoring request to write a PLTE chunk in grayscale PNG");
931 :
932 0 : return;
933 : }
934 :
935 0 : png_ptr->num_palette = (png_uint_16)num_pal;
936 : png_debug1(3, "num_palette = %d", png_ptr->num_palette);
937 :
938 0 : png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
939 : #ifdef PNG_POINTER_INDEXING_SUPPORTED
940 :
941 0 : for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
942 : {
943 0 : buf[0] = pal_ptr->red;
944 0 : buf[1] = pal_ptr->green;
945 0 : buf[2] = pal_ptr->blue;
946 0 : png_write_chunk_data(png_ptr, buf, (png_size_t)3);
947 : }
948 :
949 : #else
950 : /* This is a little slower but some buggy compilers need to do this
951 : * instead
952 : */
953 : pal_ptr=palette;
954 :
955 : for (i = 0; i < num_pal; i++)
956 : {
957 : buf[0] = pal_ptr[i].red;
958 : buf[1] = pal_ptr[i].green;
959 : buf[2] = pal_ptr[i].blue;
960 : png_write_chunk_data(png_ptr, buf, (png_size_t)3);
961 : }
962 :
963 : #endif
964 0 : png_write_chunk_end(png_ptr);
965 0 : png_ptr->mode |= PNG_HAVE_PLTE;
966 : }
967 :
968 : /* Write an IDAT chunk */
969 : void /* PRIVATE */
970 39 : png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
971 : {
972 : png_debug(1, "in png_write_IDAT");
973 :
974 : #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
975 78 : if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
976 39 : png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
977 : {
978 : /* Optimize the CMF field in the zlib stream. This hack of the zlib
979 : * stream is compliant to the stream specification.
980 : */
981 39 : unsigned int z_cmf = data[0]; /* zlib compression method and flags */
982 :
983 39 : if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
984 : {
985 : /* Avoid memory underflows and multiplication overflows.
986 : *
987 : * The conditions below are practically always satisfied;
988 : * however, they still must be checked.
989 : */
990 117 : if (length >= 2 &&
991 78 : png_ptr->height < 16384 && png_ptr->width < 16384)
992 : {
993 : /* Compute the maximum possible length of the datastream */
994 :
995 : /* Number of pixels, plus for each row a filter byte
996 : * and possibly a padding byte, so increase the maximum
997 : * size to account for these.
998 : */
999 : unsigned int z_cinfo;
1000 : unsigned int half_z_window_size;
1001 78 : png_uint_32 uncompressed_idat_size = png_ptr->height *
1002 78 : ((png_ptr->width *
1003 78 : png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
1004 :
1005 : /* If it's interlaced, each block of 8 rows is sent as up to
1006 : * 14 rows, i.e., 6 additional rows, each with a filter byte
1007 : * and possibly a padding byte
1008 : */
1009 39 : if (png_ptr->interlaced)
1010 0 : uncompressed_idat_size += ((png_ptr->height + 7)/8) *
1011 0 : (png_ptr->bit_depth < 8 ? 12 : 6);
1012 :
1013 39 : z_cinfo = z_cmf >> 4;
1014 39 : half_z_window_size = 1 << (z_cinfo + 7);
1015 :
1016 311 : while (uncompressed_idat_size <= half_z_window_size &&
1017 : half_z_window_size >= 256)
1018 : {
1019 233 : z_cinfo--;
1020 233 : half_z_window_size >>= 1;
1021 : }
1022 :
1023 39 : z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
1024 :
1025 39 : if (data[0] != z_cmf)
1026 : {
1027 : int tmp;
1028 39 : data[0] = (png_byte)z_cmf;
1029 39 : tmp = data[1] & 0xe0;
1030 39 : tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
1031 39 : data[1] = (png_byte)tmp;
1032 : }
1033 : }
1034 : }
1035 :
1036 : else
1037 0 : png_error(png_ptr,
1038 : "Invalid zlib compression method or flags in IDAT");
1039 : }
1040 : #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
1041 :
1042 : #ifdef PNG_WRITE_APNG_SUPPORTED
1043 39 : if (png_ptr->num_frames_written == 0)
1044 : #endif
1045 26 : png_write_complete_chunk(png_ptr, png_IDAT, data, length);
1046 : #ifdef PNG_WRITE_APNG_SUPPORTED
1047 : else
1048 : {
1049 : png_byte buf[4];
1050 :
1051 13 : png_write_chunk_header(png_ptr, png_fdAT, 4 + length);
1052 :
1053 13 : png_save_uint_32(buf, png_ptr->next_seq_num);
1054 13 : png_write_chunk_data(png_ptr, buf, 4);
1055 :
1056 13 : png_write_chunk_data(png_ptr, data, length);
1057 :
1058 13 : png_write_chunk_end(png_ptr);
1059 :
1060 13 : png_ptr->next_seq_num++;
1061 : }
1062 : #endif /* PNG_WRITE_APNG_SUPPORTED */
1063 :
1064 39 : png_ptr->mode |= PNG_HAVE_IDAT;
1065 :
1066 : /* Prior to 1.5.4 this code was replicated in every caller (except at the
1067 : * end, where it isn't technically necessary). Since this function has
1068 : * flushed the data we can safely reset the zlib output buffer here.
1069 : */
1070 39 : png_ptr->zstream.next_out = png_ptr->zbuf;
1071 39 : png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1072 39 : }
1073 :
1074 : /* Write an IEND chunk */
1075 : void /* PRIVATE */
1076 26 : png_write_IEND(png_structp png_ptr)
1077 : {
1078 : png_debug(1, "in png_write_IEND");
1079 :
1080 26 : png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
1081 26 : png_ptr->mode |= PNG_HAVE_IEND;
1082 26 : }
1083 :
1084 : #ifdef PNG_WRITE_gAMA_SUPPORTED
1085 : /* Write a gAMA chunk */
1086 : void /* PRIVATE */
1087 : png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
1088 : {
1089 : png_byte buf[4];
1090 :
1091 : png_debug(1, "in png_write_gAMA");
1092 :
1093 : /* file_gamma is saved in 1/100,000ths */
1094 : png_save_uint_32(buf, (png_uint_32)file_gamma);
1095 : png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
1096 : }
1097 : #endif
1098 :
1099 : #ifdef PNG_WRITE_sRGB_SUPPORTED
1100 : /* Write a sRGB chunk */
1101 : void /* PRIVATE */
1102 : png_write_sRGB(png_structp png_ptr, int srgb_intent)
1103 : {
1104 : png_byte buf[1];
1105 :
1106 : png_debug(1, "in png_write_sRGB");
1107 :
1108 : if (srgb_intent >= PNG_sRGB_INTENT_LAST)
1109 : png_warning(png_ptr,
1110 : "Invalid sRGB rendering intent specified");
1111 :
1112 : buf[0]=(png_byte)srgb_intent;
1113 : png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
1114 : }
1115 : #endif
1116 :
1117 : #ifdef PNG_WRITE_iCCP_SUPPORTED
1118 : /* Write an iCCP chunk */
1119 : void /* PRIVATE */
1120 : png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
1121 : png_const_charp profile, int profile_len)
1122 : {
1123 : png_size_t name_len;
1124 : png_charp new_name;
1125 : compression_state comp;
1126 : int embedded_profile_len = 0;
1127 :
1128 : png_debug(1, "in png_write_iCCP");
1129 :
1130 : comp.num_output_ptr = 0;
1131 : comp.max_output_ptr = 0;
1132 : comp.output_ptr = NULL;
1133 : comp.input = NULL;
1134 : comp.input_len = 0;
1135 :
1136 : if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
1137 : return;
1138 :
1139 : if (compression_type != PNG_COMPRESSION_TYPE_BASE)
1140 : png_warning(png_ptr, "Unknown compression type in iCCP chunk");
1141 :
1142 : if (profile == NULL)
1143 : profile_len = 0;
1144 :
1145 : if (profile_len > 3)
1146 : embedded_profile_len =
1147 : ((*( (png_const_bytep)profile ))<<24) |
1148 : ((*( (png_const_bytep)profile + 1))<<16) |
1149 : ((*( (png_const_bytep)profile + 2))<< 8) |
1150 : ((*( (png_const_bytep)profile + 3)) );
1151 :
1152 : if (embedded_profile_len < 0)
1153 : {
1154 : png_warning(png_ptr,
1155 : "Embedded profile length in iCCP chunk is negative");
1156 :
1157 : png_free(png_ptr, new_name);
1158 : return;
1159 : }
1160 :
1161 : if (profile_len < embedded_profile_len)
1162 : {
1163 : png_warning(png_ptr,
1164 : "Embedded profile length too large in iCCP chunk");
1165 :
1166 : png_free(png_ptr, new_name);
1167 : return;
1168 : }
1169 :
1170 : if (profile_len > embedded_profile_len)
1171 : {
1172 : png_warning(png_ptr,
1173 : "Truncating profile to actual length in iCCP chunk");
1174 :
1175 : profile_len = embedded_profile_len;
1176 : }
1177 :
1178 : if (profile_len)
1179 : profile_len = png_text_compress(png_ptr, profile,
1180 : (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
1181 :
1182 : /* Make sure we include the NULL after the name and the compression type */
1183 : png_write_chunk_header(png_ptr, png_iCCP,
1184 : (png_uint_32)(name_len + profile_len + 2));
1185 :
1186 : new_name[name_len + 1] = 0x00;
1187 :
1188 : png_write_chunk_data(png_ptr, (png_bytep)new_name,
1189 : (png_size_t)(name_len + 2));
1190 :
1191 : if (profile_len)
1192 : {
1193 : comp.input_len = profile_len;
1194 : png_write_compressed_data_out(png_ptr, &comp);
1195 : }
1196 :
1197 : png_write_chunk_end(png_ptr);
1198 : png_free(png_ptr, new_name);
1199 : }
1200 : #endif
1201 :
1202 : #ifdef PNG_WRITE_sPLT_SUPPORTED
1203 : /* Write a sPLT chunk */
1204 : void /* PRIVATE */
1205 : png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
1206 : {
1207 : png_size_t name_len;
1208 : png_charp new_name;
1209 : png_byte entrybuf[10];
1210 : png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
1211 : png_size_t palette_size = entry_size * spalette->nentries;
1212 : png_sPLT_entryp ep;
1213 : #ifndef PNG_POINTER_INDEXING_SUPPORTED
1214 : int i;
1215 : #endif
1216 :
1217 : png_debug(1, "in png_write_sPLT");
1218 :
1219 : if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
1220 : return;
1221 :
1222 : /* Make sure we include the NULL after the name */
1223 : png_write_chunk_header(png_ptr, png_sPLT,
1224 : (png_uint_32)(name_len + 2 + palette_size));
1225 :
1226 : png_write_chunk_data(png_ptr, (png_bytep)new_name,
1227 : (png_size_t)(name_len + 1));
1228 :
1229 : png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
1230 :
1231 : /* Loop through each palette entry, writing appropriately */
1232 : #ifdef PNG_POINTER_INDEXING_SUPPORTED
1233 : for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
1234 : {
1235 : if (spalette->depth == 8)
1236 : {
1237 : entrybuf[0] = (png_byte)ep->red;
1238 : entrybuf[1] = (png_byte)ep->green;
1239 : entrybuf[2] = (png_byte)ep->blue;
1240 : entrybuf[3] = (png_byte)ep->alpha;
1241 : png_save_uint_16(entrybuf + 4, ep->frequency);
1242 : }
1243 :
1244 : else
1245 : {
1246 : png_save_uint_16(entrybuf + 0, ep->red);
1247 : png_save_uint_16(entrybuf + 2, ep->green);
1248 : png_save_uint_16(entrybuf + 4, ep->blue);
1249 : png_save_uint_16(entrybuf + 6, ep->alpha);
1250 : png_save_uint_16(entrybuf + 8, ep->frequency);
1251 : }
1252 :
1253 : png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
1254 : }
1255 : #else
1256 : ep=spalette->entries;
1257 : for (i = 0; i>spalette->nentries; i++)
1258 : {
1259 : if (spalette->depth == 8)
1260 : {
1261 : entrybuf[0] = (png_byte)ep[i].red;
1262 : entrybuf[1] = (png_byte)ep[i].green;
1263 : entrybuf[2] = (png_byte)ep[i].blue;
1264 : entrybuf[3] = (png_byte)ep[i].alpha;
1265 : png_save_uint_16(entrybuf + 4, ep[i].frequency);
1266 : }
1267 :
1268 : else
1269 : {
1270 : png_save_uint_16(entrybuf + 0, ep[i].red);
1271 : png_save_uint_16(entrybuf + 2, ep[i].green);
1272 : png_save_uint_16(entrybuf + 4, ep[i].blue);
1273 : png_save_uint_16(entrybuf + 6, ep[i].alpha);
1274 : png_save_uint_16(entrybuf + 8, ep[i].frequency);
1275 : }
1276 :
1277 : png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
1278 : }
1279 : #endif
1280 :
1281 : png_write_chunk_end(png_ptr);
1282 : png_free(png_ptr, new_name);
1283 : }
1284 : #endif
1285 :
1286 : #ifdef PNG_WRITE_sBIT_SUPPORTED
1287 : /* Write the sBIT chunk */
1288 : void /* PRIVATE */
1289 : png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
1290 : {
1291 : png_byte buf[4];
1292 : png_size_t size;
1293 :
1294 : png_debug(1, "in png_write_sBIT");
1295 :
1296 : /* Make sure we don't depend upon the order of PNG_COLOR_8 */
1297 : if (color_type & PNG_COLOR_MASK_COLOR)
1298 : {
1299 : png_byte maxbits;
1300 :
1301 : maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
1302 : png_ptr->usr_bit_depth);
1303 :
1304 : if (sbit->red == 0 || sbit->red > maxbits ||
1305 : sbit->green == 0 || sbit->green > maxbits ||
1306 : sbit->blue == 0 || sbit->blue > maxbits)
1307 : {
1308 : png_warning(png_ptr, "Invalid sBIT depth specified");
1309 : return;
1310 : }
1311 :
1312 : buf[0] = sbit->red;
1313 : buf[1] = sbit->green;
1314 : buf[2] = sbit->blue;
1315 : size = 3;
1316 : }
1317 :
1318 : else
1319 : {
1320 : if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
1321 : {
1322 : png_warning(png_ptr, "Invalid sBIT depth specified");
1323 : return;
1324 : }
1325 :
1326 : buf[0] = sbit->gray;
1327 : size = 1;
1328 : }
1329 :
1330 : if (color_type & PNG_COLOR_MASK_ALPHA)
1331 : {
1332 : if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
1333 : {
1334 : png_warning(png_ptr, "Invalid sBIT depth specified");
1335 : return;
1336 : }
1337 :
1338 : buf[size++] = sbit->alpha;
1339 : }
1340 :
1341 : png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
1342 : }
1343 : #endif
1344 :
1345 : #ifdef PNG_WRITE_cHRM_SUPPORTED
1346 : /* Write the cHRM chunk */
1347 : void /* PRIVATE */
1348 : png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
1349 : png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
1350 : png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
1351 : png_fixed_point blue_y)
1352 : {
1353 : png_byte buf[32];
1354 :
1355 : png_debug(1, "in png_write_cHRM");
1356 :
1357 : /* Each value is saved in 1/100,000ths */
1358 : #ifdef PNG_CHECK_cHRM_SUPPORTED
1359 : if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
1360 : green_x, green_y, blue_x, blue_y))
1361 : #endif
1362 : {
1363 : png_save_uint_32(buf, (png_uint_32)white_x);
1364 : png_save_uint_32(buf + 4, (png_uint_32)white_y);
1365 :
1366 : png_save_uint_32(buf + 8, (png_uint_32)red_x);
1367 : png_save_uint_32(buf + 12, (png_uint_32)red_y);
1368 :
1369 : png_save_uint_32(buf + 16, (png_uint_32)green_x);
1370 : png_save_uint_32(buf + 20, (png_uint_32)green_y);
1371 :
1372 : png_save_uint_32(buf + 24, (png_uint_32)blue_x);
1373 : png_save_uint_32(buf + 28, (png_uint_32)blue_y);
1374 :
1375 : png_write_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
1376 : }
1377 : }
1378 : #endif
1379 :
1380 : #ifdef PNG_WRITE_tRNS_SUPPORTED
1381 : /* Write the tRNS chunk */
1382 : void /* PRIVATE */
1383 0 : png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
1384 : png_const_color_16p tran, int num_trans, int color_type)
1385 : {
1386 : png_byte buf[6];
1387 :
1388 : png_debug(1, "in png_write_tRNS");
1389 :
1390 0 : if (color_type == PNG_COLOR_TYPE_PALETTE)
1391 : {
1392 0 : if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
1393 : {
1394 : png_warning(png_ptr, "Invalid number of transparent colors specified");
1395 0 : return;
1396 : }
1397 :
1398 : /* Write the chunk out as it is */
1399 0 : png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
1400 : }
1401 :
1402 0 : else if (color_type == PNG_COLOR_TYPE_GRAY)
1403 : {
1404 : /* One 16 bit value */
1405 0 : if (tran->gray >= (1 << png_ptr->bit_depth))
1406 : {
1407 : png_warning(png_ptr,
1408 : "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
1409 :
1410 0 : return;
1411 : }
1412 :
1413 0 : png_save_uint_16(buf, tran->gray);
1414 0 : png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
1415 : }
1416 :
1417 0 : else if (color_type == PNG_COLOR_TYPE_RGB)
1418 : {
1419 : /* Three 16 bit values */
1420 0 : png_save_uint_16(buf, tran->red);
1421 0 : png_save_uint_16(buf + 2, tran->green);
1422 0 : png_save_uint_16(buf + 4, tran->blue);
1423 : #ifdef PNG_WRITE_16BIT_SUPPORTED
1424 0 : if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1425 : #else
1426 : if (buf[0] | buf[2] | buf[4])
1427 : #endif
1428 : {
1429 : png_warning(png_ptr,
1430 : "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
1431 0 : return;
1432 : }
1433 :
1434 0 : png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
1435 : }
1436 :
1437 : else
1438 : {
1439 : png_warning(png_ptr, "Can't write tRNS with an alpha channel");
1440 : }
1441 : }
1442 : #endif
1443 :
1444 : #ifdef PNG_WRITE_bKGD_SUPPORTED
1445 : /* Write the background chunk */
1446 : void /* PRIVATE */
1447 : png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
1448 : {
1449 : png_byte buf[6];
1450 :
1451 : png_debug(1, "in png_write_bKGD");
1452 :
1453 : if (color_type == PNG_COLOR_TYPE_PALETTE)
1454 : {
1455 : if (
1456 : #ifdef PNG_MNG_FEATURES_SUPPORTED
1457 : (png_ptr->num_palette ||
1458 : (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
1459 : #endif
1460 : back->index >= png_ptr->num_palette)
1461 : {
1462 : png_warning(png_ptr, "Invalid background palette index");
1463 : return;
1464 : }
1465 :
1466 : buf[0] = back->index;
1467 : png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
1468 : }
1469 :
1470 : else if (color_type & PNG_COLOR_MASK_COLOR)
1471 : {
1472 : png_save_uint_16(buf, back->red);
1473 : png_save_uint_16(buf + 2, back->green);
1474 : png_save_uint_16(buf + 4, back->blue);
1475 : #ifdef PNG_WRITE_16BIT_SUPPORTED
1476 : if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
1477 : #else
1478 : if (buf[0] | buf[2] | buf[4])
1479 : #endif
1480 : {
1481 : png_warning(png_ptr,
1482 : "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
1483 :
1484 : return;
1485 : }
1486 :
1487 : png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
1488 : }
1489 :
1490 : else
1491 : {
1492 : if (back->gray >= (1 << png_ptr->bit_depth))
1493 : {
1494 : png_warning(png_ptr,
1495 : "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
1496 :
1497 : return;
1498 : }
1499 :
1500 : png_save_uint_16(buf, back->gray);
1501 : png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
1502 : }
1503 : }
1504 : #endif
1505 :
1506 : #ifdef PNG_WRITE_hIST_SUPPORTED
1507 : /* Write the histogram */
1508 : void /* PRIVATE */
1509 : png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
1510 : {
1511 : int i;
1512 : png_byte buf[3];
1513 :
1514 : png_debug(1, "in png_write_hIST");
1515 :
1516 : if (num_hist > (int)png_ptr->num_palette)
1517 : {
1518 : png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
1519 : png_ptr->num_palette);
1520 :
1521 : png_warning(png_ptr, "Invalid number of histogram entries specified");
1522 : return;
1523 : }
1524 :
1525 : png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
1526 :
1527 : for (i = 0; i < num_hist; i++)
1528 : {
1529 : png_save_uint_16(buf, hist[i]);
1530 : png_write_chunk_data(png_ptr, buf, (png_size_t)2);
1531 : }
1532 :
1533 : png_write_chunk_end(png_ptr);
1534 : }
1535 : #endif
1536 :
1537 : #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
1538 : defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
1539 : /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
1540 : * and if invalid, correct the keyword rather than discarding the entire
1541 : * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
1542 : * length, forbids leading or trailing whitespace, multiple internal spaces,
1543 : * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
1544 : *
1545 : * The new_key is allocated to hold the corrected keyword and must be freed
1546 : * by the calling routine. This avoids problems with trying to write to
1547 : * static keywords without having to have duplicate copies of the strings.
1548 : */
1549 : png_size_t /* PRIVATE */
1550 : png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
1551 : {
1552 : png_size_t key_len;
1553 : png_const_charp ikp;
1554 : png_charp kp, dp;
1555 : int kflag;
1556 : int kwarn=0;
1557 :
1558 : png_debug(1, "in png_check_keyword");
1559 :
1560 : *new_key = NULL;
1561 :
1562 : if (key == NULL || (key_len = png_strlen(key)) == 0)
1563 : {
1564 : png_warning(png_ptr, "zero length keyword");
1565 : return ((png_size_t)0);
1566 : }
1567 :
1568 : png_debug1(2, "Keyword to be checked is '%s'", key);
1569 :
1570 : *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
1571 :
1572 : if (*new_key == NULL)
1573 : {
1574 : png_warning(png_ptr, "Out of memory while procesing keyword");
1575 : return ((png_size_t)0);
1576 : }
1577 :
1578 : /* Replace non-printing characters with a blank and print a warning */
1579 : for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
1580 : {
1581 : if ((png_byte)*ikp < 0x20 ||
1582 : ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
1583 : {
1584 : PNG_WARNING_PARAMETERS(p)
1585 :
1586 : png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
1587 : (png_byte)*ikp);
1588 : png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
1589 : *dp = ' ';
1590 : }
1591 :
1592 : else
1593 : {
1594 : *dp = *ikp;
1595 : }
1596 : }
1597 : *dp = '\0';
1598 :
1599 : /* Remove any trailing white space. */
1600 : kp = *new_key + key_len - 1;
1601 : if (*kp == ' ')
1602 : {
1603 : png_warning(png_ptr, "trailing spaces removed from keyword");
1604 :
1605 : while (*kp == ' ')
1606 : {
1607 : *(kp--) = '\0';
1608 : key_len--;
1609 : }
1610 : }
1611 :
1612 : /* Remove any leading white space. */
1613 : kp = *new_key;
1614 : if (*kp == ' ')
1615 : {
1616 : png_warning(png_ptr, "leading spaces removed from keyword");
1617 :
1618 : while (*kp == ' ')
1619 : {
1620 : kp++;
1621 : key_len--;
1622 : }
1623 : }
1624 :
1625 : png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
1626 :
1627 : /* Remove multiple internal spaces. */
1628 : for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
1629 : {
1630 : if (*kp == ' ' && kflag == 0)
1631 : {
1632 : *(dp++) = *kp;
1633 : kflag = 1;
1634 : }
1635 :
1636 : else if (*kp == ' ')
1637 : {
1638 : key_len--;
1639 : kwarn = 1;
1640 : }
1641 :
1642 : else
1643 : {
1644 : *(dp++) = *kp;
1645 : kflag = 0;
1646 : }
1647 : }
1648 : *dp = '\0';
1649 : if (kwarn)
1650 : png_warning(png_ptr, "extra interior spaces removed from keyword");
1651 :
1652 : if (key_len == 0)
1653 : {
1654 : png_free(png_ptr, *new_key);
1655 : png_warning(png_ptr, "Zero length keyword");
1656 : }
1657 :
1658 : if (key_len > 79)
1659 : {
1660 : png_warning(png_ptr, "keyword length must be 1 - 79 characters");
1661 : (*new_key)[79] = '\0';
1662 : key_len = 79;
1663 : }
1664 :
1665 : return (key_len);
1666 : }
1667 : #endif
1668 :
1669 : #ifdef PNG_WRITE_tEXt_SUPPORTED
1670 : /* Write a tEXt chunk */
1671 : void /* PRIVATE */
1672 : png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
1673 : png_size_t text_len)
1674 : {
1675 : png_size_t key_len;
1676 : png_charp new_key;
1677 :
1678 : png_debug(1, "in png_write_tEXt");
1679 :
1680 : if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
1681 : return;
1682 :
1683 : if (text == NULL || *text == '\0')
1684 : text_len = 0;
1685 :
1686 : else
1687 : text_len = png_strlen(text);
1688 :
1689 : /* Make sure we include the 0 after the key */
1690 : png_write_chunk_header(png_ptr, png_tEXt,
1691 : (png_uint_32)(key_len + text_len + 1));
1692 : /*
1693 : * We leave it to the application to meet PNG-1.0 requirements on the
1694 : * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1695 : * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1696 : * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1697 : */
1698 : png_write_chunk_data(png_ptr, (png_bytep)new_key,
1699 : (png_size_t)(key_len + 1));
1700 :
1701 : if (text_len)
1702 : png_write_chunk_data(png_ptr, (png_const_bytep)text,
1703 : (png_size_t)text_len);
1704 :
1705 : png_write_chunk_end(png_ptr);
1706 : png_free(png_ptr, new_key);
1707 : }
1708 : #endif
1709 :
1710 : #ifdef PNG_WRITE_zTXt_SUPPORTED
1711 : /* Write a compressed text chunk */
1712 : void /* PRIVATE */
1713 : png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
1714 : png_size_t text_len, int compression)
1715 : {
1716 : png_size_t key_len;
1717 : png_byte buf;
1718 : png_charp new_key;
1719 : compression_state comp;
1720 :
1721 : png_debug(1, "in png_write_zTXt");
1722 :
1723 : comp.num_output_ptr = 0;
1724 : comp.max_output_ptr = 0;
1725 : comp.output_ptr = NULL;
1726 : comp.input = NULL;
1727 : comp.input_len = 0;
1728 :
1729 : if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
1730 : {
1731 : png_free(png_ptr, new_key);
1732 : return;
1733 : }
1734 :
1735 : if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
1736 : {
1737 : png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
1738 : png_free(png_ptr, new_key);
1739 : return;
1740 : }
1741 :
1742 : text_len = png_strlen(text);
1743 :
1744 : /* Compute the compressed data; do it now for the length */
1745 : text_len = png_text_compress(png_ptr, text, text_len, compression,
1746 : &comp);
1747 :
1748 : /* Write start of chunk */
1749 : png_write_chunk_header(png_ptr, png_zTXt,
1750 : (png_uint_32)(key_len+text_len + 2));
1751 :
1752 : /* Write key */
1753 : png_write_chunk_data(png_ptr, (png_bytep)new_key,
1754 : (png_size_t)(key_len + 1));
1755 :
1756 : png_free(png_ptr, new_key);
1757 :
1758 : buf = (png_byte)compression;
1759 :
1760 : /* Write compression */
1761 : png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
1762 :
1763 : /* Write the compressed data */
1764 : comp.input_len = text_len;
1765 : png_write_compressed_data_out(png_ptr, &comp);
1766 :
1767 : /* Close the chunk */
1768 : png_write_chunk_end(png_ptr);
1769 : }
1770 : #endif
1771 :
1772 : #ifdef PNG_WRITE_iTXt_SUPPORTED
1773 : /* Write an iTXt chunk */
1774 : void /* PRIVATE */
1775 : png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
1776 : png_const_charp lang, png_const_charp lang_key, png_const_charp text)
1777 : {
1778 : png_size_t lang_len, key_len, lang_key_len, text_len;
1779 : png_charp new_lang;
1780 : png_charp new_key = NULL;
1781 : png_byte cbuf[2];
1782 : compression_state comp;
1783 :
1784 : png_debug(1, "in png_write_iTXt");
1785 :
1786 : comp.num_output_ptr = 0;
1787 : comp.max_output_ptr = 0;
1788 : comp.output_ptr = NULL;
1789 : comp.input = NULL;
1790 :
1791 : if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
1792 : return;
1793 :
1794 : if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
1795 : {
1796 : png_warning(png_ptr, "Empty language field in iTXt chunk");
1797 : new_lang = NULL;
1798 : lang_len = 0;
1799 : }
1800 :
1801 : if (lang_key == NULL)
1802 : lang_key_len = 0;
1803 :
1804 : else
1805 : lang_key_len = png_strlen(lang_key);
1806 :
1807 : if (text == NULL)
1808 : text_len = 0;
1809 :
1810 : else
1811 : text_len = png_strlen(text);
1812 :
1813 : /* Compute the compressed data; do it now for the length */
1814 : text_len = png_text_compress(png_ptr, text, text_len, compression - 2,
1815 : &comp);
1816 :
1817 :
1818 : /* Make sure we include the compression flag, the compression byte,
1819 : * and the NULs after the key, lang, and lang_key parts
1820 : */
1821 :
1822 : png_write_chunk_header(png_ptr, png_iTXt, (png_uint_32)(
1823 : 5 /* comp byte, comp flag, terminators for key, lang and lang_key */
1824 : + key_len
1825 : + lang_len
1826 : + lang_key_len
1827 : + text_len));
1828 :
1829 : /* We leave it to the application to meet PNG-1.0 requirements on the
1830 : * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
1831 : * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
1832 : * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
1833 : */
1834 : png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
1835 :
1836 : /* Set the compression flag */
1837 : if (compression == PNG_ITXT_COMPRESSION_NONE ||
1838 : compression == PNG_TEXT_COMPRESSION_NONE)
1839 : cbuf[0] = 0;
1840 :
1841 : else /* compression == PNG_ITXT_COMPRESSION_zTXt */
1842 : cbuf[0] = 1;
1843 :
1844 : /* Set the compression method */
1845 : cbuf[1] = 0;
1846 :
1847 : png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
1848 :
1849 : cbuf[0] = 0;
1850 : png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
1851 : (png_size_t)(lang_len + 1));
1852 :
1853 : png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
1854 : (png_size_t)(lang_key_len + 1));
1855 :
1856 : png_write_compressed_data_out(png_ptr, &comp);
1857 :
1858 : png_write_chunk_end(png_ptr);
1859 :
1860 : png_free(png_ptr, new_key);
1861 : png_free(png_ptr, new_lang);
1862 : }
1863 : #endif
1864 :
1865 : #ifdef PNG_WRITE_oFFs_SUPPORTED
1866 : /* Write the oFFs chunk */
1867 : void /* PRIVATE */
1868 : png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
1869 : int unit_type)
1870 : {
1871 : png_byte buf[9];
1872 :
1873 : png_debug(1, "in png_write_oFFs");
1874 :
1875 : if (unit_type >= PNG_OFFSET_LAST)
1876 : png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
1877 :
1878 : png_save_int_32(buf, x_offset);
1879 : png_save_int_32(buf + 4, y_offset);
1880 : buf[8] = (png_byte)unit_type;
1881 :
1882 : png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
1883 : }
1884 : #endif
1885 : #ifdef PNG_WRITE_pCAL_SUPPORTED
1886 : /* Write the pCAL chunk (described in the PNG extensions document) */
1887 : void /* PRIVATE */
1888 : png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
1889 : png_int_32 X1, int type, int nparams, png_const_charp units,
1890 : png_charpp params)
1891 : {
1892 : png_size_t purpose_len, units_len, total_len;
1893 : png_size_tp params_len;
1894 : png_byte buf[10];
1895 : png_charp new_purpose;
1896 : int i;
1897 :
1898 : png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
1899 :
1900 : if (type >= PNG_EQUATION_LAST)
1901 : png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1902 :
1903 : purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
1904 : png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
1905 : units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
1906 : png_debug1(3, "pCAL units length = %d", (int)units_len);
1907 : total_len = purpose_len + units_len + 10;
1908 :
1909 : params_len = (png_size_tp)png_malloc(png_ptr,
1910 : (png_alloc_size_t)(nparams * png_sizeof(png_size_t)));
1911 :
1912 : /* Find the length of each parameter, making sure we don't count the
1913 : * null terminator for the last parameter.
1914 : */
1915 : for (i = 0; i < nparams; i++)
1916 : {
1917 : params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
1918 : png_debug2(3, "pCAL parameter %d length = %lu", i,
1919 : (unsigned long)params_len[i]);
1920 : total_len += params_len[i];
1921 : }
1922 :
1923 : png_debug1(3, "pCAL total length = %d", (int)total_len);
1924 : png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
1925 : png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len);
1926 : png_save_int_32(buf, X0);
1927 : png_save_int_32(buf + 4, X1);
1928 : buf[8] = (png_byte)type;
1929 : buf[9] = (png_byte)nparams;
1930 : png_write_chunk_data(png_ptr, buf, (png_size_t)10);
1931 : png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
1932 :
1933 : png_free(png_ptr, new_purpose);
1934 :
1935 : for (i = 0; i < nparams; i++)
1936 : {
1937 : png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
1938 : }
1939 :
1940 : png_free(png_ptr, params_len);
1941 : png_write_chunk_end(png_ptr);
1942 : }
1943 : #endif
1944 :
1945 : #ifdef PNG_WRITE_sCAL_SUPPORTED
1946 : /* Write the sCAL chunk */
1947 : void /* PRIVATE */
1948 : png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
1949 : png_const_charp height)
1950 : {
1951 : png_byte buf[64];
1952 : png_size_t wlen, hlen, total_len;
1953 :
1954 : png_debug(1, "in png_write_sCAL_s");
1955 :
1956 : wlen = png_strlen(width);
1957 : hlen = png_strlen(height);
1958 : total_len = wlen + hlen + 2;
1959 :
1960 : if (total_len > 64)
1961 : {
1962 : png_warning(png_ptr, "Can't write sCAL (buffer too small)");
1963 : return;
1964 : }
1965 :
1966 : buf[0] = (png_byte)unit;
1967 : png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
1968 : png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
1969 :
1970 : png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
1971 : png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
1972 : }
1973 : #endif
1974 :
1975 : #ifdef PNG_WRITE_pHYs_SUPPORTED
1976 : /* Write the pHYs chunk */
1977 : void /* PRIVATE */
1978 : png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1979 : png_uint_32 y_pixels_per_unit,
1980 : int unit_type)
1981 : {
1982 : png_byte buf[9];
1983 :
1984 : png_debug(1, "in png_write_pHYs");
1985 :
1986 : if (unit_type >= PNG_RESOLUTION_LAST)
1987 : png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
1988 :
1989 : png_save_uint_32(buf, x_pixels_per_unit);
1990 : png_save_uint_32(buf + 4, y_pixels_per_unit);
1991 : buf[8] = (png_byte)unit_type;
1992 :
1993 : png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
1994 : }
1995 : #endif
1996 :
1997 : #ifdef PNG_WRITE_tIME_SUPPORTED
1998 : /* Write the tIME chunk. Use either png_convert_from_struct_tm()
1999 : * or png_convert_from_time_t(), or fill in the structure yourself.
2000 : */
2001 : void /* PRIVATE */
2002 : png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
2003 : {
2004 : png_byte buf[7];
2005 :
2006 : png_debug(1, "in png_write_tIME");
2007 :
2008 : if (mod_time->month > 12 || mod_time->month < 1 ||
2009 : mod_time->day > 31 || mod_time->day < 1 ||
2010 : mod_time->hour > 23 || mod_time->second > 60)
2011 : {
2012 : png_warning(png_ptr, "Invalid time specified for tIME chunk");
2013 : return;
2014 : }
2015 :
2016 : png_save_uint_16(buf, mod_time->year);
2017 : buf[2] = mod_time->month;
2018 : buf[3] = mod_time->day;
2019 : buf[4] = mod_time->hour;
2020 : buf[5] = mod_time->minute;
2021 : buf[6] = mod_time->second;
2022 :
2023 : png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
2024 : }
2025 : #endif
2026 :
2027 : #ifdef PNG_WRITE_APNG_SUPPORTED
2028 : void /* PRIVATE */
2029 6 : png_write_acTL(png_structp png_ptr,
2030 : png_uint_32 num_frames, png_uint_32 num_plays)
2031 : {
2032 : png_byte buf[8];
2033 :
2034 : png_debug(1, "in png_write_acTL");
2035 :
2036 6 : png_ptr->num_frames_to_write = num_frames;
2037 :
2038 6 : if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
2039 1 : num_frames--;
2040 :
2041 6 : png_save_uint_32(buf, num_frames);
2042 6 : png_save_uint_32(buf + 4, num_plays);
2043 :
2044 6 : png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
2045 6 : }
2046 :
2047 : void /* PRIVATE */
2048 18 : png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
2049 : png_uint_32 x_offset, png_uint_32 y_offset,
2050 : png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
2051 : png_byte blend_op)
2052 : {
2053 : png_byte buf[26];
2054 :
2055 : png_debug(1, "in png_write_fcTL");
2056 :
2057 18 : if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
2058 0 : png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
2059 23 : if (png_ptr->num_frames_written == 0 &&
2060 10 : (width != png_ptr->first_frame_width ||
2061 5 : height != png_ptr->first_frame_height))
2062 0 : png_error(png_ptr, "width and/or height in the first frame's fcTL "
2063 : "don't match the ones in IHDR");
2064 :
2065 : /* more error checking */
2066 18 : png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
2067 : delay_num, delay_den, dispose_op, blend_op);
2068 :
2069 18 : png_save_uint_32(buf, png_ptr->next_seq_num);
2070 18 : png_save_uint_32(buf + 4, width);
2071 18 : png_save_uint_32(buf + 8, height);
2072 18 : png_save_uint_32(buf + 12, x_offset);
2073 18 : png_save_uint_32(buf + 16, y_offset);
2074 18 : png_save_uint_16(buf + 20, delay_num);
2075 18 : png_save_uint_16(buf + 22, delay_den);
2076 18 : buf[24] = dispose_op;
2077 18 : buf[25] = blend_op;
2078 :
2079 18 : png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
2080 :
2081 18 : png_ptr->next_seq_num++;
2082 18 : }
2083 : #endif /* PNG_WRITE_APNG_SUPPORTED */
2084 :
2085 : /* Initializes the row writing capability of libpng */
2086 : void /* PRIVATE */
2087 39 : png_write_start_row(png_structp png_ptr)
2088 : {
2089 : #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2090 : /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2091 :
2092 : /* Start of interlace block */
2093 : static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2094 :
2095 : /* Offset to next interlace block */
2096 : static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2097 :
2098 : /* Start of interlace block in the y direction */
2099 : static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2100 :
2101 : /* Offset to next interlace block in the y direction */
2102 : static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2103 : #endif
2104 :
2105 : png_alloc_size_t buf_size;
2106 : int usr_pixel_depth;
2107 :
2108 : png_debug(1, "in png_write_start_row");
2109 :
2110 39 : usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
2111 39 : buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
2112 :
2113 : /* 1.5.6: added to allow checking in the row write code. */
2114 39 : png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
2115 39 : png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
2116 :
2117 : /* Set up row buffer */
2118 39 : png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
2119 :
2120 39 : png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
2121 :
2122 : #ifdef PNG_WRITE_FILTER_SUPPORTED
2123 : /* Set up filtering buffer, if using this filter */
2124 : if (png_ptr->do_filter & PNG_FILTER_SUB)
2125 : {
2126 : png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
2127 :
2128 : png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
2129 : }
2130 :
2131 : /* We only need to keep the previous row if we are using one of these. */
2132 : if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
2133 : {
2134 : /* Set up previous row buffer */
2135 : png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
2136 :
2137 : if (png_ptr->do_filter & PNG_FILTER_UP)
2138 : {
2139 : png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
2140 : png_ptr->rowbytes + 1);
2141 :
2142 : png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
2143 : }
2144 :
2145 : if (png_ptr->do_filter & PNG_FILTER_AVG)
2146 : {
2147 : png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
2148 : png_ptr->rowbytes + 1);
2149 :
2150 : png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
2151 : }
2152 :
2153 : if (png_ptr->do_filter & PNG_FILTER_PAETH)
2154 : {
2155 : png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
2156 : png_ptr->rowbytes + 1);
2157 :
2158 : png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
2159 : }
2160 : }
2161 : #endif /* PNG_WRITE_FILTER_SUPPORTED */
2162 :
2163 : #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2164 : /* If interlaced, we need to set up width and height of pass */
2165 : if (png_ptr->interlaced)
2166 : {
2167 : if (!(png_ptr->transformations & PNG_INTERLACE))
2168 : {
2169 : png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2170 : png_pass_ystart[0]) / png_pass_yinc[0];
2171 :
2172 : png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
2173 : png_pass_start[0]) / png_pass_inc[0];
2174 : }
2175 :
2176 : else
2177 : {
2178 : png_ptr->num_rows = png_ptr->height;
2179 : png_ptr->usr_width = png_ptr->width;
2180 : }
2181 : }
2182 :
2183 : else
2184 : #endif
2185 : {
2186 39 : png_ptr->num_rows = png_ptr->height;
2187 39 : png_ptr->usr_width = png_ptr->width;
2188 : }
2189 :
2190 39 : png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT);
2191 39 : png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2192 39 : png_ptr->zstream.next_out = png_ptr->zbuf;
2193 39 : }
2194 :
2195 : /* Internal use only. Called when finished processing a row of data. */
2196 : void /* PRIVATE */
2197 299 : png_write_finish_row(png_structp png_ptr)
2198 : {
2199 : #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2200 : /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2201 :
2202 : /* Start of interlace block */
2203 : static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2204 :
2205 : /* Offset to next interlace block */
2206 : static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2207 :
2208 : /* Start of interlace block in the y direction */
2209 : static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2210 :
2211 : /* Offset to next interlace block in the y direction */
2212 : static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2213 : #endif
2214 :
2215 : int ret;
2216 :
2217 : png_debug(1, "in png_write_finish_row");
2218 :
2219 : /* Next row */
2220 299 : png_ptr->row_number++;
2221 :
2222 : /* See if we are done */
2223 299 : if (png_ptr->row_number < png_ptr->num_rows)
2224 260 : return;
2225 :
2226 : #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2227 : /* If interlaced, go to next pass */
2228 : if (png_ptr->interlaced)
2229 : {
2230 : png_ptr->row_number = 0;
2231 : if (png_ptr->transformations & PNG_INTERLACE)
2232 : {
2233 : png_ptr->pass++;
2234 : }
2235 :
2236 : else
2237 : {
2238 : /* Loop until we find a non-zero width or height pass */
2239 : do
2240 : {
2241 : png_ptr->pass++;
2242 :
2243 : if (png_ptr->pass >= 7)
2244 : break;
2245 :
2246 : png_ptr->usr_width = (png_ptr->width +
2247 : png_pass_inc[png_ptr->pass] - 1 -
2248 : png_pass_start[png_ptr->pass]) /
2249 : png_pass_inc[png_ptr->pass];
2250 :
2251 : png_ptr->num_rows = (png_ptr->height +
2252 : png_pass_yinc[png_ptr->pass] - 1 -
2253 : png_pass_ystart[png_ptr->pass]) /
2254 : png_pass_yinc[png_ptr->pass];
2255 :
2256 : if (png_ptr->transformations & PNG_INTERLACE)
2257 : break;
2258 :
2259 : } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
2260 :
2261 : }
2262 :
2263 : /* Reset the row above the image for the next pass */
2264 : if (png_ptr->pass < 7)
2265 : {
2266 : if (png_ptr->prev_row != NULL)
2267 : png_memset(png_ptr->prev_row, 0,
2268 : (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
2269 : png_ptr->usr_bit_depth, png_ptr->width)) + 1);
2270 :
2271 : return;
2272 : }
2273 : }
2274 : #endif
2275 :
2276 : /* If we get here, we've just written the last row, so we need
2277 : to flush the compressor */
2278 : do
2279 : {
2280 : /* Tell the compressor we are done */
2281 39 : ret = deflate(&png_ptr->zstream, Z_FINISH);
2282 :
2283 : /* Check for an error */
2284 39 : if (ret == Z_OK)
2285 : {
2286 : /* Check to see if we need more room */
2287 0 : if (!(png_ptr->zstream.avail_out))
2288 : {
2289 0 : png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
2290 0 : png_ptr->zstream.next_out = png_ptr->zbuf;
2291 0 : png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2292 : }
2293 : }
2294 :
2295 39 : else if (ret != Z_STREAM_END)
2296 : {
2297 0 : if (png_ptr->zstream.msg != NULL)
2298 0 : png_error(png_ptr, png_ptr->zstream.msg);
2299 :
2300 : else
2301 0 : png_error(png_ptr, "zlib error");
2302 : }
2303 39 : } while (ret != Z_STREAM_END);
2304 :
2305 : /* Write any extra space */
2306 39 : if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
2307 : {
2308 78 : png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
2309 39 : png_ptr->zstream.avail_out);
2310 : }
2311 :
2312 39 : png_zlib_release(png_ptr);
2313 39 : png_ptr->zstream.data_type = Z_BINARY;
2314 : }
2315 :
2316 : #ifdef PNG_WRITE_INTERLACING_SUPPORTED
2317 : /* Pick out the correct pixels for the interlace pass.
2318 : * The basic idea here is to go through the row with a source
2319 : * pointer and a destination pointer (sp and dp), and copy the
2320 : * correct pixels for the pass. As the row gets compacted,
2321 : * sp will always be >= dp, so we should never overwrite anything.
2322 : * See the default: case for the easiest code to understand.
2323 : */
2324 : void /* PRIVATE */
2325 : png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
2326 : {
2327 : /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2328 :
2329 : /* Start of interlace block */
2330 : static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2331 :
2332 : /* Offset to next interlace block */
2333 : static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2334 :
2335 : png_debug(1, "in png_do_write_interlace");
2336 :
2337 : /* We don't have to do anything on the last pass (6) */
2338 : if (pass < 6)
2339 : {
2340 : /* Each pixel depth is handled separately */
2341 : switch (row_info->pixel_depth)
2342 : {
2343 : case 1:
2344 : {
2345 : png_bytep sp;
2346 : png_bytep dp;
2347 : int shift;
2348 : int d;
2349 : int value;
2350 : png_uint_32 i;
2351 : png_uint_32 row_width = row_info->width;
2352 :
2353 : dp = row;
2354 : d = 0;
2355 : shift = 7;
2356 :
2357 : for (i = png_pass_start[pass]; i < row_width;
2358 : i += png_pass_inc[pass])
2359 : {
2360 : sp = row + (png_size_t)(i >> 3);
2361 : value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
2362 : d |= (value << shift);
2363 :
2364 : if (shift == 0)
2365 : {
2366 : shift = 7;
2367 : *dp++ = (png_byte)d;
2368 : d = 0;
2369 : }
2370 :
2371 : else
2372 : shift--;
2373 :
2374 : }
2375 : if (shift != 7)
2376 : *dp = (png_byte)d;
2377 :
2378 : break;
2379 : }
2380 :
2381 : case 2:
2382 : {
2383 : png_bytep sp;
2384 : png_bytep dp;
2385 : int shift;
2386 : int d;
2387 : int value;
2388 : png_uint_32 i;
2389 : png_uint_32 row_width = row_info->width;
2390 :
2391 : dp = row;
2392 : shift = 6;
2393 : d = 0;
2394 :
2395 : for (i = png_pass_start[pass]; i < row_width;
2396 : i += png_pass_inc[pass])
2397 : {
2398 : sp = row + (png_size_t)(i >> 2);
2399 : value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
2400 : d |= (value << shift);
2401 :
2402 : if (shift == 0)
2403 : {
2404 : shift = 6;
2405 : *dp++ = (png_byte)d;
2406 : d = 0;
2407 : }
2408 :
2409 : else
2410 : shift -= 2;
2411 : }
2412 : if (shift != 6)
2413 : *dp = (png_byte)d;
2414 :
2415 : break;
2416 : }
2417 :
2418 : case 4:
2419 : {
2420 : png_bytep sp;
2421 : png_bytep dp;
2422 : int shift;
2423 : int d;
2424 : int value;
2425 : png_uint_32 i;
2426 : png_uint_32 row_width = row_info->width;
2427 :
2428 : dp = row;
2429 : shift = 4;
2430 : d = 0;
2431 : for (i = png_pass_start[pass]; i < row_width;
2432 : i += png_pass_inc[pass])
2433 : {
2434 : sp = row + (png_size_t)(i >> 1);
2435 : value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
2436 : d |= (value << shift);
2437 :
2438 : if (shift == 0)
2439 : {
2440 : shift = 4;
2441 : *dp++ = (png_byte)d;
2442 : d = 0;
2443 : }
2444 :
2445 : else
2446 : shift -= 4;
2447 : }
2448 : if (shift != 4)
2449 : *dp = (png_byte)d;
2450 :
2451 : break;
2452 : }
2453 :
2454 : default:
2455 : {
2456 : png_bytep sp;
2457 : png_bytep dp;
2458 : png_uint_32 i;
2459 : png_uint_32 row_width = row_info->width;
2460 : png_size_t pixel_bytes;
2461 :
2462 : /* Start at the beginning */
2463 : dp = row;
2464 :
2465 : /* Find out how many bytes each pixel takes up */
2466 : pixel_bytes = (row_info->pixel_depth >> 3);
2467 :
2468 : /* Loop through the row, only looking at the pixels that matter */
2469 : for (i = png_pass_start[pass]; i < row_width;
2470 : i += png_pass_inc[pass])
2471 : {
2472 : /* Find out where the original pixel is */
2473 : sp = row + (png_size_t)i * pixel_bytes;
2474 :
2475 : /* Move the pixel */
2476 : if (dp != sp)
2477 : png_memcpy(dp, sp, pixel_bytes);
2478 :
2479 : /* Next pixel */
2480 : dp += pixel_bytes;
2481 : }
2482 : break;
2483 : }
2484 : }
2485 : /* Set new row width */
2486 : row_info->width = (row_info->width +
2487 : png_pass_inc[pass] - 1 -
2488 : png_pass_start[pass]) /
2489 : png_pass_inc[pass];
2490 :
2491 : row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
2492 : row_info->width);
2493 : }
2494 : }
2495 : #endif
2496 :
2497 : /* This filters the row, chooses which filter to use, if it has not already
2498 : * been specified by the application, and then writes the row out with the
2499 : * chosen filter.
2500 : */
2501 : static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
2502 : png_size_t row_bytes);
2503 :
2504 : #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
2505 : #define PNG_HISHIFT 10
2506 : #define PNG_LOMASK ((png_uint_32)0xffffL)
2507 : #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
2508 : void /* PRIVATE */
2509 299 : png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
2510 : {
2511 : png_bytep best_row;
2512 : #ifdef PNG_WRITE_FILTER_SUPPORTED
2513 : png_bytep prev_row, row_buf;
2514 : png_uint_32 mins, bpp;
2515 : png_byte filter_to_do = png_ptr->do_filter;
2516 : png_size_t row_bytes = row_info->rowbytes;
2517 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2518 : int num_p_filters = png_ptr->num_prev_filters;
2519 : #endif
2520 :
2521 : png_debug(1, "in png_write_find_filter");
2522 :
2523 : #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2524 : if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
2525 : {
2526 : /* These will never be selected so we need not test them. */
2527 : filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
2528 : }
2529 : #endif
2530 :
2531 : /* Find out how many bytes offset each pixel is */
2532 : bpp = (row_info->pixel_depth + 7) >> 3;
2533 :
2534 : prev_row = png_ptr->prev_row;
2535 : #endif
2536 299 : best_row = png_ptr->row_buf;
2537 : #ifdef PNG_WRITE_FILTER_SUPPORTED
2538 : row_buf = best_row;
2539 : mins = PNG_MAXSUM;
2540 :
2541 : /* The prediction method we use is to find which method provides the
2542 : * smallest value when summing the absolute values of the distances
2543 : * from zero, using anything >= 128 as negative numbers. This is known
2544 : * as the "minimum sum of absolute differences" heuristic. Other
2545 : * heuristics are the "weighted minimum sum of absolute differences"
2546 : * (experimental and can in theory improve compression), and the "zlib
2547 : * predictive" method (not implemented yet), which does test compressions
2548 : * of lines using different filter methods, and then chooses the
2549 : * (series of) filter(s) that give minimum compressed data size (VERY
2550 : * computationally expensive).
2551 : *
2552 : * GRR 980525: consider also
2553 : *
2554 : * (1) minimum sum of absolute differences from running average (i.e.,
2555 : * keep running sum of non-absolute differences & count of bytes)
2556 : * [track dispersion, too? restart average if dispersion too large?]
2557 : *
2558 : * (1b) minimum sum of absolute differences from sliding average, probably
2559 : * with window size <= deflate window (usually 32K)
2560 : *
2561 : * (2) minimum sum of squared differences from zero or running average
2562 : * (i.e., ~ root-mean-square approach)
2563 : */
2564 :
2565 :
2566 : /* We don't need to test the 'no filter' case if this is the only filter
2567 : * that has been chosen, as it doesn't actually do anything to the data.
2568 : */
2569 : if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
2570 : {
2571 : png_bytep rp;
2572 : png_uint_32 sum = 0;
2573 : png_size_t i;
2574 : int v;
2575 :
2576 : for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
2577 : {
2578 : v = *rp;
2579 : sum += (v < 128) ? v : 256 - v;
2580 : }
2581 :
2582 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2583 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2584 : {
2585 : png_uint_32 sumhi, sumlo;
2586 : int j;
2587 : sumlo = sum & PNG_LOMASK;
2588 : sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
2589 :
2590 : /* Reduce the sum if we match any of the previous rows */
2591 : for (j = 0; j < num_p_filters; j++)
2592 : {
2593 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2594 : {
2595 : sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2596 : PNG_WEIGHT_SHIFT;
2597 :
2598 : sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2599 : PNG_WEIGHT_SHIFT;
2600 : }
2601 : }
2602 :
2603 : /* Factor in the cost of this filter (this is here for completeness,
2604 : * but it makes no sense to have a "cost" for the NONE filter, as
2605 : * it has the minimum possible computational cost - none).
2606 : */
2607 : sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2608 : PNG_COST_SHIFT;
2609 :
2610 : sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
2611 : PNG_COST_SHIFT;
2612 :
2613 : if (sumhi > PNG_HIMASK)
2614 : sum = PNG_MAXSUM;
2615 :
2616 : else
2617 : sum = (sumhi << PNG_HISHIFT) + sumlo;
2618 : }
2619 : #endif
2620 : mins = sum;
2621 : }
2622 :
2623 : /* Sub filter */
2624 : if (filter_to_do == PNG_FILTER_SUB)
2625 : /* It's the only filter so no testing is needed */
2626 : {
2627 : png_bytep rp, lp, dp;
2628 : png_size_t i;
2629 :
2630 : for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2631 : i++, rp++, dp++)
2632 : {
2633 : *dp = *rp;
2634 : }
2635 :
2636 : for (lp = row_buf + 1; i < row_bytes;
2637 : i++, rp++, lp++, dp++)
2638 : {
2639 : *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2640 : }
2641 :
2642 : best_row = png_ptr->sub_row;
2643 : }
2644 :
2645 : else if (filter_to_do & PNG_FILTER_SUB)
2646 : {
2647 : png_bytep rp, dp, lp;
2648 : png_uint_32 sum = 0, lmins = mins;
2649 : png_size_t i;
2650 : int v;
2651 :
2652 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2653 : /* We temporarily increase the "minimum sum" by the factor we
2654 : * would reduce the sum of this filter, so that we can do the
2655 : * early exit comparison without scaling the sum each time.
2656 : */
2657 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2658 : {
2659 : int j;
2660 : png_uint_32 lmhi, lmlo;
2661 : lmlo = lmins & PNG_LOMASK;
2662 : lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2663 :
2664 : for (j = 0; j < num_p_filters; j++)
2665 : {
2666 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2667 : {
2668 : lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2669 : PNG_WEIGHT_SHIFT;
2670 :
2671 : lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2672 : PNG_WEIGHT_SHIFT;
2673 : }
2674 : }
2675 :
2676 : lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2677 : PNG_COST_SHIFT;
2678 :
2679 : lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2680 : PNG_COST_SHIFT;
2681 :
2682 : if (lmhi > PNG_HIMASK)
2683 : lmins = PNG_MAXSUM;
2684 :
2685 : else
2686 : lmins = (lmhi << PNG_HISHIFT) + lmlo;
2687 : }
2688 : #endif
2689 :
2690 : for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
2691 : i++, rp++, dp++)
2692 : {
2693 : v = *dp = *rp;
2694 :
2695 : sum += (v < 128) ? v : 256 - v;
2696 : }
2697 :
2698 : for (lp = row_buf + 1; i < row_bytes;
2699 : i++, rp++, lp++, dp++)
2700 : {
2701 : v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
2702 :
2703 : sum += (v < 128) ? v : 256 - v;
2704 :
2705 : if (sum > lmins) /* We are already worse, don't continue. */
2706 : break;
2707 : }
2708 :
2709 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2710 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2711 : {
2712 : int j;
2713 : png_uint_32 sumhi, sumlo;
2714 : sumlo = sum & PNG_LOMASK;
2715 : sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2716 :
2717 : for (j = 0; j < num_p_filters; j++)
2718 : {
2719 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
2720 : {
2721 : sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
2722 : PNG_WEIGHT_SHIFT;
2723 :
2724 : sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
2725 : PNG_WEIGHT_SHIFT;
2726 : }
2727 : }
2728 :
2729 : sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2730 : PNG_COST_SHIFT;
2731 :
2732 : sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
2733 : PNG_COST_SHIFT;
2734 :
2735 : if (sumhi > PNG_HIMASK)
2736 : sum = PNG_MAXSUM;
2737 :
2738 : else
2739 : sum = (sumhi << PNG_HISHIFT) + sumlo;
2740 : }
2741 : #endif
2742 :
2743 : if (sum < mins)
2744 : {
2745 : mins = sum;
2746 : best_row = png_ptr->sub_row;
2747 : }
2748 : }
2749 :
2750 : /* Up filter */
2751 : if (filter_to_do == PNG_FILTER_UP)
2752 : {
2753 : png_bytep rp, dp, pp;
2754 : png_size_t i;
2755 :
2756 : for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2757 : pp = prev_row + 1; i < row_bytes;
2758 : i++, rp++, pp++, dp++)
2759 : {
2760 : *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
2761 : }
2762 :
2763 : best_row = png_ptr->up_row;
2764 : }
2765 :
2766 : else if (filter_to_do & PNG_FILTER_UP)
2767 : {
2768 : png_bytep rp, dp, pp;
2769 : png_uint_32 sum = 0, lmins = mins;
2770 : png_size_t i;
2771 : int v;
2772 :
2773 :
2774 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2775 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2776 : {
2777 : int j;
2778 : png_uint_32 lmhi, lmlo;
2779 : lmlo = lmins & PNG_LOMASK;
2780 : lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2781 :
2782 : for (j = 0; j < num_p_filters; j++)
2783 : {
2784 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2785 : {
2786 : lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2787 : PNG_WEIGHT_SHIFT;
2788 :
2789 : lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2790 : PNG_WEIGHT_SHIFT;
2791 : }
2792 : }
2793 :
2794 : lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2795 : PNG_COST_SHIFT;
2796 :
2797 : lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
2798 : PNG_COST_SHIFT;
2799 :
2800 : if (lmhi > PNG_HIMASK)
2801 : lmins = PNG_MAXSUM;
2802 :
2803 : else
2804 : lmins = (lmhi << PNG_HISHIFT) + lmlo;
2805 : }
2806 : #endif
2807 :
2808 : for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
2809 : pp = prev_row + 1; i < row_bytes; i++)
2810 : {
2811 : v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2812 :
2813 : sum += (v < 128) ? v : 256 - v;
2814 :
2815 : if (sum > lmins) /* We are already worse, don't continue. */
2816 : break;
2817 : }
2818 :
2819 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2820 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2821 : {
2822 : int j;
2823 : png_uint_32 sumhi, sumlo;
2824 : sumlo = sum & PNG_LOMASK;
2825 : sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2826 :
2827 : for (j = 0; j < num_p_filters; j++)
2828 : {
2829 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
2830 : {
2831 : sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2832 : PNG_WEIGHT_SHIFT;
2833 :
2834 : sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2835 : PNG_WEIGHT_SHIFT;
2836 : }
2837 : }
2838 :
2839 : sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2840 : PNG_COST_SHIFT;
2841 :
2842 : sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
2843 : PNG_COST_SHIFT;
2844 :
2845 : if (sumhi > PNG_HIMASK)
2846 : sum = PNG_MAXSUM;
2847 :
2848 : else
2849 : sum = (sumhi << PNG_HISHIFT) + sumlo;
2850 : }
2851 : #endif
2852 :
2853 : if (sum < mins)
2854 : {
2855 : mins = sum;
2856 : best_row = png_ptr->up_row;
2857 : }
2858 : }
2859 :
2860 : /* Avg filter */
2861 : if (filter_to_do == PNG_FILTER_AVG)
2862 : {
2863 : png_bytep rp, dp, pp, lp;
2864 : png_uint_32 i;
2865 :
2866 : for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2867 : pp = prev_row + 1; i < bpp; i++)
2868 : {
2869 : *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2870 : }
2871 :
2872 : for (lp = row_buf + 1; i < row_bytes; i++)
2873 : {
2874 : *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
2875 : & 0xff);
2876 : }
2877 : best_row = png_ptr->avg_row;
2878 : }
2879 :
2880 : else if (filter_to_do & PNG_FILTER_AVG)
2881 : {
2882 : png_bytep rp, dp, pp, lp;
2883 : png_uint_32 sum = 0, lmins = mins;
2884 : png_size_t i;
2885 : int v;
2886 :
2887 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2888 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2889 : {
2890 : int j;
2891 : png_uint_32 lmhi, lmlo;
2892 : lmlo = lmins & PNG_LOMASK;
2893 : lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
2894 :
2895 : for (j = 0; j < num_p_filters; j++)
2896 : {
2897 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
2898 : {
2899 : lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
2900 : PNG_WEIGHT_SHIFT;
2901 :
2902 : lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
2903 : PNG_WEIGHT_SHIFT;
2904 : }
2905 : }
2906 :
2907 : lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2908 : PNG_COST_SHIFT;
2909 :
2910 : lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
2911 : PNG_COST_SHIFT;
2912 :
2913 : if (lmhi > PNG_HIMASK)
2914 : lmins = PNG_MAXSUM;
2915 :
2916 : else
2917 : lmins = (lmhi << PNG_HISHIFT) + lmlo;
2918 : }
2919 : #endif
2920 :
2921 : for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
2922 : pp = prev_row + 1; i < bpp; i++)
2923 : {
2924 : v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
2925 :
2926 : sum += (v < 128) ? v : 256 - v;
2927 : }
2928 :
2929 : for (lp = row_buf + 1; i < row_bytes; i++)
2930 : {
2931 : v = *dp++ =
2932 : (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
2933 :
2934 : sum += (v < 128) ? v : 256 - v;
2935 :
2936 : if (sum > lmins) /* We are already worse, don't continue. */
2937 : break;
2938 : }
2939 :
2940 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
2941 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
2942 : {
2943 : int j;
2944 : png_uint_32 sumhi, sumlo;
2945 : sumlo = sum & PNG_LOMASK;
2946 : sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
2947 :
2948 : for (j = 0; j < num_p_filters; j++)
2949 : {
2950 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
2951 : {
2952 : sumlo = (sumlo * png_ptr->filter_weights[j]) >>
2953 : PNG_WEIGHT_SHIFT;
2954 :
2955 : sumhi = (sumhi * png_ptr->filter_weights[j]) >>
2956 : PNG_WEIGHT_SHIFT;
2957 : }
2958 : }
2959 :
2960 : sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2961 : PNG_COST_SHIFT;
2962 :
2963 : sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
2964 : PNG_COST_SHIFT;
2965 :
2966 : if (sumhi > PNG_HIMASK)
2967 : sum = PNG_MAXSUM;
2968 :
2969 : else
2970 : sum = (sumhi << PNG_HISHIFT) + sumlo;
2971 : }
2972 : #endif
2973 :
2974 : if (sum < mins)
2975 : {
2976 : mins = sum;
2977 : best_row = png_ptr->avg_row;
2978 : }
2979 : }
2980 :
2981 : /* Paeth filter */
2982 : if (filter_to_do == PNG_FILTER_PAETH)
2983 : {
2984 : png_bytep rp, dp, pp, cp, lp;
2985 : png_size_t i;
2986 :
2987 : for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
2988 : pp = prev_row + 1; i < bpp; i++)
2989 : {
2990 : *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
2991 : }
2992 :
2993 : for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
2994 : {
2995 : int a, b, c, pa, pb, pc, p;
2996 :
2997 : b = *pp++;
2998 : c = *cp++;
2999 : a = *lp++;
3000 :
3001 : p = b - c;
3002 : pc = a - c;
3003 :
3004 : #ifdef PNG_USE_ABS
3005 : pa = abs(p);
3006 : pb = abs(pc);
3007 : pc = abs(p + pc);
3008 : #else
3009 : pa = p < 0 ? -p : p;
3010 : pb = pc < 0 ? -pc : pc;
3011 : pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3012 : #endif
3013 :
3014 : p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
3015 :
3016 : *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
3017 : }
3018 : best_row = png_ptr->paeth_row;
3019 : }
3020 :
3021 : else if (filter_to_do & PNG_FILTER_PAETH)
3022 : {
3023 : png_bytep rp, dp, pp, cp, lp;
3024 : png_uint_32 sum = 0, lmins = mins;
3025 : png_size_t i;
3026 : int v;
3027 :
3028 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
3029 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
3030 : {
3031 : int j;
3032 : png_uint_32 lmhi, lmlo;
3033 : lmlo = lmins & PNG_LOMASK;
3034 : lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
3035 :
3036 : for (j = 0; j < num_p_filters; j++)
3037 : {
3038 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
3039 : {
3040 : lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
3041 : PNG_WEIGHT_SHIFT;
3042 :
3043 : lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
3044 : PNG_WEIGHT_SHIFT;
3045 : }
3046 : }
3047 :
3048 : lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
3049 : PNG_COST_SHIFT;
3050 :
3051 : lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
3052 : PNG_COST_SHIFT;
3053 :
3054 : if (lmhi > PNG_HIMASK)
3055 : lmins = PNG_MAXSUM;
3056 :
3057 : else
3058 : lmins = (lmhi << PNG_HISHIFT) + lmlo;
3059 : }
3060 : #endif
3061 :
3062 : for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
3063 : pp = prev_row + 1; i < bpp; i++)
3064 : {
3065 : v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
3066 :
3067 : sum += (v < 128) ? v : 256 - v;
3068 : }
3069 :
3070 : for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
3071 : {
3072 : int a, b, c, pa, pb, pc, p;
3073 :
3074 : b = *pp++;
3075 : c = *cp++;
3076 : a = *lp++;
3077 :
3078 : #ifndef PNG_SLOW_PAETH
3079 : p = b - c;
3080 : pc = a - c;
3081 : #ifdef PNG_USE_ABS
3082 : pa = abs(p);
3083 : pb = abs(pc);
3084 : pc = abs(p + pc);
3085 : #else
3086 : pa = p < 0 ? -p : p;
3087 : pb = pc < 0 ? -pc : pc;
3088 : pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3089 : #endif
3090 : p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
3091 : #else /* PNG_SLOW_PAETH */
3092 : p = a + b - c;
3093 : pa = abs(p - a);
3094 : pb = abs(p - b);
3095 : pc = abs(p - c);
3096 :
3097 : if (pa <= pb && pa <= pc)
3098 : p = a;
3099 :
3100 : else if (pb <= pc)
3101 : p = b;
3102 :
3103 : else
3104 : p = c;
3105 : #endif /* PNG_SLOW_PAETH */
3106 :
3107 : v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
3108 :
3109 : sum += (v < 128) ? v : 256 - v;
3110 :
3111 : if (sum > lmins) /* We are already worse, don't continue. */
3112 : break;
3113 : }
3114 :
3115 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
3116 : if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
3117 : {
3118 : int j;
3119 : png_uint_32 sumhi, sumlo;
3120 : sumlo = sum & PNG_LOMASK;
3121 : sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
3122 :
3123 : for (j = 0; j < num_p_filters; j++)
3124 : {
3125 : if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
3126 : {
3127 : sumlo = (sumlo * png_ptr->filter_weights[j]) >>
3128 : PNG_WEIGHT_SHIFT;
3129 :
3130 : sumhi = (sumhi * png_ptr->filter_weights[j]) >>
3131 : PNG_WEIGHT_SHIFT;
3132 : }
3133 : }
3134 :
3135 : sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
3136 : PNG_COST_SHIFT;
3137 :
3138 : sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
3139 : PNG_COST_SHIFT;
3140 :
3141 : if (sumhi > PNG_HIMASK)
3142 : sum = PNG_MAXSUM;
3143 :
3144 : else
3145 : sum = (sumhi << PNG_HISHIFT) + sumlo;
3146 : }
3147 : #endif
3148 :
3149 : if (sum < mins)
3150 : {
3151 : best_row = png_ptr->paeth_row;
3152 : }
3153 : }
3154 : #endif /* PNG_WRITE_FILTER_SUPPORTED */
3155 :
3156 : /* Do the actual writing of the filtered row data from the chosen filter. */
3157 299 : png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
3158 :
3159 : #ifdef PNG_WRITE_FILTER_SUPPORTED
3160 : #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
3161 : /* Save the type of filter we picked this time for future calculations */
3162 : if (png_ptr->num_prev_filters > 0)
3163 : {
3164 : int j;
3165 :
3166 : for (j = 1; j < num_p_filters; j++)
3167 : {
3168 : png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
3169 : }
3170 :
3171 : png_ptr->prev_filters[j] = best_row[0];
3172 : }
3173 : #endif
3174 : #endif /* PNG_WRITE_FILTER_SUPPORTED */
3175 299 : }
3176 :
3177 :
3178 : /* Do the actual writing of a previously filtered row. */
3179 : static void
3180 299 : png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
3181 : png_size_t avail/*includes filter byte*/)
3182 : {
3183 : png_debug(1, "in png_write_filtered_row");
3184 :
3185 : png_debug1(2, "filter = %d", filtered_row[0]);
3186 : /* Set up the zlib input buffer */
3187 :
3188 299 : png_ptr->zstream.next_in = filtered_row;
3189 299 : png_ptr->zstream.avail_in = 0;
3190 : /* Repeat until we have compressed all the data */
3191 : do
3192 : {
3193 : int ret; /* Return of zlib */
3194 :
3195 : /* Record the number of bytes available - zlib supports at least 65535
3196 : * bytes at one step, depending on the size of the zlib type 'uInt', the
3197 : * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
3198 : * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
3199 : * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
3200 : * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called
3201 : * with smaller chunks of data.
3202 : */
3203 299 : if (png_ptr->zstream.avail_in == 0)
3204 : {
3205 : if (avail > ZLIB_IO_MAX)
3206 : {
3207 : png_ptr->zstream.avail_in = ZLIB_IO_MAX;
3208 : avail -= ZLIB_IO_MAX;
3209 : }
3210 :
3211 : else
3212 : {
3213 : /* So this will fit in the available uInt space: */
3214 299 : png_ptr->zstream.avail_in = (uInt)avail;
3215 299 : avail = 0;
3216 : }
3217 : }
3218 :
3219 : /* Compress the data */
3220 299 : ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
3221 :
3222 : /* Check for compression errors */
3223 299 : if (ret != Z_OK)
3224 : {
3225 0 : if (png_ptr->zstream.msg != NULL)
3226 0 : png_error(png_ptr, png_ptr->zstream.msg);
3227 :
3228 : else
3229 0 : png_error(png_ptr, "zlib error");
3230 : }
3231 :
3232 : /* See if it is time to write another IDAT */
3233 299 : if (!(png_ptr->zstream.avail_out))
3234 : {
3235 : /* Write the IDAT and reset the zlib output buffer */
3236 0 : png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
3237 : }
3238 : /* Repeat until all data has been compressed */
3239 299 : } while (avail > 0 || png_ptr->zstream.avail_in > 0);
3240 :
3241 : /* Swap the current and previous rows */
3242 299 : if (png_ptr->prev_row != NULL)
3243 : {
3244 : png_bytep tptr;
3245 :
3246 0 : tptr = png_ptr->prev_row;
3247 0 : png_ptr->prev_row = png_ptr->row_buf;
3248 0 : png_ptr->row_buf = tptr;
3249 : }
3250 :
3251 : /* Finish row - updates counters and flushes zlib if last row */
3252 299 : png_write_finish_row(png_ptr);
3253 :
3254 : #ifdef PNG_WRITE_FLUSH_SUPPORTED
3255 299 : png_ptr->flush_rows++;
3256 :
3257 299 : if (png_ptr->flush_dist > 0 &&
3258 0 : png_ptr->flush_rows >= png_ptr->flush_dist)
3259 : {
3260 0 : png_write_flush(png_ptr);
3261 : }
3262 : #endif
3263 299 : }
3264 :
3265 : #ifdef PNG_WRITE_APNG_SUPPORTED
3266 : void /* PRIVATE */
3267 19 : png_write_reset(png_structp png_ptr)
3268 : {
3269 19 : png_ptr->row_number = 0;
3270 19 : png_ptr->pass = 0;
3271 19 : png_ptr->mode &= ~PNG_HAVE_IDAT;
3272 19 : }
3273 :
3274 : void /* PRIVATE */
3275 19 : png_write_reinit(png_structp png_ptr, png_infop info_ptr,
3276 : png_uint_32 width, png_uint_32 height)
3277 : {
3278 25 : if (png_ptr->num_frames_written == 0 &&
3279 12 : (width != png_ptr->first_frame_width ||
3280 6 : height != png_ptr->first_frame_height))
3281 0 : png_error(png_ptr, "width and/or height in the first frame's fcTL "
3282 : "don't match the ones in IHDR");
3283 38 : if (width > png_ptr->first_frame_width ||
3284 19 : height > png_ptr->first_frame_height)
3285 0 : png_error(png_ptr, "width and/or height for a frame greater than"
3286 : "the ones in IHDR");
3287 :
3288 95 : png_set_IHDR(png_ptr, info_ptr, width, height,
3289 38 : info_ptr->bit_depth, info_ptr->color_type,
3290 38 : info_ptr->interlace_type, info_ptr->compression_type,
3291 19 : info_ptr->filter_type);
3292 :
3293 19 : png_ptr->width = width;
3294 19 : png_ptr->height = height;
3295 19 : png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
3296 19 : png_ptr->usr_width = png_ptr->width;
3297 19 : }
3298 : #endif /* PNG_WRITE_APNG_SUPPORTED */
3299 : #endif /* PNG_WRITE_SUPPORTED */
|