source: svn/newcon3bcm2_21bu/dst/dlib/src/PNG/pngwutil.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 63.1 KB
Line 
1/*
2 * $Id: //suprahd/releases/suprahd_163/suprahd_ztvapp640_163/drivers/graphics/PNG/lpng102/pngwutil.c#1 $
3 * $Revision: #1 $
4 * $DateTime: 2006/02/24 17:51:46 $
5 * $Change: 42566 $
6 * $Author: pryush.sharma $
7 */
8
9
10/* pngwutil.c - utilities to write a PNG file
11 *
12 * libpng 1.0.2 - June 14, 1998
13 * For conditions of distribution and use, see copyright notice in png.h
14 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
15 * Copyright (c) 1996, 1997 Andreas Dilger
16 * Copyright (c) 1998, Glenn Randers-Pehrson
17 */
18
19#define PNG_INTERNAL
20#include "png.h"
21
22/* Place a 32-bit number into a buffer in PNG byte order.  We work
23 * with unsigned numbers for convenience, although one supported
24 * ancillary chunk uses signed (two's complement) numbers.
25 */
26void
27png_save_uint_32(png_bytep buf, png_uint_32 i)
28{
29   buf[0] = (png_byte)((i >> 24) & 0xff);
30   buf[1] = (png_byte)((i >> 16) & 0xff);
31   buf[2] = (png_byte)((i >> 8) & 0xff);
32   buf[3] = (png_byte)(i & 0xff);
33}
34
35#if defined(PNG_WRITE_pCAL_SUPPORTED)
36/* The png_save_int_32 function assumes integers are stored in two's
37 * complement format.  If this isn't the case, then this routine needs to
38 * be modified to write data in two's complement format.
39 */
40void
41png_save_int_32(png_bytep buf, png_int_32 i)
42{
43   buf[0] = (png_byte)((i >> 24) & 0xff);
44   buf[1] = (png_byte)((i >> 16) & 0xff);
45   buf[2] = (png_byte)((i >> 8) & 0xff);
46   buf[3] = (png_byte)(i & 0xff);
47}
48#endif
49
50/* Place a 16-bit number into a buffer in PNG byte order.
51 * The parameter is declared unsigned int, not png_uint_16,
52 * just to avoid potential problems on pre-ANSI C compilers.
53 */
54void
55png_save_uint_16(png_bytep buf, unsigned int i)
56{
57   buf[0] = (png_byte)((i >> 8) & 0xff);
58   buf[1] = (png_byte)(i & 0xff);
59}
60
61/* Write a PNG chunk all at once.  The type is an array of ASCII characters
62 * representing the chunk name.  The array must be at least 4 bytes in
63 * length, and does not need to be null terminated.  To be safe, pass the
64 * pre-defined chunk names here, and if you need a new one, define it
65 * where the others are defined.  The length is the length of the data.
66 * All the data must be present.  If that is not possible, use the
67 * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
68 * functions instead.
69 */
70void
71png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
72   png_bytep data, png_size_t length)
73{
74   png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
75   png_write_chunk_data(png_ptr, data, length);
76   png_write_chunk_end(png_ptr);
77}
78
79/* Write the start of a PNG chunk.  The type is the chunk type.
80 * The total_length is the sum of the lengths of all the data you will be
81 * passing in png_write_chunk_data().
82 */
83void
84png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
85   png_uint_32 length)
86{
87   png_byte buf[4];
88   png_debug2(0, "Writing %s chunk (%d bytes)\n", chunk_name, length);
89
90   /* write the length */
91   png_save_uint_32(buf, length);
92   png_write_data(png_ptr, buf, (png_size_t)4);
93
94   /* write the chunk name */
95   png_write_data(png_ptr, chunk_name, (png_size_t)4);
96   /* reset the crc and run it over the chunk name */
97   png_reset_crc(png_ptr);
98   png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
99}
100
101/* Write the data of a PNG chunk started with png_write_chunk_start().
102 * Note that multiple calls to this function are allowed, and that the
103 * sum of the lengths from these calls *must* add up to the total_length
104 * given to png_write_chunk_start().
105 */
106void
107png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
108{
109   /* write the data, and run the CRC over it */
110   if (data != NULL && length > 0)
111   {
112      png_calculate_crc(png_ptr, data, length);
113      png_write_data(png_ptr, data, length);
114   }
115}
116
117/* Finish a chunk started with png_write_chunk_start(). */
118void
119png_write_chunk_end(png_structp png_ptr)
120{
121   png_byte buf[4];
122
123   /* write the crc */
124   png_save_uint_32(buf, png_ptr->crc);
125
126   png_write_data(png_ptr, buf, (png_size_t)4);
127}
128
129/* Simple function to write the signature.  If we have already written
130 * the magic bytes of the signature, or more likely, the PNG stream is
131 * being embedded into another stream and doesn't need its own signature,
132 * we should call png_set_sig_bytes() to tell libpng how many of the
133 * bytes have already been written.
134 */
135void
136png_write_sig(png_structp png_ptr)
137{
138   /* write the rest of the 8 byte signature */
139   png_write_data(png_ptr, &png_sig[png_ptr->sig_bytes],
140      (png_size_t)8 - png_ptr->sig_bytes);
141}
142
143/* Write the IHDR chunk, and update the png_struct with the necessary
144 * information.  Note that the rest of this code depends upon this
145 * information being correct.
146 */
147void
148png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
149   int bit_depth, int color_type, int compression_type, int filter_type,
150   int interlace_type)
151{
152   png_byte buf[13]; /* buffer to store the IHDR info */
153
154   png_debug(1, "in png_write_IHDR\n");
155   /* Check that we have valid input data from the application info */
156   switch (color_type)
157   {
158      case PNG_COLOR_TYPE_GRAY:
159         switch (bit_depth)
160         {
161            case 1:
162            case 2:
163            case 4:
164            case 8:
165            case 16: png_ptr->channels = 1; break;
166            default: png_error(png_ptr,"Invalid bit depth for grayscale image");
167         }
168         break;
169      case PNG_COLOR_TYPE_RGB:
170         if (bit_depth != 8 && bit_depth != 16)
171            png_error(png_ptr, "Invalid bit depth for RGB image");
172         png_ptr->channels = 3;
173         break;
174      case PNG_COLOR_TYPE_PALETTE:
175         switch (bit_depth)
176         {
177            case 1:
178            case 2:
179            case 4:
180            case 8: png_ptr->channels = 1; break;
181            default: png_error(png_ptr, "Invalid bit depth for paletted image");
182         }
183         break;
184      case PNG_COLOR_TYPE_GRAY_ALPHA:
185         if (bit_depth != 8 && bit_depth != 16)
186            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
187         png_ptr->channels = 2;
188         break;
189      case PNG_COLOR_TYPE_RGB_ALPHA:
190         if (bit_depth != 8 && bit_depth != 16)
191            png_error(png_ptr, "Invalid bit depth for RGBA image");
192         png_ptr->channels = 4;
193         break;
194      default:
195         png_error(png_ptr, "Invalid image color type specified");
196   }
197
198   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
199   {
200      png_warning(png_ptr, "Invalid compression type specified");
201      compression_type = PNG_COMPRESSION_TYPE_BASE;
202   }
203
204   if (filter_type != PNG_FILTER_TYPE_BASE)
205   {
206      png_warning(png_ptr, "Invalid filter type specified");
207      filter_type = PNG_FILTER_TYPE_BASE;
208   }
209
210#ifdef PNG_WRITE_INTERLACING_SUPPORTED
211   if (interlace_type != PNG_INTERLACE_NONE &&
212      interlace_type != PNG_INTERLACE_ADAM7)
213   {
214      png_warning(png_ptr, "Invalid interlace type specified");
215      interlace_type = PNG_INTERLACE_ADAM7;
216   }
217#else
218   interlace_type=PNG_INTERLACE_NONE;
219#endif
220
221   /* save off the relevent information */
222   png_ptr->bit_depth = (png_byte)bit_depth;
223   png_ptr->color_type = (png_byte)color_type;
224   png_ptr->interlaced = (png_byte)interlace_type;
225   png_ptr->width = width;
226   png_ptr->height = height;
227
228   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
229   png_ptr->rowbytes = ((width * (png_size_t)png_ptr->pixel_depth + 7) >> 3);
230   /* set the usr info, so any transformations can modify it */
231   png_ptr->usr_width = png_ptr->width;
232   png_ptr->usr_bit_depth = png_ptr->bit_depth;
233   png_ptr->usr_channels = png_ptr->channels;
234
235   /* pack the header information into the buffer */
236   png_save_uint_32(buf, width);
237   png_save_uint_32(buf + 4, height);
238   buf[8] = (png_byte)bit_depth;
239   buf[9] = (png_byte)color_type;
240   buf[10] = (png_byte)compression_type;
241   buf[11] = (png_byte)filter_type;
242   buf[12] = (png_byte)interlace_type;
243
244   /* write the chunk */
245   png_write_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
246
247   /* initialize zlib with PNG info */
248   png_ptr->zstream.zalloc = png_zalloc;
249   png_ptr->zstream.zfree = png_zfree;
250   png_ptr->zstream.opaque = (voidpf)png_ptr;
251   if (!(png_ptr->do_filter))
252   {
253      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
254         png_ptr->bit_depth < 8)
255         png_ptr->do_filter = PNG_FILTER_NONE;
256      else
257         png_ptr->do_filter = PNG_ALL_FILTERS;
258   }
259   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
260   {
261      if (png_ptr->do_filter != PNG_FILTER_NONE)
262         png_ptr->zlib_strategy = Z_FILTERED;
263      else
264         png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
265   }
266   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
267      png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
268   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
269      png_ptr->zlib_mem_level = 8;
270   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
271      png_ptr->zlib_window_bits = 15;
272   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
273      png_ptr->zlib_method = 8;
274   deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
275      png_ptr->zlib_method, png_ptr->zlib_window_bits,
276      png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
277   png_ptr->zstream.next_out = png_ptr->zbuf;
278   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
279
280   png_ptr->mode = PNG_HAVE_IHDR;
281}
282
283/* write the palette.  We are careful not to trust png_color to be in the
284 * correct order for PNG, so people can redefine it to any convenient
285 * structure.
286 */
287void
288png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
289{
290   png_uint_32 i;
291   png_colorp pal_ptr;
292   png_byte buf[3];
293
294   png_debug(1, "in png_write_PLTE\n");
295   if (num_pal == 0 || num_pal > 256)
296   {
297      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
298      {
299         png_error(png_ptr, "Invalid number of colors in palette");
300      }
301      else
302      {
303         png_warning(png_ptr, "Invalid number of colors in palette");
304         return;
305      }
306   }
307
308   png_ptr->num_palette = (png_uint_16)num_pal;
309   png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
310
311   png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3);
312   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
313   {
314      buf[0] = pal_ptr->red;
315      buf[1] = pal_ptr->green;
316      buf[2] = pal_ptr->blue;
317      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
318   }
319   png_write_chunk_end(png_ptr);
320   png_ptr->mode |= PNG_HAVE_PLTE;
321}
322
323/* write an IDAT chunk */
324void
325png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
326{
327   png_debug(1, "in png_write_IDAT\n");
328   png_write_chunk(png_ptr, png_IDAT, data, length);
329   png_ptr->mode |= PNG_HAVE_IDAT;
330}
331
332/* write an IEND chunk */
333void
334png_write_IEND(png_structp png_ptr)
335{
336   png_debug(1, "in png_write_IEND\n");
337   png_write_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
338   png_ptr->mode |= PNG_HAVE_IEND;
339}
340
341#if defined(PNG_WRITE_gAMA_SUPPORTED)
342/* write a gAMA chunk */
343void
344png_write_gAMA(png_structp png_ptr, double file_gamma)
345{
346   png_uint_32 igamma;
347   png_byte buf[4];
348
349   png_debug(1, "in png_write_gAMA\n");
350   /* file_gamma is saved in 1/1000000ths */
351   igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
352   png_save_uint_32(buf, igamma);
353   png_write_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
354}
355#endif
356
357#if defined(PNG_WRITE_sRGB_SUPPORTED)
358/* write a sRGB chunk */
359void
360png_write_sRGB(png_structp png_ptr, int srgb_intent)
361{
362   png_byte buf[1];
363
364   png_debug(1, "in png_write_sRGB\n");
365   if(srgb_intent >= PNG_sRGB_INTENT_LAST)
366         png_warning(png_ptr,
367            "Invalid sRGB rendering intent specified");
368   buf[0]=(png_byte)srgb_intent;
369   png_write_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
370}
371#endif
372
373#if defined(PNG_WRITE_sBIT_SUPPORTED)
374/* write the sBIT chunk */
375void
376png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
377{
378   png_byte buf[4];
379   png_size_t size;
380
381   png_debug(1, "in png_write_sBIT\n");
382   /* make sure we don't depend upon the order of PNG_COLOR_8 */
383   if (color_type & PNG_COLOR_MASK_COLOR)
384   {
385      png_byte maxbits;
386
387      maxbits = color_type==PNG_COLOR_TYPE_PALETTE ? 8:png_ptr->usr_bit_depth;
388      if (sbit->red == 0 || sbit->red > maxbits || 
389          sbit->green == 0 || sbit->green > maxbits || 
390          sbit->blue == 0 || sbit->blue > maxbits)
391      {
392         png_warning(png_ptr, "Invalid sBIT depth specified");
393         return;
394      }
395      buf[0] = sbit->red;
396      buf[1] = sbit->green;
397      buf[2] = sbit->blue;
398      size = 3;
399   }
400   else
401   {
402      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
403      {
404         png_warning(png_ptr, "Invalid sBIT depth specified");
405         return;
406      }
407      buf[0] = sbit->gray;
408      size = 1;
409   }
410
411   if (color_type & PNG_COLOR_MASK_ALPHA)
412   {
413      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
414      {
415         png_warning(png_ptr, "Invalid sBIT depth specified");
416         return;
417      }
418      buf[size++] = sbit->alpha;
419   }
420
421   png_write_chunk(png_ptr, png_sBIT, buf, size);
422}
423#endif
424
425#if defined(PNG_WRITE_cHRM_SUPPORTED)
426/* write the cHRM chunk */
427void
428png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
429   double red_x, double red_y, double green_x, double green_y,
430   double blue_x, double blue_y)
431{
432   png_uint_32 itemp;
433   png_byte buf[32];
434
435   png_debug(1, "in png_write_cHRM\n");
436   /* each value is saved int 1/1000000ths */
437   if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
438       white_x + white_y > 1.0)
439   {
440      png_warning(png_ptr, "Invalid cHRM white point specified");
441      return;
442   }
443   itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
444   png_save_uint_32(buf, itemp);
445   itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
446   png_save_uint_32(buf + 4, itemp);
447
448   if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
449       red_x + red_y > 1.0)
450   {
451      png_warning(png_ptr, "Invalid cHRM red point specified");
452      return;
453   }
454   itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
455   png_save_uint_32(buf + 8, itemp);
456   itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
457   png_save_uint_32(buf + 12, itemp);
458
459   if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
460       green_x + green_y > 1.0)
461   {
462      png_warning(png_ptr, "Invalid cHRM green point specified");
463      return;
464   }
465   itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
466   png_save_uint_32(buf + 16, itemp);
467   itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
468   png_save_uint_32(buf + 20, itemp);
469
470   if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
471       blue_x + blue_y > 1.0)
472   {
473      png_warning(png_ptr, "Invalid cHRM blue point specified");
474      return;
475   }
476   itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
477   png_save_uint_32(buf + 24, itemp);
478   itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
479   png_save_uint_32(buf + 28, itemp);
480
481   png_write_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
482}
483#endif
484
485#if defined(PNG_WRITE_tRNS_SUPPORTED)
486/* write the tRNS chunk */
487void
488png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
489   int num_trans, int color_type)
490{
491   png_byte buf[6];
492
493   png_debug(1, "in png_write_tRNS\n");
494   if (color_type == PNG_COLOR_TYPE_PALETTE)
495   {
496      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
497      {
498         png_warning(png_ptr,"Invalid number of transparent colors specified");
499         return;
500      }
501      /* write the chunk out as it is */
502      png_write_chunk(png_ptr, png_tRNS, trans, (png_size_t)num_trans);
503   }
504   else if (color_type == PNG_COLOR_TYPE_GRAY)
505   {
506      /* one 16 bit value */
507      png_save_uint_16(buf, tran->gray);
508      png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
509   }
510   else if (color_type == PNG_COLOR_TYPE_RGB)
511   {
512      /* three 16 bit values */
513      png_save_uint_16(buf, tran->red);
514      png_save_uint_16(buf + 2, tran->green);
515      png_save_uint_16(buf + 4, tran->blue);
516      png_write_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
517   }
518   else
519   {
520      png_warning(png_ptr, "Can't write tRNS with an alpha channel");
521   }
522}
523#endif
524
525#if defined(PNG_WRITE_bKGD_SUPPORTED)
526/* write the background chunk */
527void
528png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
529{
530   png_byte buf[6];
531
532   png_debug(1, "in png_write_bKGD\n");
533   if (color_type == PNG_COLOR_TYPE_PALETTE)
534   {
535      if (back->index > png_ptr->num_palette)
536      {
537         png_warning(png_ptr, "Invalid background palette index");
538         return;
539      }
540      buf[0] = back->index;
541      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
542   }
543   else if (color_type & PNG_COLOR_MASK_COLOR)
544   {
545      png_save_uint_16(buf, back->red);
546      png_save_uint_16(buf + 2, back->green);
547      png_save_uint_16(buf + 4, back->blue);
548      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
549   }
550   else
551   {
552      png_save_uint_16(buf, back->gray);
553      png_write_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
554   }
555}
556#endif
557
558#if defined(PNG_WRITE_hIST_SUPPORTED)
559/* write the histogram */
560void
561png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
562{
563   int i;
564   png_byte buf[3];
565
566   png_debug(1, "in png_write_hIST\n");
567   if (num_hist > (int)png_ptr->num_palette)
568   {
569      png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
570         png_ptr->num_palette);
571      png_warning(png_ptr, "Invalid number of histogram entries specified");
572      return;
573   }
574
575   png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
576   for (i = 0; i < num_hist; i++)
577   {
578      png_save_uint_16(buf, hist[i]);
579      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
580   }
581   png_write_chunk_end(png_ptr);
582}
583#endif
584
585#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) || \
586    defined(PNG_WRITE_pCAL_SUPPORTED)
587/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
588 * and if invalid, correct the keyword rather than discarding the entire
589 * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
590 * length, forbids leading or trailing whitespace, multiple internal spaces,
591 * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
592 *
593 * The new_key is allocated to hold the corrected keyword and must be freed
594 * by the calling routine.  This avoids problems with trying to write to
595 * static keywords without having to have duplicate copies of the strings.
596 */
597png_size_t
598png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
599{
600   png_size_t key_len;
601   png_charp kp, dp;
602   int kflag;
603
604   png_debug(1, "in png_check_keyword\n");
605   *new_key = NULL;
606
607   if (key == NULL || (key_len = png_strlen(key)) == 0)
608   {
609      png_chunk_warning(png_ptr, "zero length keyword");
610      return ((png_size_t)0);
611   }
612
613   png_debug1(2, "Keyword to be checked is '%s'\n", key);
614
615   *new_key = (png_charp)png_malloc(png_ptr, (png_uint_32)(key_len + 1));
616
617   /* Replace non-printing characters with a blank and print a warning */
618   for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
619   {
620      if (*kp < 0x20 || (*kp > 0x7E && (png_byte)*kp < 0xA1))
621      {
622#if !defined(PNG_NO_STDIO)
623         char msg[40];
624
625         sprintf(msg, "invalid keyword character 0x%02X", *kp);
626         png_chunk_warning(png_ptr, msg);
627#else
628         png_chunk_warning(png_ptr, "invalid character in keyword");
629#endif
630         *dp = ' ';
631      }
632      else
633      {
634         *dp = *kp;
635      }
636   }
637   *dp = '\0';
638
639   /* Remove any trailing white space. */
640   kp = *new_key + key_len - 1;
641   if (*kp == ' ')
642   {
643      png_chunk_warning(png_ptr, "trailing spaces removed from keyword");
644
645      while (*kp == ' ')
646      {
647        *(kp--) = '\0';
648        key_len--;
649      }
650   }
651
652   /* Remove any leading white space. */
653   kp = *new_key;
654   if (*kp == ' ')
655   {
656      png_chunk_warning(png_ptr, "leading spaces removed from keyword");
657
658      while (*kp == ' ')
659      {
660        kp++;
661        key_len--;
662      }
663   }
664
665   png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
666
667   /* Remove multiple internal spaces. */
668   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
669   {
670      if (*kp == ' ' && kflag == 0)
671      {
672         *(dp++) = *kp;
673         kflag = 1;
674      }
675      else if (*kp == ' ')
676      {
677         key_len--;
678      }
679      else
680      {
681         *(dp++) = *kp;
682         kflag = 0;
683      }
684   }
685   *dp = '\0';
686
687   if (key_len == 0)
688   {
689      png_chunk_warning(png_ptr, "zero length keyword");
690   }
691
692   if (key_len > 79)
693   {
694      png_chunk_warning(png_ptr, "keyword length must be 1 - 79 characters");
695      new_key[79] = '\0';
696      key_len = 79;
697   }
698
699   return (key_len);
700}
701#endif
702
703#if defined(PNG_WRITE_tEXt_SUPPORTED)
704/* write a tEXt chunk */
705void
706png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
707   png_size_t text_len)
708{
709   png_size_t key_len;
710   png_charp new_key;
711
712   png_debug(1, "in png_write_tEXt\n");
713   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
714   {
715      png_warning(png_ptr, "Empty keyword in tEXt chunk");
716      return;
717   }
718
719   if (text == NULL || *text == '\0')
720      text_len = 0;
721
722   /* make sure we include the 0 after the key */
723   png_write_chunk_start(png_ptr, png_tEXt, (png_uint_32)key_len+text_len+1);
724   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
725   if (text_len)
726      png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
727
728   png_write_chunk_end(png_ptr);
729   png_free(png_ptr, new_key);
730}
731#endif
732
733#if defined(PNG_WRITE_zTXt_SUPPORTED)
734/* write a compressed text chunk */
735void
736png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
737   png_size_t text_len, int compression)
738{
739   png_size_t key_len;
740   char buf[1];
741   png_charp new_key;
742   int i, ret;
743   png_charpp output_ptr = NULL; /* array of pointers to output */
744   int num_output_ptr = 0; /* number of output pointers used */
745   int max_output_ptr = 0; /* size of output_ptr */
746
747   png_debug(1, "in png_write_zTXt\n");
748
749   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
750   {
751      png_warning(png_ptr, "Empty keyword in zTXt chunk");
752      return;
753   }
754
755   if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
756   {
757      png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
758      png_free(png_ptr, new_key);
759      return;
760   }
761
762   png_free(png_ptr, new_key);
763
764   if (compression >= PNG_TEXT_COMPRESSION_LAST)
765   {
766#if !defined(PNG_NO_STDIO)
767      char msg[50];
768      sprintf(msg, "Unknown zTXt compression type %d", compression);
769      png_warning(png_ptr, msg);
770#else
771      png_warning(png_ptr, "Unknown zTXt compression type");
772#endif
773      compression = PNG_TEXT_COMPRESSION_zTXt;
774   }
775
776   /* We can't write the chunk until we find out how much data we have,
777    * which means we need to run the compressor first and save the
778    * output.  This shouldn't be a problem, as the vast majority of
779    * comments should be reasonable, but we will set up an array of
780    * malloc'd pointers to be sure.
781    *
782    * If we knew the application was well behaved, we could simplify this
783    * greatly by assuming we can always malloc an output buffer large
784    * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
785    * and malloc this directly.  The only time this would be a bad idea is
786    * if we can't malloc more than 64K and we have 64K of random input
787    * data, or if the input string is incredibly large (although this
788    * wouldn't cause a failure, just a slowdown due to swapping).
789    */
790
791   /* set up the compression buffers */
792   png_ptr->zstream.avail_in = (uInt)text_len;
793   png_ptr->zstream.next_in = (Bytef *)text;
794   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
795   png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
796
797   /* this is the same compression loop as in png_write_row() */
798   do
799   {
800      /* compress the data */
801      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
802      if (ret != Z_OK)
803      {
804         /* error */
805         if (png_ptr->zstream.msg != NULL)
806            png_error(png_ptr, png_ptr->zstream.msg);
807         else
808            png_error(png_ptr, "zlib error");
809      }
810      /* check to see if we need more room */
811      if (!png_ptr->zstream.avail_out && png_ptr->zstream.avail_in)
812      {
813         /* make sure the output array has room */
814         if (num_output_ptr >= max_output_ptr)
815         {
816            int old_max;
817
818            old_max = max_output_ptr;
819            max_output_ptr = num_output_ptr + 4;
820            if (output_ptr != NULL)
821            {
822               png_charpp old_ptr;
823
824               old_ptr = output_ptr;
825               output_ptr = (png_charpp)png_malloc(png_ptr,
826                  (png_uint_32)(max_output_ptr * sizeof (png_charpp)));
827               png_memcpy(output_ptr, old_ptr, old_max * sizeof (png_charp));
828               png_free(png_ptr, old_ptr);
829            }
830            else
831               output_ptr = (png_charpp)png_malloc(png_ptr,
832                  (png_uint_32)(max_output_ptr * sizeof (png_charp)));
833         }
834
835         /* save the data */
836         output_ptr[num_output_ptr] = (png_charp)png_malloc(png_ptr,
837            (png_uint_32)png_ptr->zbuf_size);
838         png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf,
839            png_ptr->zbuf_size);
840         num_output_ptr++;
841
842         /* and reset the buffer */
843         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
844         png_ptr->zstream.next_out = png_ptr->zbuf;
845      }
846   /* continue until we don't have any more to compress */
847   } while (png_ptr->zstream.avail_in);
848
849   /* finish the compression */
850   do
851   {
852      /* tell zlib we are finished */
853      ret = deflate(&png_ptr->zstream, Z_FINISH);
854      if (ret != Z_OK && ret != Z_STREAM_END)
855      {
856         /* we got an error */
857         if (png_ptr->zstream.msg != NULL)
858            png_error(png_ptr, png_ptr->zstream.msg);
859         else
860            png_error(png_ptr, "zlib error");
861      }
862
863      /* check to see if we need more room */
864      if (!(png_ptr->zstream.avail_out) && ret == Z_OK)
865      {
866         /* check to make sure our output array has room */
867         if (num_output_ptr >= max_output_ptr)
868         {
869            int old_max;
870
871            old_max = max_output_ptr;
872            max_output_ptr = num_output_ptr + 4;
873            if (output_ptr != NULL)
874            {
875               png_charpp old_ptr;
876
877               old_ptr = output_ptr;
878               /* This could be optimized to realloc() */
879               output_ptr = (png_charpp)png_malloc(png_ptr,
880                  (png_uint_32)(max_output_ptr * sizeof (png_charpp)));
881               png_memcpy(output_ptr, old_ptr, old_max * sizeof (png_charp));
882               png_free(png_ptr, old_ptr);
883            }
884            else
885               output_ptr = (png_charpp)png_malloc(png_ptr,
886                  (png_uint_32)(max_output_ptr * sizeof (png_charp)));
887         }
888
889         /* save off the data */
890         output_ptr[num_output_ptr] = (png_charp)png_malloc(png_ptr,
891            (png_uint_32)png_ptr->zbuf_size);
892         png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf,
893            png_ptr->zbuf_size);
894         num_output_ptr++;
895
896         /* and reset the buffer pointers */
897         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
898         png_ptr->zstream.next_out = png_ptr->zbuf;
899      }
900   } while (ret != Z_STREAM_END);
901
902   /* text length is number of buffers plus last buffer */
903   text_len = png_ptr->zbuf_size * num_output_ptr;
904   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
905      text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
906
907   /* write start of chunk */
908   png_write_chunk_start(png_ptr, png_zTXt, (png_uint_32)(key_len+text_len+2));
909   /* write key */
910   png_write_chunk_data(png_ptr, (png_bytep)key, key_len + 1);
911   buf[0] = (png_byte)compression;
912   /* write compression */
913   png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
914
915   /* write saved output buffers, if any */
916   for (i = 0; i < num_output_ptr; i++)
917   {
918      png_write_chunk_data(png_ptr,(png_bytep)output_ptr[i],png_ptr->zbuf_size);
919      png_free(png_ptr, output_ptr[i]);
920   }
921   if (max_output_ptr != 0)
922      png_free(png_ptr, output_ptr);
923   /* write anything left in zbuf */
924   if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
925      png_write_chunk_data(png_ptr, png_ptr->zbuf,
926         png_ptr->zbuf_size - png_ptr->zstream.avail_out);
927   /* close the chunk */
928   png_write_chunk_end(png_ptr);
929
930   /* reset zlib for another zTXt or the image data */
931   deflateReset(&png_ptr->zstream);
932}
933#endif
934
935
936#if defined(PNG_WRITE_oFFs_SUPPORTED)
937/* write the oFFs chunk */
938void
939png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset,
940   png_uint_32 y_offset,
941   int unit_type)
942{
943   png_byte buf[9];
944
945   png_debug(1, "in png_write_oFFs\n");
946   if (unit_type >= PNG_OFFSET_LAST)
947      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
948
949   png_save_uint_32(buf, x_offset);
950   png_save_uint_32(buf + 4, y_offset);
951   buf[8] = (png_byte)unit_type;
952
953   png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
954}
955#endif
956
957#if defined(PNG_WRITE_pCAL_SUPPORTED)
958/* write the pCAL chunk (png-scivis-19970203) */
959void
960png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
961   png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
962{
963   png_size_t purpose_len, units_len, total_len; 
964   png_uint_32p params_len;
965   png_byte buf[10];
966   png_charp new_purpose;
967   int i;
968
969   png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
970   if (type >= PNG_EQUATION_LAST)
971      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
972
973   purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
974   png_debug1(3, "pCAL purpose length = %d\n", purpose_len);
975   units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
976   png_debug1(3, "pCAL units length = %d\n", units_len);
977   total_len = purpose_len + units_len + 10;
978
979   params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
980      *sizeof(png_uint_32)));
981
982   /* Find the length of each parameter, making sure we don't count the
983      null terminator for the last parameter. */
984   for (i = 0; i < nparams; i++)
985   {
986      params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
987      png_debug2(3, "pCAL parameter %d length = %d\n", i, params_len[i]);
988      total_len += (png_size_t)params_len[i];
989   }
990
991   png_debug1(3, "pCAL total length = %d\n", total_len);
992   png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len);
993   png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len);
994   png_save_int_32(buf, X0);
995   png_save_int_32(buf + 4, X1);
996   buf[8] = (png_byte)type;
997   buf[9] = (png_byte)nparams;
998   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
999   png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
1000
1001   png_free(png_ptr, new_purpose);
1002
1003   for (i = 0; i < nparams; i++)
1004   {
1005      png_write_chunk_data(png_ptr, (png_bytep)params[i],
1006         (png_size_t)params_len[i]);
1007   }
1008
1009   png_free(png_ptr, params_len);
1010   png_write_chunk_end(png_ptr);
1011}
1012#endif
1013
1014#if defined(PNG_WRITE_pHYs_SUPPORTED)
1015/* write the pHYs chunk */
1016void
1017png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
1018   png_uint_32 y_pixels_per_unit,
1019   int unit_type)
1020{
1021   png_byte buf[9];
1022
1023   png_debug(1, "in png_write_pHYs\n");
1024   if (unit_type >= PNG_RESOLUTION_LAST)
1025      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
1026
1027   png_save_uint_32(buf, x_pixels_per_unit);
1028   png_save_uint_32(buf + 4, y_pixels_per_unit);
1029   buf[8] = (png_byte)unit_type;
1030
1031   png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
1032}
1033#endif
1034
1035#if defined(PNG_WRITE_tIME_SUPPORTED)
1036/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
1037 * or png_convert_from_time_t(), or fill in the structure yourself.
1038 */
1039void
1040png_write_tIME(png_structp png_ptr, png_timep mod_time)
1041{
1042   png_byte buf[7];
1043
1044   png_debug(1, "in png_write_tIME\n");
1045   if (mod_time->month  > 12 || mod_time->month  < 1 ||
1046       mod_time->day    > 31 || mod_time->day    < 1 ||
1047       mod_time->hour   > 23 || mod_time->second > 60)
1048   {
1049      png_warning(png_ptr, "Invalid time specified for tIME chunk");
1050      return;
1051   }
1052
1053   png_save_uint_16(buf, mod_time->year);
1054   buf[2] = mod_time->month;
1055   buf[3] = mod_time->day;
1056   buf[4] = mod_time->hour;
1057   buf[5] = mod_time->minute;
1058   buf[6] = mod_time->second;
1059
1060   png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
1061}
1062#endif
1063
1064/* initializes the row writing capability of libpng */
1065void
1066png_write_start_row(png_structp png_ptr)
1067{
1068   png_size_t buf_size;
1069
1070   png_debug(1, "in png_write_start_row\n");
1071   buf_size = (png_size_t)(((png_ptr->width * png_ptr->usr_channels *
1072                            png_ptr->usr_bit_depth + 7) >> 3) + 1);
1073
1074   /* set up row buffer */
1075   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
1076   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
1077
1078   /* set up filtering buffer, if using this filter */
1079   if (png_ptr->do_filter & PNG_FILTER_SUB)
1080   {
1081      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
1082         (png_ptr->rowbytes + 1));
1083      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
1084   }
1085
1086   /* We only need to keep the previous row if we are using one of these. */
1087   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
1088   {
1089     /* set up previous row buffer */
1090      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
1091      png_memset(png_ptr->prev_row, 0, buf_size);
1092
1093      if (png_ptr->do_filter & PNG_FILTER_UP)
1094      {
1095         png_ptr->up_row = (png_bytep )png_malloc(png_ptr,
1096            (png_ptr->rowbytes + 1));
1097         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
1098      }
1099
1100      if (png_ptr->do_filter & PNG_FILTER_AVG)
1101      {
1102         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
1103            (png_ptr->rowbytes + 1));
1104         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
1105      }
1106
1107      if (png_ptr->do_filter & PNG_FILTER_PAETH)
1108      {
1109         png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
1110            (png_ptr->rowbytes + 1));
1111         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
1112      }
1113   }
1114
1115#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1116   /* if interlaced, we need to set up width and height of pass */
1117   if (png_ptr->interlaced)
1118   {
1119      if (!(png_ptr->transformations & PNG_INTERLACE))
1120      {
1121         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
1122            png_pass_ystart[0]) / png_pass_yinc[0];
1123         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
1124            png_pass_start[0]) / png_pass_inc[0];
1125      }
1126      else
1127      {
1128         png_ptr->num_rows = png_ptr->height;
1129         png_ptr->usr_width = png_ptr->width;
1130      }
1131   }
1132   else
1133#endif
1134   {
1135      png_ptr->num_rows = png_ptr->height;
1136      png_ptr->usr_width = png_ptr->width;
1137   }
1138   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1139   png_ptr->zstream.next_out = png_ptr->zbuf;
1140}
1141
1142/* Internal use only.  Called when finished processing a row of data. */
1143void
1144png_write_finish_row(png_structp png_ptr)
1145{
1146   int ret;
1147
1148   png_debug(1, "in png_write_finish_row\n");
1149   /* next row */
1150   png_ptr->row_number++;
1151
1152   /* see if we are done */
1153   if (png_ptr->row_number < png_ptr->num_rows)
1154      return;
1155
1156#ifdef PNG_WRITE_INTERLACING_SUPPORTED
1157   /* if interlaced, go to next pass */
1158   if (png_ptr->interlaced)
1159   {
1160      png_ptr->row_number = 0;
1161      if (png_ptr->transformations & PNG_INTERLACE)
1162      {
1163         png_ptr->pass++;
1164      }
1165      else
1166      {
1167         /* loop until we find a non-zero width or height pass */
1168         do
1169         {
1170            png_ptr->pass++;
1171            if (png_ptr->pass >= 7)
1172               break;
1173            png_ptr->usr_width = (png_ptr->width +
1174               png_pass_inc[png_ptr->pass] - 1 -
1175               png_pass_start[png_ptr->pass]) /
1176               png_pass_inc[png_ptr->pass];
1177            png_ptr->num_rows = (png_ptr->height +
1178               png_pass_yinc[png_ptr->pass] - 1 -
1179               png_pass_ystart[png_ptr->pass]) /
1180               png_pass_yinc[png_ptr->pass];
1181            if (png_ptr->transformations & PNG_INTERLACE)
1182               break;
1183         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
1184
1185      }
1186
1187      /* reset the row above the image for the next pass */
1188      if (png_ptr->pass < 7)
1189      {
1190         if (png_ptr->prev_row != NULL)
1191            png_memset(png_ptr->prev_row, 0, 
1192               (png_size_t) (((png_uint_32)png_ptr->usr_channels *
1193               (png_uint_32)png_ptr->usr_bit_depth *
1194               png_ptr->width + 7) >> 3) + 1);
1195         return;
1196      }
1197   }
1198#endif
1199
1200   /* if we get here, we've just written the last row, so we need
1201      to flush the compressor */
1202   do
1203   {
1204      /* tell the compressor we are done */
1205      ret = deflate(&png_ptr->zstream, Z_FINISH);
1206      /* check for an error */
1207      if (ret != Z_OK && ret != Z_STREAM_END)
1208      {
1209         if (png_ptr->zstream.msg != NULL)
1210            png_error(png_ptr, png_ptr->zstream.msg);
1211         else
1212            png_error(png_ptr, "zlib error");
1213      }
1214      /* check to see if we need more room */
1215      if (!(png_ptr->zstream.avail_out) && ret == Z_OK)
1216      {
1217         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
1218         png_ptr->zstream.next_out = png_ptr->zbuf;
1219         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1220      }
1221   } while (ret != Z_STREAM_END);
1222
1223   /* write any extra space */
1224   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
1225   {
1226      png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
1227         png_ptr->zstream.avail_out);
1228   }
1229
1230   deflateReset(&png_ptr->zstream);
1231}
1232
1233#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
1234/* Pick out the correct pixels for the interlace pass.
1235 * The basic idea here is to go through the row with a source
1236 * pointer and a destination pointer (sp and dp), and copy the
1237 * correct pixels for the pass.  As the row gets compacted,
1238 * sp will always be >= dp, so we should never overwrite anything.
1239 * See the default: case for the easiest code to understand.
1240 */
1241void
1242png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
1243{
1244   png_debug(1, "in png_do_write_interlace\n");
1245   /* we don't have to do anything on the last pass (6) */
1246#if defined(PNG_USELESS_TESTS_SUPPORTED)
1247   if (row != NULL && row_info != NULL && pass < 6)
1248#else
1249   if (pass < 6)
1250#endif
1251   {
1252      /* each pixel depth is handled separately */
1253      switch (row_info->pixel_depth)
1254      {
1255         case 1:
1256         {
1257            png_bytep sp;
1258            png_bytep dp;
1259            int shift;
1260            int d;
1261            int value;
1262            png_uint_32 i;
1263            png_uint_32 row_width = row_info->width;
1264
1265            dp = row;
1266            d = 0;
1267            shift = 7;
1268            for (i = png_pass_start[pass]; i < row_width;
1269               i += png_pass_inc[pass])
1270            {
1271               sp = row + (png_size_t)(i >> 3);
1272               value = (int)(*sp >> (7 - (int)(i & 7))) & 0x1;
1273               d |= (value << shift);
1274
1275               if (shift == 0)
1276               {
1277                  shift = 7;
1278                  *dp++ = (png_byte)d;
1279                  d = 0;
1280               }
1281               else
1282                  shift--;
1283
1284            }
1285            if (shift != 7)
1286               *dp = (png_byte)d;
1287            break;
1288         }
1289         case 2:
1290         {
1291            png_bytep sp;
1292            png_bytep dp;
1293            int shift;
1294            int d;
1295            int value;
1296            png_uint_32 i;
1297            png_uint_32 row_width = row_info->width;
1298
1299            dp = row;
1300            shift = 6;
1301            d = 0;
1302            for (i = png_pass_start[pass]; i < row_width;
1303               i += png_pass_inc[pass])
1304            {
1305               sp = row + (png_size_t)(i >> 2);
1306               value = (*sp >> ((3 - (int)(i & 3)) << 1)) & 0x3;
1307               d |= (value << shift);
1308
1309               if (shift == 0)
1310               {
1311                  shift = 6;
1312                  *dp++ = (png_byte)d;
1313                  d = 0;
1314               }
1315               else
1316                  shift -= 2;
1317            }
1318            if (shift != 6)
1319                   *dp = (png_byte)d;
1320            break;
1321         }
1322         case 4:
1323         {
1324            png_bytep sp;
1325            png_bytep dp;
1326            int shift;
1327            int d;
1328            int value;
1329            png_uint_32 i;
1330            png_uint_32 row_width = row_info->width;
1331
1332            dp = row;
1333            shift = 4;
1334            d = 0;
1335            for (i = png_pass_start[pass]; i < row_width;
1336               i += png_pass_inc[pass])
1337            {
1338               sp = row + (png_size_t)(i >> 1);
1339               value = (*sp >> ((1 - (int)(i & 1)) << 2)) & 0xf;
1340               d |= (value << shift);
1341
1342               if (shift == 0)
1343               {
1344                  shift = 4;
1345                  *dp++ = (png_byte)d;
1346                  d = 0;
1347               }
1348               else
1349                  shift -= 4;
1350            }
1351            if (shift != 4)
1352               *dp = (png_byte)d;
1353            break;
1354         }
1355         default:
1356         {
1357            png_bytep sp;
1358            png_bytep dp;
1359            png_uint_32 i;
1360            png_uint_32 row_width = row_info->width;
1361            png_size_t pixel_bytes;
1362
1363            /* start at the beginning */
1364            dp = row;
1365            /* find out how many bytes each pixel takes up */
1366            pixel_bytes = (row_info->pixel_depth >> 3);
1367            /* loop through the row, only looking at the pixels that
1368               matter */
1369            for (i = png_pass_start[pass]; i < row_width;
1370               i += png_pass_inc[pass])
1371            {
1372               /* find out where the original pixel is */
1373               sp = row + (png_size_t)i * pixel_bytes;
1374               /* move the pixel */
1375               if (dp != sp)
1376                  png_memcpy(dp, sp, pixel_bytes);
1377               /* next pixel */
1378               dp += pixel_bytes;
1379            }
1380            break;
1381         }
1382      }
1383      /* set new row width */
1384      row_info->width = (row_info->width +
1385         png_pass_inc[pass] - 1 -
1386         png_pass_start[pass]) /
1387         png_pass_inc[pass];
1388         row_info->rowbytes = ((row_info->width *
1389            row_info->pixel_depth + 7) >> 3);
1390   }
1391}
1392#endif
1393
1394/* This filters the row, chooses which filter to use, if it has not already
1395 * been specified by the application, and then writes the row out with the
1396 * chosen filter.
1397 */
1398#define PNG_MAXSUM (~((png_uint_32)0) >> 1)
1399#define PNG_HISHIFT 10
1400#define PNG_LOMASK ((png_uint_32)0xffffL)
1401#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
1402void
1403png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
1404{
1405   png_bytep prev_row, best_row, row_buf;
1406   png_uint_32 mins, bpp;
1407   png_byte filter_to_do = png_ptr->do_filter;
1408   png_uint_32 row_bytes = row_info->rowbytes;
1409#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1410   int num_p_filters = (int)png_ptr->num_prev_filters;
1411#endif
1412
1413   png_debug(1, "in png_write_find_filter\n");
1414   /* find out how many bytes offset each pixel is */
1415   bpp = (row_info->pixel_depth + 7) / 8;
1416
1417   prev_row = png_ptr->prev_row;
1418   best_row = row_buf = png_ptr->row_buf;
1419   mins = PNG_MAXSUM;
1420
1421   /* The prediction method we use is to find which method provides the
1422    * smallest value when summing the absolute values of the distances
1423    * from zero, using anything >= 128 as negative numbers.  This is known
1424    * as the "minimum sum of absolute differences" heuristic.  Other
1425    * heuristics are the "weighted minimum sum of absolute differences"
1426    * (experimental and can in theory improve compression), and the "zlib
1427    * predictive" method (not implemented yet), which does test compressions
1428    * of lines using different filter methods, and then chooses the
1429    * (series of) filter(s) that give minimum compressed data size (VERY
1430    * computationally expensive).
1431    *
1432    * GRR 980525:  consider also
1433    *   (1) minimum sum of absolute differences from running average (i.e.,
1434    *       keep running sum of non-absolute differences & count of bytes)
1435    *       [track dispersion, too?  restart average if dispersion too large?]
1436    *  (1b) minimum sum of absolute differences from sliding average, probably
1437    *       with window size <= deflate window (usually 32K)
1438    *   (2) minimum sum of squared differences from zero or running average
1439    *       (i.e., ~ root-mean-square approach)
1440    */
1441
1442
1443   /* We don't need to test the 'no filter' case if this is the only filter
1444    * that has been chosen, as it doesn't actually do anything to the data.
1445    */
1446   if (filter_to_do & PNG_FILTER_NONE &&
1447       filter_to_do != PNG_FILTER_NONE)
1448   {
1449      png_bytep rp;
1450      png_uint_32 sum = 0;
1451      png_uint_32 i;
1452      int v;
1453
1454      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
1455      {
1456         v = *rp;
1457         sum += (v < 128) ? v : 256 - v;
1458      }
1459
1460#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1461      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1462      {
1463         png_uint_32 sumhi, sumlo;
1464         int j;
1465         sumlo = sum & PNG_LOMASK;
1466         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
1467
1468         /* Reduce the sum if we match any of the previous rows */
1469         for (j = 0; j < num_p_filters; j++)
1470         {
1471            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
1472            {
1473               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
1474                  PNG_WEIGHT_SHIFT;
1475               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
1476                  PNG_WEIGHT_SHIFT;
1477            }
1478         }
1479
1480         /* Factor in the cost of this filter (this is here for completeness,
1481          * but it makes no sense to have a "cost" for the NONE filter, as
1482          * it has the minimum possible computational cost - none).
1483          */
1484         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
1485            PNG_COST_SHIFT;
1486         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
1487            PNG_COST_SHIFT;
1488
1489         if (sumhi > PNG_HIMASK)
1490            sum = PNG_MAXSUM;
1491         else
1492            sum = (sumhi << PNG_HISHIFT) + sumlo;
1493      }
1494#endif
1495      mins = sum;
1496   }
1497
1498   /* sub filter */
1499   if (filter_to_do == PNG_FILTER_SUB)
1500   /* it's the only filter so no testing is needed */
1501   {
1502      png_bytep rp, lp, dp;
1503      png_uint_32 i;
1504      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
1505           i++, rp++, dp++)
1506      {
1507         *dp = *rp;
1508      }
1509      for (lp = row_buf + 1; i < row_bytes;
1510         i++, rp++, lp++, dp++)
1511      {
1512         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
1513      }
1514      best_row = png_ptr->sub_row;
1515   }
1516
1517   else if (filter_to_do & PNG_FILTER_SUB)
1518   {
1519      png_bytep rp, dp, lp;
1520      png_uint_32 sum = 0, lmins = mins;
1521      png_uint_32 i;
1522      int v;
1523
1524#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1525      /* We temporarily increase the "minimum sum" by the factor we
1526       * would reduce the sum of this filter, so that we can do the
1527       * early exit comparison without scaling the sum each time.
1528       */
1529      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1530      {
1531         int j;
1532         png_uint_32 lmhi, lmlo;
1533         lmlo = lmins & PNG_LOMASK;
1534         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
1535
1536         for (j = 0; j < num_p_filters; j++)
1537         {
1538            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
1539            {
1540               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
1541                  PNG_WEIGHT_SHIFT;
1542               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
1543                  PNG_WEIGHT_SHIFT;
1544            }
1545         }
1546
1547         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
1548            PNG_COST_SHIFT;
1549         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
1550            PNG_COST_SHIFT;
1551
1552         if (lmhi > PNG_HIMASK)
1553            lmins = PNG_MAXSUM;
1554         else
1555            lmins = (lmhi << PNG_HISHIFT) + lmlo;
1556      }
1557#endif
1558
1559      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
1560           i++, rp++, dp++)
1561      {
1562         v = *dp = *rp;
1563
1564         sum += (v < 128) ? v : 256 - v;
1565      }
1566      for (lp = row_buf + 1; i < row_info->rowbytes;
1567         i++, rp++, lp++, dp++)
1568      {
1569         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
1570
1571         sum += (v < 128) ? v : 256 - v;
1572
1573         if (sum > lmins)  /* We are already worse, don't continue. */
1574            break;
1575      }
1576
1577#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1578      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1579      {
1580         int j;
1581         png_uint_32 sumhi, sumlo;
1582         sumlo = sum & PNG_LOMASK;
1583         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
1584
1585         for (j = 0; j < num_p_filters; j++)
1586         {
1587            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
1588            {
1589               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
1590                  PNG_WEIGHT_SHIFT;
1591               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
1592                  PNG_WEIGHT_SHIFT;
1593            }
1594         }
1595
1596         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
1597            PNG_COST_SHIFT;
1598         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
1599            PNG_COST_SHIFT;
1600
1601         if (sumhi > PNG_HIMASK)
1602            sum = PNG_MAXSUM;
1603         else
1604            sum = (sumhi << PNG_HISHIFT) + sumlo;
1605      }
1606#endif
1607
1608      if (sum < mins)
1609      {
1610         mins = sum;
1611         best_row = png_ptr->sub_row;
1612      }
1613   }
1614
1615   /* up filter */
1616   if (filter_to_do == PNG_FILTER_UP)
1617   {
1618      png_bytep rp, dp, pp;
1619      png_uint_32 i;
1620
1621      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
1622           pp = prev_row + 1; i < row_bytes;
1623           i++, rp++, pp++, dp++)
1624      {
1625         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
1626      }
1627      best_row = png_ptr->up_row;
1628   }
1629
1630   else if (filter_to_do & PNG_FILTER_UP)
1631   {
1632      png_bytep rp, dp, pp;
1633      png_uint_32 sum = 0, lmins = mins;
1634      png_uint_32 i;
1635      int v;
1636
1637
1638#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1639      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1640      {
1641         int j;
1642         png_uint_32 lmhi, lmlo;
1643         lmlo = lmins & PNG_LOMASK;
1644         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
1645
1646         for (j = 0; j < num_p_filters; j++)
1647         {
1648            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
1649            {
1650               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
1651                  PNG_WEIGHT_SHIFT;
1652               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
1653                  PNG_WEIGHT_SHIFT;
1654            }
1655         }
1656
1657         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
1658            PNG_COST_SHIFT;
1659         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
1660            PNG_COST_SHIFT;
1661
1662         if (lmhi > PNG_HIMASK)
1663            lmins = PNG_MAXSUM;
1664         else
1665            lmins = (lmhi << PNG_HISHIFT) + lmlo;
1666      }
1667#endif
1668
1669      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
1670           pp = prev_row + 1; i < row_bytes; i++)
1671      {
1672         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
1673
1674         sum += (v < 128) ? v : 256 - v;
1675
1676         if (sum > lmins)  /* We are already worse, don't continue. */
1677            break;
1678      }
1679
1680#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1681      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1682      {
1683         int j;
1684         png_uint_32 sumhi, sumlo;
1685         sumlo = sum & PNG_LOMASK;
1686         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
1687
1688         for (j = 0; j < num_p_filters; j++)
1689         {
1690            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
1691            {
1692               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
1693                  PNG_WEIGHT_SHIFT;
1694               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
1695                  PNG_WEIGHT_SHIFT;
1696            }
1697         }
1698
1699         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
1700            PNG_COST_SHIFT;
1701         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
1702            PNG_COST_SHIFT;
1703
1704         if (sumhi > PNG_HIMASK)
1705            sum = PNG_MAXSUM;
1706         else
1707            sum = (sumhi << PNG_HISHIFT) + sumlo;
1708      }
1709#endif
1710
1711      if (sum < mins)
1712      {
1713         mins = sum;
1714         best_row = png_ptr->up_row;
1715      }
1716   }
1717
1718   /* avg filter */
1719   if (filter_to_do == PNG_FILTER_AVG)
1720   {
1721      png_bytep rp, dp, pp, lp;
1722      png_uint_32 i;
1723      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
1724           pp = prev_row + 1; i < bpp; i++)
1725      {
1726         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
1727      }
1728      for (lp = row_buf + 1; i < row_bytes; i++)
1729      {
1730         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
1731                 & 0xff);
1732      }
1733      best_row = png_ptr->avg_row;
1734   }
1735
1736   else if (filter_to_do & PNG_FILTER_AVG)
1737   {
1738      png_bytep rp, dp, pp, lp;
1739      png_uint_32 sum = 0, lmins = mins;
1740      png_uint_32 i;
1741      int v;
1742
1743#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1744      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1745      {
1746         int j;
1747         png_uint_32 lmhi, lmlo;
1748         lmlo = lmins & PNG_LOMASK;
1749         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
1750
1751         for (j = 0; j < num_p_filters; j++)
1752         {
1753            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
1754            {
1755               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
1756                  PNG_WEIGHT_SHIFT;
1757               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
1758                  PNG_WEIGHT_SHIFT;
1759            }
1760         }
1761
1762         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
1763            PNG_COST_SHIFT;
1764         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
1765            PNG_COST_SHIFT;
1766
1767         if (lmhi > PNG_HIMASK)
1768            lmins = PNG_MAXSUM;
1769         else
1770            lmins = (lmhi << PNG_HISHIFT) + lmlo;
1771      }
1772#endif
1773
1774      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
1775           pp = prev_row + 1; i < bpp; i++)
1776      {
1777         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
1778
1779         sum += (v < 128) ? v : 256 - v;
1780      }
1781      for (lp = row_buf + 1; i < row_bytes; i++)
1782      {
1783         v = *dp++ = 
1784          (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
1785
1786         sum += (v < 128) ? v : 256 - v;
1787
1788         if (sum > lmins)  /* We are already worse, don't continue. */
1789            break;
1790      }
1791
1792#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1793      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1794      {
1795         int j;
1796         png_uint_32 sumhi, sumlo;
1797         sumlo = sum & PNG_LOMASK;
1798         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
1799
1800         for (j = 0; j < num_p_filters; j++)
1801         {
1802            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
1803            {
1804               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
1805                  PNG_WEIGHT_SHIFT;
1806               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
1807                  PNG_WEIGHT_SHIFT;
1808            }
1809         }
1810
1811         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
1812            PNG_COST_SHIFT;
1813         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
1814            PNG_COST_SHIFT;
1815
1816         if (sumhi > PNG_HIMASK)
1817            sum = PNG_MAXSUM;
1818         else
1819            sum = (sumhi << PNG_HISHIFT) + sumlo;
1820      }
1821#endif
1822
1823      if (sum < mins)
1824      {
1825         mins = sum;
1826         best_row = png_ptr->avg_row;
1827      }
1828   }
1829
1830   /* Paeth filter */
1831   if (filter_to_do == PNG_FILTER_PAETH)
1832   {
1833      png_bytep rp, dp, pp, cp, lp;
1834      png_uint_32 i;
1835      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
1836           pp = prev_row + 1; i < bpp; i++)
1837      {
1838         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
1839      }
1840
1841      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
1842      {
1843         int a, b, c, pa, pb, pc, p;
1844
1845         b = *pp++;
1846         c = *cp++;
1847         a = *lp++;
1848
1849         p = b - c;
1850         pc = a - c;
1851
1852#ifdef PNG_USE_ABS
1853         pa = abs(p);
1854         pb = abs(pc);
1855         pc = abs(p + pc);
1856#else
1857         pa = p < 0 ? -p : p;
1858         pb = pc < 0 ? -pc : pc;
1859         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
1860#endif
1861
1862         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
1863
1864         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
1865      }
1866      best_row = png_ptr->paeth_row;
1867   }
1868
1869   else if (filter_to_do & PNG_FILTER_PAETH)
1870   {
1871      png_bytep rp, dp, pp, cp, lp;
1872      png_uint_32 sum = 0, lmins = mins;
1873      png_uint_32 i;
1874      int v;
1875
1876#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1877      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1878      {
1879         int j;
1880         png_uint_32 lmhi, lmlo;
1881         lmlo = lmins & PNG_LOMASK;
1882         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
1883
1884         for (j = 0; j < num_p_filters; j++)
1885         {
1886            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
1887            {
1888               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
1889                  PNG_WEIGHT_SHIFT;
1890               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
1891                  PNG_WEIGHT_SHIFT;
1892            }
1893         }
1894
1895         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
1896            PNG_COST_SHIFT;
1897         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
1898            PNG_COST_SHIFT;
1899
1900         if (lmhi > PNG_HIMASK)
1901            lmins = PNG_MAXSUM;
1902         else
1903            lmins = (lmhi << PNG_HISHIFT) + lmlo;
1904      }
1905#endif
1906
1907      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
1908           pp = prev_row + 1; i < bpp; i++)
1909      {
1910         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
1911
1912         sum += (v < 128) ? v : 256 - v;
1913      }
1914
1915      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
1916      {
1917         int a, b, c, pa, pb, pc, p;
1918
1919         b = *pp++;
1920         c = *cp++;
1921         a = *lp++;
1922
1923#ifndef PNG_SLOW_PAETH
1924         p = b - c;
1925         pc = a - c;
1926#ifdef PNG_USE_ABS
1927         pa = abs(p);
1928         pb = abs(pc);
1929         pc = abs(p + pc);
1930#else
1931         pa = p < 0 ? -p : p;
1932         pb = pc < 0 ? -pc : pc;
1933         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
1934#endif
1935         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
1936#else /* PNG_SLOW_PAETH */
1937         p = a + b - c;
1938         pa = abs(p - a);
1939         pb = abs(p - b);
1940         pc = abs(p - c);
1941         if (pa <= pb && pa <= pc)
1942            p = a;
1943         else if (pb <= pc)
1944            p = b;
1945         else
1946            p = c;
1947#endif /* PNG_SLOW_PAETH */
1948
1949         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
1950
1951         sum += (v < 128) ? v : 256 - v;
1952
1953         if (sum > lmins)  /* We are already worse, don't continue. */
1954            break;
1955      }
1956
1957#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1958      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
1959      {
1960         int j;
1961         png_uint_32 sumhi, sumlo;
1962         sumlo = sum & PNG_LOMASK;
1963         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
1964
1965         for (j = 0; j < num_p_filters; j++)
1966         {
1967            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
1968            {
1969               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
1970                  PNG_WEIGHT_SHIFT;
1971               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
1972                  PNG_WEIGHT_SHIFT;
1973            }
1974         }
1975
1976         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
1977            PNG_COST_SHIFT;
1978         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
1979            PNG_COST_SHIFT;
1980
1981         if (sumhi > PNG_HIMASK)
1982            sum = PNG_MAXSUM;
1983         else
1984            sum = (sumhi << PNG_HISHIFT) + sumlo;
1985      }
1986#endif
1987
1988      if (sum < mins)
1989      {
1990         best_row = png_ptr->paeth_row;
1991      }
1992   }
1993
1994   /* Do the actual writing of the filtered row data from the chosen filter. */
1995
1996   png_write_filtered_row(png_ptr, best_row);
1997
1998#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
1999   /* Save the type of filter we picked this time for future calculations */
2000   if (png_ptr->num_prev_filters > 0)
2001   {
2002      int j;
2003      for (j = 1; j < num_p_filters; j++)
2004      {
2005         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
2006      }
2007      png_ptr->prev_filters[j] = best_row[0];
2008   }
2009#endif
2010}
2011
2012
2013/* Do the actual writing of a previously filtered row. */
2014void
2015png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
2016{
2017   png_debug(1, "in png_write_filtered_row\n");
2018   png_debug1(2, "filter = %d\n", filtered_row[0]);
2019   /* set up the zlib input buffer */
2020   png_ptr->zstream.next_in = filtered_row;
2021   png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
2022   /* repeat until we have compressed all the data */
2023   do
2024   {
2025      int ret; /* return of zlib */
2026
2027      /* compress the data */
2028      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
2029      /* check for compression errors */
2030      if (ret != Z_OK)
2031      {
2032         if (png_ptr->zstream.msg != NULL)
2033            png_error(png_ptr, png_ptr->zstream.msg);
2034         else
2035            png_error(png_ptr, "zlib error");
2036      }
2037
2038      /* see if it is time to write another IDAT */
2039      if (!(png_ptr->zstream.avail_out))
2040      {
2041         /* write the IDAT and reset the zlib output buffer */
2042         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
2043         png_ptr->zstream.next_out = png_ptr->zbuf;
2044         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2045      }
2046   /* repeat until all data has been compressed */
2047   } while (png_ptr->zstream.avail_in);
2048
2049   /* swap the current and previous rows */
2050   if (png_ptr->prev_row != NULL)
2051   {
2052      png_bytep tptr;
2053
2054      tptr = png_ptr->prev_row;
2055      png_ptr->prev_row = png_ptr->row_buf;
2056      png_ptr->row_buf = tptr;
2057   }
2058
2059   /* finish row - updates counters and flushes zlib if last row */
2060   png_write_finish_row(png_ptr);
2061
2062#if defined(PNG_WRITE_FLUSH_SUPPORTED)
2063   png_ptr->flush_rows++;
2064
2065   if (png_ptr->flush_dist > 0 &&
2066       png_ptr->flush_rows >= png_ptr->flush_dist)
2067   {
2068      png_write_flush(png_ptr);
2069   }
2070#endif /* PNG_WRITE_FLUSH_SUPPORTED */
2071}
Note: See TracBrowser for help on using the repository browser.