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