syslinux-3.08-2 sources from FC4
[bootcd.git] / syslinux / com32 / lib / libpng / pngrtran.c
1
2 /* pngrtran.c - transforms the data in a row for PNG readers
3  *
4  * libpng version  1.2.8 - December 3, 2004
5  * For conditions of distribution and use, see copyright notice in png.h
6  * Copyright (c) 1998-2004 Glenn Randers-Pehrson
7  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9  *
10  * This file contains functions optionally called by an application
11  * in order to tell libpng how to handle data when reading a PNG.
12  * Transformations that are used in both reading and writing are
13  * in pngtrans.c.
14  */
15
16 #define PNG_INTERNAL
17 #include "png.h"
18
19 /* Set the action on getting a CRC error for an ancillary or critical chunk. */
20 void PNGAPI
21 png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
22 {
23    png_debug(1, "in png_set_crc_action\n");
24    /* Tell libpng how we react to CRC errors in critical chunks */
25    switch (crit_action)
26    {
27       case PNG_CRC_NO_CHANGE:                        /* leave setting as is */
28          break;
29       case PNG_CRC_WARN_USE:                               /* warn/use data */
30          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
31          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
32          break;
33       case PNG_CRC_QUIET_USE:                             /* quiet/use data */
34          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
35          png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
36                            PNG_FLAG_CRC_CRITICAL_IGNORE;
37          break;
38       case PNG_CRC_WARN_DISCARD:    /* not a valid action for critical data */
39          png_warning(png_ptr, "Can't discard critical data on CRC error.");
40       case PNG_CRC_ERROR_QUIT:                                /* error/quit */
41       case PNG_CRC_DEFAULT:
42       default:
43          png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
44          break;
45    }
46
47    switch (ancil_action)
48    {
49       case PNG_CRC_NO_CHANGE:                       /* leave setting as is */
50          break;
51       case PNG_CRC_WARN_USE:                              /* warn/use data */
52          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
53          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
54          break;
55       case PNG_CRC_QUIET_USE:                            /* quiet/use data */
56          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
57          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
58                            PNG_FLAG_CRC_ANCILLARY_NOWARN;
59          break;
60       case PNG_CRC_ERROR_QUIT:                               /* error/quit */
61          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
62          png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
63          break;
64       case PNG_CRC_WARN_DISCARD:                      /* warn/discard data */
65       case PNG_CRC_DEFAULT:
66       default:
67          png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
68          break;
69    }
70 }
71
72 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
73     defined(PNG_FLOATING_POINT_SUPPORTED)
74 /* handle alpha and tRNS via a background color */
75 void PNGAPI
76 png_set_background(png_structp png_ptr,
77    png_color_16p background_color, int background_gamma_code,
78    int need_expand, double background_gamma)
79 {
80    png_debug(1, "in png_set_background\n");
81    if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
82    {
83       png_warning(png_ptr, "Application must supply a known background gamma");
84       return;
85    }
86
87    png_ptr->transformations |= PNG_BACKGROUND;
88    png_memcpy(&(png_ptr->background), background_color,
89       png_sizeof(png_color_16));
90    png_ptr->background_gamma = (float)background_gamma;
91    png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
92    png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
93
94    /* Note:  if need_expand is set and color_type is either RGB or RGB_ALPHA
95     * (in which case need_expand is superfluous anyway), the background color
96     * might actually be gray yet not be flagged as such. This is not a problem
97     * for the current code, which uses PNG_BACKGROUND_IS_GRAY only to
98     * decide when to do the png_do_gray_to_rgb() transformation.
99     */
100    if ((need_expand && !(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) ||
101        (!need_expand && background_color->red == background_color->green &&
102         background_color->red == background_color->blue))
103       png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
104 }
105 #endif
106
107 #if defined(PNG_READ_16_TO_8_SUPPORTED)
108 /* strip 16 bit depth files to 8 bit depth */
109 void PNGAPI
110 png_set_strip_16(png_structp png_ptr)
111 {
112    png_debug(1, "in png_set_strip_16\n");
113    png_ptr->transformations |= PNG_16_TO_8;
114 }
115 #endif
116
117 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
118 void PNGAPI
119 png_set_strip_alpha(png_structp png_ptr)
120 {
121    png_debug(1, "in png_set_strip_alpha\n");
122    png_ptr->flags |= PNG_FLAG_STRIP_ALPHA;
123 }
124 #endif
125
126 #if defined(PNG_READ_DITHER_SUPPORTED)
127 /* Dither file to 8 bit.  Supply a palette, the current number
128  * of elements in the palette, the maximum number of elements
129  * allowed, and a histogram if possible.  If the current number
130  * of colors is greater then the maximum number, the palette will be
131  * modified to fit in the maximum number.  "full_dither" indicates
132  * whether we need a dithering cube set up for RGB images, or if we
133  * simply are reducing the number of colors in a paletted image.
134  */
135
136 typedef struct png_dsort_struct
137 {
138    struct png_dsort_struct FAR * next;
139    png_byte left;
140    png_byte right;
141 } png_dsort;
142 typedef png_dsort FAR *       png_dsortp;
143 typedef png_dsort FAR * FAR * png_dsortpp;
144
145 void PNGAPI
146 png_set_dither(png_structp png_ptr, png_colorp palette,
147    int num_palette, int maximum_colors, png_uint_16p histogram,
148    int full_dither)
149 {
150    png_debug(1, "in png_set_dither\n");
151    png_ptr->transformations |= PNG_DITHER;
152
153    if (!full_dither)
154    {
155       int i;
156
157       png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
158          (png_uint_32)(num_palette * png_sizeof (png_byte)));
159       for (i = 0; i < num_palette; i++)
160          png_ptr->dither_index[i] = (png_byte)i;
161    }
162
163    if (num_palette > maximum_colors)
164    {
165       if (histogram != NULL)
166       {
167          /* This is easy enough, just throw out the least used colors.
168             Perhaps not the best solution, but good enough. */
169
170          int i;
171
172          /* initialize an array to sort colors */
173          png_ptr->dither_sort = (png_bytep)png_malloc(png_ptr,
174             (png_uint_32)(num_palette * png_sizeof (png_byte)));
175
176          /* initialize the dither_sort array */
177          for (i = 0; i < num_palette; i++)
178             png_ptr->dither_sort[i] = (png_byte)i;
179
180          /* Find the least used palette entries by starting a
181             bubble sort, and running it until we have sorted
182             out enough colors.  Note that we don't care about
183             sorting all the colors, just finding which are
184             least used. */
185
186          for (i = num_palette - 1; i >= maximum_colors; i--)
187          {
188             int done; /* to stop early if the list is pre-sorted */
189             int j;
190
191             done = 1;
192             for (j = 0; j < i; j++)
193             {
194                if (histogram[png_ptr->dither_sort[j]]
195                    < histogram[png_ptr->dither_sort[j + 1]])
196                {
197                   png_byte t;
198
199                   t = png_ptr->dither_sort[j];
200                   png_ptr->dither_sort[j] = png_ptr->dither_sort[j + 1];
201                   png_ptr->dither_sort[j + 1] = t;
202                   done = 0;
203                }
204             }
205             if (done)
206                break;
207          }
208
209          /* swap the palette around, and set up a table, if necessary */
210          if (full_dither)
211          {
212             int j = num_palette;
213
214             /* put all the useful colors within the max, but don't
215                move the others */
216             for (i = 0; i < maximum_colors; i++)
217             {
218                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
219                {
220                   do
221                      j--;
222                   while ((int)png_ptr->dither_sort[j] >= maximum_colors);
223                   palette[i] = palette[j];
224                }
225             }
226          }
227          else
228          {
229             int j = num_palette;
230
231             /* move all the used colors inside the max limit, and
232                develop a translation table */
233             for (i = 0; i < maximum_colors; i++)
234             {
235                /* only move the colors we need to */
236                if ((int)png_ptr->dither_sort[i] >= maximum_colors)
237                {
238                   png_color tmp_color;
239
240                   do
241                      j--;
242                   while ((int)png_ptr->dither_sort[j] >= maximum_colors);
243
244                   tmp_color = palette[j];
245                   palette[j] = palette[i];
246                   palette[i] = tmp_color;
247                   /* indicate where the color went */
248                   png_ptr->dither_index[j] = (png_byte)i;
249                   png_ptr->dither_index[i] = (png_byte)j;
250                }
251             }
252
253             /* find closest color for those colors we are not using */
254             for (i = 0; i < num_palette; i++)
255             {
256                if ((int)png_ptr->dither_index[i] >= maximum_colors)
257                {
258                   int min_d, k, min_k, d_index;
259
260                   /* find the closest color to one we threw out */
261                   d_index = png_ptr->dither_index[i];
262                   min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
263                   for (k = 1, min_k = 0; k < maximum_colors; k++)
264                   {
265                      int d;
266
267                      d = PNG_COLOR_DIST(palette[d_index], palette[k]);
268
269                      if (d < min_d)
270                      {
271                         min_d = d;
272                         min_k = k;
273                      }
274                   }
275                   /* point to closest color */
276                   png_ptr->dither_index[i] = (png_byte)min_k;
277                }
278             }
279          }
280          png_free(png_ptr, png_ptr->dither_sort);
281          png_ptr->dither_sort=NULL;
282       }
283       else
284       {
285          /* This is much harder to do simply (and quickly).  Perhaps
286             we need to go through a median cut routine, but those
287             don't always behave themselves with only a few colors
288             as input.  So we will just find the closest two colors,
289             and throw out one of them (chosen somewhat randomly).
290             [We don't understand this at all, so if someone wants to
291              work on improving it, be our guest - AED, GRP]
292             */
293          int i;
294          int max_d;
295          int num_new_palette;
296          png_dsortp t;
297          png_dsortpp hash;
298
299          t=NULL;
300
301          /* initialize palette index arrays */
302          png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
303             (png_uint_32)(num_palette * png_sizeof (png_byte)));
304          png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
305             (png_uint_32)(num_palette * png_sizeof (png_byte)));
306
307          /* initialize the sort array */
308          for (i = 0; i < num_palette; i++)
309          {
310             png_ptr->index_to_palette[i] = (png_byte)i;
311             png_ptr->palette_to_index[i] = (png_byte)i;
312          }
313
314          hash = (png_dsortpp)png_malloc(png_ptr, (png_uint_32)(769 *
315             png_sizeof (png_dsortp)));
316          for (i = 0; i < 769; i++)
317             hash[i] = NULL;
318 /*         png_memset(hash, 0, 769 * png_sizeof (png_dsortp)); */
319
320          num_new_palette = num_palette;
321
322          /* initial wild guess at how far apart the farthest pixel
323             pair we will be eliminating will be.  Larger
324             numbers mean more areas will be allocated, Smaller
325             numbers run the risk of not saving enough data, and
326             having to do this all over again.
327
328             I have not done extensive checking on this number.
329             */
330          max_d = 96;
331
332          while (num_new_palette > maximum_colors)
333          {
334             for (i = 0; i < num_new_palette - 1; i++)
335             {
336                int j;
337
338                for (j = i + 1; j < num_new_palette; j++)
339                {
340                   int d;
341
342                   d = PNG_COLOR_DIST(palette[i], palette[j]);
343
344                   if (d <= max_d)
345                   {
346
347                      t = (png_dsortp)png_malloc_warn(png_ptr,
348                          (png_uint_32)(png_sizeof(png_dsort)));
349                      if (t == NULL)
350                          break;
351                      t->next = hash[d];
352                      t->left = (png_byte)i;
353                      t->right = (png_byte)j;
354                      hash[d] = t;
355                   }
356                }
357                if (t == NULL)
358                   break;
359             }
360
361             if (t != NULL)
362             for (i = 0; i <= max_d; i++)
363             {
364                if (hash[i] != NULL)
365                {
366                   png_dsortp p;
367
368                   for (p = hash[i]; p; p = p->next)
369                   {
370                      if ((int)png_ptr->index_to_palette[p->left]
371                         < num_new_palette &&
372                         (int)png_ptr->index_to_palette[p->right]
373                         < num_new_palette)
374                      {
375                         int j, next_j;
376
377                         if (num_new_palette & 0x01)
378                         {
379                            j = p->left;
380                            next_j = p->right;
381                         }
382                         else
383                         {
384                            j = p->right;
385                            next_j = p->left;
386                         }
387
388                         num_new_palette--;
389                         palette[png_ptr->index_to_palette[j]]
390                           = palette[num_new_palette];
391                         if (!full_dither)
392                         {
393                            int k;
394
395                            for (k = 0; k < num_palette; k++)
396                            {
397                               if (png_ptr->dither_index[k] ==
398                                  png_ptr->index_to_palette[j])
399                                  png_ptr->dither_index[k] =
400                                     png_ptr->index_to_palette[next_j];
401                               if ((int)png_ptr->dither_index[k] ==
402                                  num_new_palette)
403                                  png_ptr->dither_index[k] =
404                                     png_ptr->index_to_palette[j];
405                            }
406                         }
407
408                         png_ptr->index_to_palette[png_ptr->palette_to_index
409                            [num_new_palette]] = png_ptr->index_to_palette[j];
410                         png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
411                            = png_ptr->palette_to_index[num_new_palette];
412
413                         png_ptr->index_to_palette[j] = (png_byte)num_new_palette;
414                         png_ptr->palette_to_index[num_new_palette] = (png_byte)j;
415                      }
416                      if (num_new_palette <= maximum_colors)
417                         break;
418                   }
419                   if (num_new_palette <= maximum_colors)
420                      break;
421                }
422             }
423
424             for (i = 0; i < 769; i++)
425             {
426                if (hash[i] != NULL)
427                {
428                   png_dsortp p = hash[i];
429                   while (p)
430                   {
431                      t = p->next;
432                      png_free(png_ptr, p);
433                      p = t;
434                   }
435                }
436                hash[i] = 0;
437             }
438             max_d += 96;
439          }
440          png_free(png_ptr, hash);
441          png_free(png_ptr, png_ptr->palette_to_index);
442          png_free(png_ptr, png_ptr->index_to_palette);
443          png_ptr->palette_to_index=NULL;
444          png_ptr->index_to_palette=NULL;
445       }
446       num_palette = maximum_colors;
447    }
448    if (png_ptr->palette == NULL)
449    {
450       png_ptr->palette = palette;
451    }
452    png_ptr->num_palette = (png_uint_16)num_palette;
453
454    if (full_dither)
455    {
456       int i;
457       png_bytep distance;
458       int total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
459          PNG_DITHER_BLUE_BITS;
460       int num_red = (1 << PNG_DITHER_RED_BITS);
461       int num_green = (1 << PNG_DITHER_GREEN_BITS);
462       int num_blue = (1 << PNG_DITHER_BLUE_BITS);
463       png_size_t num_entries = ((png_size_t)1 << total_bits);
464
465       png_ptr->palette_lookup = (png_bytep )png_malloc(png_ptr,
466          (png_uint_32)(num_entries * png_sizeof (png_byte)));
467
468       png_memset(png_ptr->palette_lookup, 0, num_entries *
469          png_sizeof (png_byte));
470
471       distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
472          png_sizeof(png_byte)));
473
474       png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
475
476       for (i = 0; i < num_palette; i++)
477       {
478          int ir, ig, ib;
479          int r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
480          int g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
481          int b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
482
483          for (ir = 0; ir < num_red; ir++)
484          {
485             /* int dr = abs(ir - r); */
486             int dr = ((ir > r) ? ir - r : r - ir);
487             int index_r = (ir << (PNG_DITHER_BLUE_BITS + PNG_DITHER_GREEN_BITS));
488
489             for (ig = 0; ig < num_green; ig++)
490             {
491                /* int dg = abs(ig - g); */
492                int dg = ((ig > g) ? ig - g : g - ig);
493                int dt = dr + dg;
494                int dm = ((dr > dg) ? dr : dg);
495                int index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
496
497                for (ib = 0; ib < num_blue; ib++)
498                {
499                   int d_index = index_g | ib;
500                   /* int db = abs(ib - b); */
501                   int db = ((ib > b) ? ib - b : b - ib);
502                   int dmax = ((dm > db) ? dm : db);
503                   int d = dmax + dt + db;
504
505                   if (d < (int)distance[d_index])
506                   {
507                      distance[d_index] = (png_byte)d;
508                      png_ptr->palette_lookup[d_index] = (png_byte)i;
509                   }
510                }
511             }
512          }
513       }
514
515       png_free(png_ptr, distance);
516    }
517 }
518 #endif
519
520 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
521 /* Transform the image from the file_gamma to the screen_gamma.  We
522  * only do transformations on images where the file_gamma and screen_gamma
523  * are not close reciprocals, otherwise it slows things down slightly, and
524  * also needlessly introduces small errors.
525  *
526  * We will turn off gamma transformation later if no semitransparent entries
527  * are present in the tRNS array for palette images.  We can't do it here
528  * because we don't necessarily have the tRNS chunk yet.
529  */
530 void PNGAPI
531 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
532 {
533    png_debug(1, "in png_set_gamma\n");
534    if ((fabs(scrn_gamma * file_gamma - 1.0) > PNG_GAMMA_THRESHOLD) ||
535        (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) ||
536        (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
537      png_ptr->transformations |= PNG_GAMMA;
538    png_ptr->gamma = (float)file_gamma;
539    png_ptr->screen_gamma = (float)scrn_gamma;
540 }
541 #endif
542
543 #if defined(PNG_READ_EXPAND_SUPPORTED)
544 /* Expand paletted images to RGB, expand grayscale images of
545  * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
546  * to alpha channels.
547  */
548 void PNGAPI
549 png_set_expand(png_structp png_ptr)
550 {
551    png_debug(1, "in png_set_expand\n");
552    png_ptr->transformations |= PNG_EXPAND;
553 }
554
555 /* GRR 19990627:  the following three functions currently are identical
556  *  to png_set_expand().  However, it is entirely reasonable that someone
557  *  might wish to expand an indexed image to RGB but *not* expand a single,
558  *  fully transparent palette entry to a full alpha channel--perhaps instead
559  *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
560  *  the transparent color with a particular RGB value, or drop tRNS entirely.
561  *  IOW, a future version of the library may make the transformations flag
562  *  a bit more fine-grained, with separate bits for each of these three
563  *  functions.
564  *
565  *  More to the point, these functions make it obvious what libpng will be
566  *  doing, whereas "expand" can (and does) mean any number of things.
567  */
568
569 /* Expand paletted images to RGB. */
570 void PNGAPI
571 png_set_palette_to_rgb(png_structp png_ptr)
572 {
573    png_debug(1, "in png_set_expand\n");
574    png_ptr->transformations |= PNG_EXPAND;
575 }
576
577 /* Expand grayscale images of less than 8-bit depth to 8 bits. */
578 void PNGAPI
579 png_set_gray_1_2_4_to_8(png_structp png_ptr)
580 {
581    png_debug(1, "in png_set_expand\n");
582    png_ptr->transformations |= PNG_EXPAND;
583 }
584
585 /* Expand tRNS chunks to alpha channels. */
586 void PNGAPI
587 png_set_tRNS_to_alpha(png_structp png_ptr)
588 {
589    png_debug(1, "in png_set_expand\n");
590    png_ptr->transformations |= PNG_EXPAND;
591 }
592 #endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
593
594 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
595 void PNGAPI
596 png_set_gray_to_rgb(png_structp png_ptr)
597 {
598    png_debug(1, "in png_set_gray_to_rgb\n");
599    png_ptr->transformations |= PNG_GRAY_TO_RGB;
600 }
601 #endif
602
603 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
604 #if defined(PNG_FLOATING_POINT_SUPPORTED)
605 /* Convert a RGB image to a grayscale of the same width.  This allows us,
606  * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
607  */
608
609 void PNGAPI
610 png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
611    double green)
612 {
613       int red_fixed = (int)((float)red*100000.0 + 0.5);
614       int green_fixed = (int)((float)green*100000.0 + 0.5);
615       png_set_rgb_to_gray_fixed(png_ptr, error_action, red_fixed, green_fixed);
616 }
617 #endif
618
619 void PNGAPI
620 png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
621    png_fixed_point red, png_fixed_point green)
622 {
623    png_debug(1, "in png_set_rgb_to_gray\n");
624    switch(error_action)
625    {
626       case 1: png_ptr->transformations |= PNG_RGB_TO_GRAY;
627               break;
628       case 2: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
629               break;
630       case 3: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
631    }
632    if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
633 #if defined(PNG_READ_EXPAND_SUPPORTED)
634       png_ptr->transformations |= PNG_EXPAND;
635 #else
636    {
637       png_warning(png_ptr, "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED.");
638       png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
639    }
640 #endif
641    {
642       png_uint_16 red_int, green_int;
643       if(red < 0 || green < 0)
644       {
645          red_int   =  6968; /* .212671 * 32768 + .5 */
646          green_int = 23434; /* .715160 * 32768 + .5 */
647       }
648       else if(red + green < 100000L)
649       {
650         red_int = (png_uint_16)(((png_uint_32)red*32768L)/100000L);
651         green_int = (png_uint_16)(((png_uint_32)green*32768L)/100000L);
652       }
653       else
654       {
655          png_warning(png_ptr, "ignoring out of range rgb_to_gray coefficients");
656          red_int   =  6968;
657          green_int = 23434;
658       }
659       png_ptr->rgb_to_gray_red_coeff   = red_int;
660       png_ptr->rgb_to_gray_green_coeff = green_int;
661       png_ptr->rgb_to_gray_blue_coeff  = (png_uint_16)(32768-red_int-green_int);
662    }
663 }
664 #endif
665
666 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
667     defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) || \
668     defined(PNG_LEGACY_SUPPORTED)
669 void PNGAPI
670 png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
671    read_user_transform_fn)
672 {
673    png_debug(1, "in png_set_read_user_transform_fn\n");
674 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
675    png_ptr->transformations |= PNG_USER_TRANSFORM;
676    png_ptr->read_user_transform_fn = read_user_transform_fn;
677 #endif
678 #ifdef PNG_LEGACY_SUPPORTED
679    if(read_user_transform_fn)
680       png_warning(png_ptr,
681         "This version of libpng does not support user transforms");
682 #endif
683 }
684 #endif
685
686 /* Initialize everything needed for the read.  This includes modifying
687  * the palette.
688  */
689 void /* PRIVATE */
690 png_init_read_transformations(png_structp png_ptr)
691 {
692    png_debug(1, "in png_init_read_transformations\n");
693 #if defined(PNG_USELESS_TESTS_SUPPORTED)
694    if(png_ptr != NULL)
695 #endif
696   {
697 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || defined(PNG_READ_SHIFT_SUPPORTED) \
698  || defined(PNG_READ_GAMMA_SUPPORTED)
699    int color_type = png_ptr->color_type;
700 #endif
701
702 #if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
703    if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
704        (png_ptr->transformations & PNG_EXPAND))
705    {
706       if (!(color_type & PNG_COLOR_MASK_COLOR))  /* i.e., GRAY or GRAY_ALPHA */
707       {
708          /* expand background chunk. */
709          switch (png_ptr->bit_depth)
710          {
711             case 1:
712                png_ptr->background.gray *= (png_uint_16)0xff;
713                png_ptr->background.red = png_ptr->background.green
714                  =  png_ptr->background.blue = png_ptr->background.gray;
715                break;
716             case 2:
717                png_ptr->background.gray *= (png_uint_16)0x55;
718                png_ptr->background.red = png_ptr->background.green
719                  = png_ptr->background.blue = png_ptr->background.gray;
720                break;
721             case 4:
722                png_ptr->background.gray *= (png_uint_16)0x11;
723                png_ptr->background.red = png_ptr->background.green
724                  = png_ptr->background.blue = png_ptr->background.gray;
725                break;
726             case 8:
727             case 16:
728                png_ptr->background.red = png_ptr->background.green
729                  = png_ptr->background.blue = png_ptr->background.gray;
730                break;
731          }
732       }
733       else if (color_type == PNG_COLOR_TYPE_PALETTE)
734       {
735          png_ptr->background.red   =
736             png_ptr->palette[png_ptr->background.index].red;
737          png_ptr->background.green =
738             png_ptr->palette[png_ptr->background.index].green;
739          png_ptr->background.blue  =
740             png_ptr->palette[png_ptr->background.index].blue;
741
742 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
743         if (png_ptr->transformations & PNG_INVERT_ALPHA)
744         {
745 #if defined(PNG_READ_EXPAND_SUPPORTED)
746            if (!(png_ptr->transformations & PNG_EXPAND))
747 #endif
748            {
749            /* invert the alpha channel (in tRNS) unless the pixels are
750               going to be expanded, in which case leave it for later */
751               int i,istop;
752               istop=(int)png_ptr->num_trans;
753               for (i=0; i<istop; i++)
754                  png_ptr->trans[i] = (png_byte)(255 - png_ptr->trans[i]);
755            }
756         }
757 #endif
758
759       }
760    }
761 #endif
762
763 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
764    png_ptr->background_1 = png_ptr->background;
765 #endif
766 #if defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
767
768    if ((color_type == PNG_COLOR_TYPE_PALETTE && png_ptr->num_trans != 0)
769        && (fabs(png_ptr->screen_gamma * png_ptr->gamma - 1.0)
770          < PNG_GAMMA_THRESHOLD))
771    {
772     int i,k;
773     k=0;
774     for (i=0; i<png_ptr->num_trans; i++)
775     {
776       if (png_ptr->trans[i] != 0 && png_ptr->trans[i] != 0xff)
777         k=1; /* partial transparency is present */
778     }
779     if (k == 0)
780       png_ptr->transformations &= (~PNG_GAMMA);
781    }
782
783    if (png_ptr->transformations & (PNG_GAMMA | PNG_RGB_TO_GRAY))
784    {
785       png_build_gamma_table(png_ptr);
786 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
787       if (png_ptr->transformations & PNG_BACKGROUND)
788       {
789          if (color_type == PNG_COLOR_TYPE_PALETTE)
790          {
791            /* could skip if no transparency and 
792            */
793             png_color back, back_1;
794             png_colorp palette = png_ptr->palette;
795             int num_palette = png_ptr->num_palette;
796             int i;
797             if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
798             {
799                back.red = png_ptr->gamma_table[png_ptr->background.red];
800                back.green = png_ptr->gamma_table[png_ptr->background.green];
801                back.blue = png_ptr->gamma_table[png_ptr->background.blue];
802
803                back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
804                back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
805                back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
806             }
807             else
808             {
809                double g, gs;
810
811                switch (png_ptr->background_gamma_type)
812                {
813                   case PNG_BACKGROUND_GAMMA_SCREEN:
814                      g = (png_ptr->screen_gamma);
815                      gs = 1.0;
816                      break;
817                   case PNG_BACKGROUND_GAMMA_FILE:
818                      g = 1.0 / (png_ptr->gamma);
819                      gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
820                      break;
821                   case PNG_BACKGROUND_GAMMA_UNIQUE:
822                      g = 1.0 / (png_ptr->background_gamma);
823                      gs = 1.0 / (png_ptr->background_gamma *
824                                  png_ptr->screen_gamma);
825                      break;
826                   default:
827                      g = 1.0;    /* back_1 */
828                      gs = 1.0;   /* back */
829                }
830
831                if ( fabs(gs - 1.0) < PNG_GAMMA_THRESHOLD)
832                {
833                   back.red   = (png_byte)png_ptr->background.red;
834                   back.green = (png_byte)png_ptr->background.green;
835                   back.blue  = (png_byte)png_ptr->background.blue;
836                }
837                else
838                {
839                   back.red = (png_byte)(pow(
840                      (double)png_ptr->background.red/255, gs) * 255.0 + .5);
841                   back.green = (png_byte)(pow(
842                      (double)png_ptr->background.green/255, gs) * 255.0 + .5);
843                   back.blue = (png_byte)(pow(
844                      (double)png_ptr->background.blue/255, gs) * 255.0 + .5);
845                }
846
847                back_1.red = (png_byte)(pow(
848                   (double)png_ptr->background.red/255, g) * 255.0 + .5);
849                back_1.green = (png_byte)(pow(
850                   (double)png_ptr->background.green/255, g) * 255.0 + .5);
851                back_1.blue = (png_byte)(pow(
852                   (double)png_ptr->background.blue/255, g) * 255.0 + .5);
853             }
854             for (i = 0; i < num_palette; i++)
855             {
856                if (i < (int)png_ptr->num_trans && png_ptr->trans[i] != 0xff)
857                {
858                   if (png_ptr->trans[i] == 0)
859                   {
860                      palette[i] = back;
861                   }
862                   else /* if (png_ptr->trans[i] != 0xff) */
863                   {
864                      png_byte v, w;
865
866                      v = png_ptr->gamma_to_1[palette[i].red];
867                      png_composite(w, v, png_ptr->trans[i], back_1.red);
868                      palette[i].red = png_ptr->gamma_from_1[w];
869
870                      v = png_ptr->gamma_to_1[palette[i].green];
871                      png_composite(w, v, png_ptr->trans[i], back_1.green);
872                      palette[i].green = png_ptr->gamma_from_1[w];
873
874                      v = png_ptr->gamma_to_1[palette[i].blue];
875                      png_composite(w, v, png_ptr->trans[i], back_1.blue);
876                      palette[i].blue = png_ptr->gamma_from_1[w];
877                   }
878                }
879                else
880                {
881                   palette[i].red = png_ptr->gamma_table[palette[i].red];
882                   palette[i].green = png_ptr->gamma_table[palette[i].green];
883                   palette[i].blue = png_ptr->gamma_table[palette[i].blue];
884                }
885             }
886          }
887          /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
888          else
889          /* color_type != PNG_COLOR_TYPE_PALETTE */
890          {
891             double m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
892             double g = 1.0;
893             double gs = 1.0;
894
895             switch (png_ptr->background_gamma_type)
896             {
897                case PNG_BACKGROUND_GAMMA_SCREEN:
898                   g = (png_ptr->screen_gamma);
899                   gs = 1.0;
900                   break;
901                case PNG_BACKGROUND_GAMMA_FILE:
902                   g = 1.0 / (png_ptr->gamma);
903                   gs = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
904                   break;
905                case PNG_BACKGROUND_GAMMA_UNIQUE:
906                   g = 1.0 / (png_ptr->background_gamma);
907                   gs = 1.0 / (png_ptr->background_gamma *
908                      png_ptr->screen_gamma);
909                   break;
910             }
911
912             png_ptr->background_1.gray = (png_uint_16)(pow(
913                (double)png_ptr->background.gray / m, g) * m + .5);
914             png_ptr->background.gray = (png_uint_16)(pow(
915                (double)png_ptr->background.gray / m, gs) * m + .5);
916
917             if ((png_ptr->background.red != png_ptr->background.green) ||
918                 (png_ptr->background.red != png_ptr->background.blue) ||
919                 (png_ptr->background.red != png_ptr->background.gray))
920             {
921                /* RGB or RGBA with color background */
922                png_ptr->background_1.red = (png_uint_16)(pow(
923                   (double)png_ptr->background.red / m, g) * m + .5);
924                png_ptr->background_1.green = (png_uint_16)(pow(
925                   (double)png_ptr->background.green / m, g) * m + .5);
926                png_ptr->background_1.blue = (png_uint_16)(pow(
927                   (double)png_ptr->background.blue / m, g) * m + .5);
928                png_ptr->background.red = (png_uint_16)(pow(
929                   (double)png_ptr->background.red / m, gs) * m + .5);
930                png_ptr->background.green = (png_uint_16)(pow(
931                   (double)png_ptr->background.green / m, gs) * m + .5);
932                png_ptr->background.blue = (png_uint_16)(pow(
933                   (double)png_ptr->background.blue / m, gs) * m + .5);
934             }
935             else
936             {
937                /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
938                png_ptr->background_1.red = png_ptr->background_1.green
939                  = png_ptr->background_1.blue = png_ptr->background_1.gray;
940                png_ptr->background.red = png_ptr->background.green
941                  = png_ptr->background.blue = png_ptr->background.gray;
942             }
943          }
944       }
945       else
946       /* transformation does not include PNG_BACKGROUND */
947 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
948       if (color_type == PNG_COLOR_TYPE_PALETTE)
949       {
950          png_colorp palette = png_ptr->palette;
951          int num_palette = png_ptr->num_palette;
952          int i;
953
954          for (i = 0; i < num_palette; i++)
955          {
956             palette[i].red = png_ptr->gamma_table[palette[i].red];
957             palette[i].green = png_ptr->gamma_table[palette[i].green];
958             palette[i].blue = png_ptr->gamma_table[palette[i].blue];
959          }
960       }
961    }
962 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
963    else
964 #endif
965 #endif /* PNG_READ_GAMMA_SUPPORTED && PNG_FLOATING_POINT_SUPPORTED */
966 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
967    /* No GAMMA transformation */
968    if ((png_ptr->transformations & PNG_BACKGROUND) &&
969        (color_type == PNG_COLOR_TYPE_PALETTE))
970    {
971       int i;
972       int istop = (int)png_ptr->num_trans;
973       png_color back;
974       png_colorp palette = png_ptr->palette;
975
976       back.red   = (png_byte)png_ptr->background.red;
977       back.green = (png_byte)png_ptr->background.green;
978       back.blue  = (png_byte)png_ptr->background.blue;
979
980       for (i = 0; i < istop; i++)
981       {
982          if (png_ptr->trans[i] == 0)
983          {
984             palette[i] = back;
985          }
986          else if (png_ptr->trans[i] != 0xff)
987          {
988             /* The png_composite() macro is defined in png.h */
989             png_composite(palette[i].red, palette[i].red,
990                png_ptr->trans[i], back.red);
991             png_composite(palette[i].green, palette[i].green,
992                png_ptr->trans[i], back.green);
993             png_composite(palette[i].blue, palette[i].blue,
994                png_ptr->trans[i], back.blue);
995          }
996       }
997    }
998 #endif /* PNG_READ_BACKGROUND_SUPPORTED */
999
1000 #if defined(PNG_READ_SHIFT_SUPPORTED)
1001    if ((png_ptr->transformations & PNG_SHIFT) &&
1002       (color_type == PNG_COLOR_TYPE_PALETTE))
1003    {
1004       png_uint_16 i;
1005       png_uint_16 istop = png_ptr->num_palette;
1006       int sr = 8 - png_ptr->sig_bit.red;
1007       int sg = 8 - png_ptr->sig_bit.green;
1008       int sb = 8 - png_ptr->sig_bit.blue;
1009
1010       if (sr < 0 || sr > 8)
1011          sr = 0;
1012       if (sg < 0 || sg > 8)
1013          sg = 0;
1014       if (sb < 0 || sb > 8)
1015          sb = 0;
1016       for (i = 0; i < istop; i++)
1017       {
1018          png_ptr->palette[i].red >>= sr;
1019          png_ptr->palette[i].green >>= sg;
1020          png_ptr->palette[i].blue >>= sb;
1021       }
1022    }
1023 #endif  /* PNG_READ_SHIFT_SUPPORTED */
1024  }
1025 #if !defined(PNG_READ_GAMMA_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) \
1026  && !defined(PNG_READ_BACKGROUND_SUPPORTED)
1027    if(png_ptr)
1028       return;
1029 #endif
1030 }
1031
1032 /* Modify the info structure to reflect the transformations.  The
1033  * info should be updated so a PNG file could be written with it,
1034  * assuming the transformations result in valid PNG data.
1035  */
1036 void /* PRIVATE */
1037 png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
1038 {
1039    png_debug(1, "in png_read_transform_info\n");
1040 #if defined(PNG_READ_EXPAND_SUPPORTED)
1041    if (png_ptr->transformations & PNG_EXPAND)
1042    {
1043       if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1044       {
1045          if (png_ptr->num_trans)
1046             info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1047          else
1048             info_ptr->color_type = PNG_COLOR_TYPE_RGB;
1049          info_ptr->bit_depth = 8;
1050          info_ptr->num_trans = 0;
1051       }
1052       else
1053       {
1054          if (png_ptr->num_trans)
1055             info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1056          if (info_ptr->bit_depth < 8)
1057             info_ptr->bit_depth = 8;
1058          info_ptr->num_trans = 0;
1059       }
1060    }
1061 #endif
1062
1063 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1064    if (png_ptr->transformations & PNG_BACKGROUND)
1065    {
1066       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1067       info_ptr->num_trans = 0;
1068       info_ptr->background = png_ptr->background;
1069    }
1070 #endif
1071
1072 #if defined(PNG_READ_GAMMA_SUPPORTED)
1073    if (png_ptr->transformations & PNG_GAMMA)
1074    {
1075 #ifdef PNG_FLOATING_POINT_SUPPORTED
1076       info_ptr->gamma = png_ptr->gamma;
1077 #endif
1078 #ifdef PNG_FIXED_POINT_SUPPORTED
1079       info_ptr->int_gamma = png_ptr->int_gamma;
1080 #endif
1081    }
1082 #endif
1083
1084 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1085    if ((png_ptr->transformations & PNG_16_TO_8) && (info_ptr->bit_depth == 16))
1086       info_ptr->bit_depth = 8;
1087 #endif
1088
1089 #if defined(PNG_READ_DITHER_SUPPORTED)
1090    if (png_ptr->transformations & PNG_DITHER)
1091    {
1092       if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1093          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
1094          png_ptr->palette_lookup && info_ptr->bit_depth == 8)
1095       {
1096          info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
1097       }
1098    }
1099 #endif
1100
1101 #if defined(PNG_READ_PACK_SUPPORTED)
1102    if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
1103       info_ptr->bit_depth = 8;
1104 #endif
1105
1106 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1107    if (png_ptr->transformations & PNG_GRAY_TO_RGB)
1108       info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
1109 #endif
1110
1111 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1112    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1113       info_ptr->color_type &= ~PNG_COLOR_MASK_COLOR;
1114 #endif
1115
1116    if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1117       info_ptr->channels = 1;
1118    else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1119       info_ptr->channels = 3;
1120    else
1121       info_ptr->channels = 1;
1122
1123 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1124    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1125       info_ptr->color_type &= ~PNG_COLOR_MASK_ALPHA;
1126 #endif
1127
1128    if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1129       info_ptr->channels++;
1130
1131 #if defined(PNG_READ_FILLER_SUPPORTED)
1132    /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
1133    if ((png_ptr->transformations & PNG_FILLER) &&
1134        ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
1135        (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
1136    {
1137       info_ptr->channels++;
1138       /* if adding a true alpha channel not just filler */
1139 #if !defined(PNG_1_0_X)
1140       if (png_ptr->transformations & PNG_ADD_ALPHA)
1141         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
1142 #endif
1143    }
1144 #endif
1145
1146 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
1147 defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1148    if(png_ptr->transformations & PNG_USER_TRANSFORM)
1149      {
1150        if(info_ptr->bit_depth < png_ptr->user_transform_depth)
1151          info_ptr->bit_depth = png_ptr->user_transform_depth;
1152        if(info_ptr->channels < png_ptr->user_transform_channels)
1153          info_ptr->channels = png_ptr->user_transform_channels;
1154      }
1155 #endif
1156
1157    info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
1158       info_ptr->bit_depth);
1159
1160    info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth,info_ptr->width);
1161
1162 #if !defined(PNG_READ_EXPAND_SUPPORTED)
1163    if(png_ptr)
1164       return;
1165 #endif
1166 }
1167
1168 /* Transform the row.  The order of transformations is significant,
1169  * and is very touchy.  If you add a transformation, take care to
1170  * decide how it fits in with the other transformations here.
1171  */
1172 void /* PRIVATE */
1173 png_do_read_transformations(png_structp png_ptr)
1174 {
1175    png_debug(1, "in png_do_read_transformations\n");
1176 #if !defined(PNG_USELESS_TESTS_SUPPORTED)
1177    if (png_ptr->row_buf == NULL)
1178    {
1179 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1180       char msg[50];
1181
1182       sprintf(msg, "NULL row buffer for row %ld, pass %d", png_ptr->row_number,
1183          png_ptr->pass);
1184       png_error(png_ptr, msg);
1185 #else
1186       png_error(png_ptr, "NULL row buffer");
1187 #endif
1188    }
1189 #endif
1190
1191 #if defined(PNG_READ_EXPAND_SUPPORTED)
1192    if (png_ptr->transformations & PNG_EXPAND)
1193    {
1194       if (png_ptr->row_info.color_type == PNG_COLOR_TYPE_PALETTE)
1195       {
1196          png_do_expand_palette(&(png_ptr->row_info), png_ptr->row_buf + 1,
1197             png_ptr->palette, png_ptr->trans, png_ptr->num_trans);
1198       }
1199       else
1200       {
1201          if (png_ptr->num_trans)
1202             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1203                &(png_ptr->trans_values));
1204          else
1205             png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
1206                NULL);
1207       }
1208    }
1209 #endif
1210
1211 #if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1212    if (png_ptr->flags & PNG_FLAG_STRIP_ALPHA)
1213       png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1214          PNG_FLAG_FILLER_AFTER | (png_ptr->flags & PNG_FLAG_STRIP_ALPHA));
1215 #endif
1216
1217 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
1218    if (png_ptr->transformations & PNG_RGB_TO_GRAY)
1219    {
1220       int rgb_error =
1221          png_do_rgb_to_gray(png_ptr, &(png_ptr->row_info), png_ptr->row_buf + 1);
1222       if(rgb_error)
1223       {
1224          png_ptr->rgb_to_gray_status=1;
1225          if(png_ptr->transformations == PNG_RGB_TO_GRAY_WARN)
1226             png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1227          if(png_ptr->transformations == PNG_RGB_TO_GRAY_ERR)
1228             png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
1229       }
1230    }
1231 #endif
1232
1233 /*
1234 From Andreas Dilger e-mail to png-implement, 26 March 1998:
1235
1236   In most cases, the "simple transparency" should be done prior to doing
1237   gray-to-RGB, or you will have to test 3x as many bytes to check if a
1238   pixel is transparent.  You would also need to make sure that the
1239   transparency information is upgraded to RGB.
1240
1241   To summarize, the current flow is:
1242   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
1243                                   with background "in place" if transparent,
1244                                   convert to RGB if necessary
1245   - Gray + alpha -> composite with gray background and remove alpha bytes,
1246                                   convert to RGB if necessary
1247
1248   To support RGB backgrounds for gray images we need:
1249   - Gray + simple transparency -> convert to RGB + simple transparency, compare
1250                                   3 or 6 bytes and composite with background
1251                                   "in place" if transparent (3x compare/pixel
1252                                   compared to doing composite with gray bkgrnd)
1253   - Gray + alpha -> convert to RGB + alpha, composite with background and
1254                                   remove alpha bytes (3x float operations/pixel
1255                                   compared with composite on gray background)
1256
1257   Greg's change will do this.  The reason it wasn't done before is for
1258   performance, as this increases the per-pixel operations.  If we would check
1259   in advance if the background was gray or RGB, and position the gray-to-RGB
1260   transform appropriately, then it would save a lot of work/time.
1261  */
1262
1263 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1264    /* if gray -> RGB, do so now only if background is non-gray; else do later
1265     * for performance reasons */
1266    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1267        !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1268       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1269 #endif
1270
1271 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1272    if ((png_ptr->transformations & PNG_BACKGROUND) &&
1273       ((png_ptr->num_trans != 0 ) ||
1274       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)))
1275       png_do_background(&(png_ptr->row_info), png_ptr->row_buf + 1,
1276          &(png_ptr->trans_values), &(png_ptr->background)
1277 #if defined(PNG_READ_GAMMA_SUPPORTED)
1278          , &(png_ptr->background_1),
1279          png_ptr->gamma_table, png_ptr->gamma_from_1,
1280          png_ptr->gamma_to_1, png_ptr->gamma_16_table,
1281          png_ptr->gamma_16_from_1, png_ptr->gamma_16_to_1,
1282          png_ptr->gamma_shift
1283 #endif
1284 );
1285 #endif
1286
1287 #if defined(PNG_READ_GAMMA_SUPPORTED)
1288    if ((png_ptr->transformations & PNG_GAMMA) &&
1289 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
1290       !((png_ptr->transformations & PNG_BACKGROUND) &&
1291       ((png_ptr->num_trans != 0) ||
1292       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
1293 #endif
1294       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
1295       png_do_gamma(&(png_ptr->row_info), png_ptr->row_buf + 1,
1296          png_ptr->gamma_table, png_ptr->gamma_16_table,
1297          png_ptr->gamma_shift);
1298 #endif
1299
1300 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1301    if (png_ptr->transformations & PNG_16_TO_8)
1302       png_do_chop(&(png_ptr->row_info), png_ptr->row_buf + 1);
1303 #endif
1304
1305 #if defined(PNG_READ_DITHER_SUPPORTED)
1306    if (png_ptr->transformations & PNG_DITHER)
1307    {
1308       png_do_dither((png_row_infop)&(png_ptr->row_info), png_ptr->row_buf + 1,
1309          png_ptr->palette_lookup, png_ptr->dither_index);
1310       if(png_ptr->row_info.rowbytes == (png_uint_32)0)
1311          png_error(png_ptr, "png_do_dither returned rowbytes=0");
1312    }
1313 #endif
1314
1315 #if defined(PNG_READ_INVERT_SUPPORTED)
1316    if (png_ptr->transformations & PNG_INVERT_MONO)
1317       png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
1318 #endif
1319
1320 #if defined(PNG_READ_SHIFT_SUPPORTED)
1321    if (png_ptr->transformations & PNG_SHIFT)
1322       png_do_unshift(&(png_ptr->row_info), png_ptr->row_buf + 1,
1323          &(png_ptr->shift));
1324 #endif
1325
1326 #if defined(PNG_READ_PACK_SUPPORTED)
1327    if (png_ptr->transformations & PNG_PACK)
1328       png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
1329 #endif
1330
1331 #if defined(PNG_READ_BGR_SUPPORTED)
1332    if (png_ptr->transformations & PNG_BGR)
1333       png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
1334 #endif
1335
1336 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
1337    if (png_ptr->transformations & PNG_PACKSWAP)
1338       png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1339 #endif
1340
1341 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
1342    /* if gray -> RGB, do so now only if we did not do so above */
1343    if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
1344        (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
1345       png_do_gray_to_rgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
1346 #endif
1347
1348 #if defined(PNG_READ_FILLER_SUPPORTED)
1349    if (png_ptr->transformations & PNG_FILLER)
1350       png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
1351          (png_uint_32)png_ptr->filler, png_ptr->flags);
1352 #endif
1353
1354 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1355    if (png_ptr->transformations & PNG_INVERT_ALPHA)
1356       png_do_read_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1357 #endif
1358
1359 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1360    if (png_ptr->transformations & PNG_SWAP_ALPHA)
1361       png_do_read_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
1362 #endif
1363
1364 #if defined(PNG_READ_SWAP_SUPPORTED)
1365    if (png_ptr->transformations & PNG_SWAP_BYTES)
1366       png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
1367 #endif
1368
1369 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
1370    if (png_ptr->transformations & PNG_USER_TRANSFORM)
1371     {
1372       if(png_ptr->read_user_transform_fn != NULL)
1373         (*(png_ptr->read_user_transform_fn)) /* user read transform function */
1374           (png_ptr,                    /* png_ptr */
1375            &(png_ptr->row_info),       /* row_info:     */
1376              /*  png_uint_32 width;          width of row */
1377              /*  png_uint_32 rowbytes;       number of bytes in row */
1378              /*  png_byte color_type;        color type of pixels */
1379              /*  png_byte bit_depth;         bit depth of samples */
1380              /*  png_byte channels;          number of channels (1-4) */
1381              /*  png_byte pixel_depth;       bits per pixel (depth*channels) */
1382            png_ptr->row_buf + 1);      /* start of pixel data for row */
1383 #if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
1384       if(png_ptr->user_transform_depth)
1385          png_ptr->row_info.bit_depth = png_ptr->user_transform_depth;
1386       if(png_ptr->user_transform_channels)
1387          png_ptr->row_info.channels = png_ptr->user_transform_channels;
1388 #endif
1389       png_ptr->row_info.pixel_depth = (png_byte)(png_ptr->row_info.bit_depth *
1390          png_ptr->row_info.channels);
1391       png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
1392          png_ptr->row_info.width);
1393    }
1394 #endif
1395
1396 }
1397
1398 #if defined(PNG_READ_PACK_SUPPORTED)
1399 /* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
1400  * without changing the actual values.  Thus, if you had a row with
1401  * a bit depth of 1, you would end up with bytes that only contained
1402  * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
1403  * png_do_shift() after this.
1404  */
1405 void /* PRIVATE */
1406 png_do_unpack(png_row_infop row_info, png_bytep row)
1407 {
1408    png_debug(1, "in png_do_unpack\n");
1409 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1410    if (row != NULL && row_info != NULL && row_info->bit_depth < 8)
1411 #else
1412    if (row_info->bit_depth < 8)
1413 #endif
1414    {
1415       png_uint_32 i;
1416       png_uint_32 row_width=row_info->width;
1417
1418       switch (row_info->bit_depth)
1419       {
1420          case 1:
1421          {
1422             png_bytep sp = row + (png_size_t)((row_width - 1) >> 3);
1423             png_bytep dp = row + (png_size_t)row_width - 1;
1424             png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07);
1425             for (i = 0; i < row_width; i++)
1426             {
1427                *dp = (png_byte)((*sp >> shift) & 0x01);
1428                if (shift == 7)
1429                {
1430                   shift = 0;
1431                   sp--;
1432                }
1433                else
1434                   shift++;
1435
1436                dp--;
1437             }
1438             break;
1439          }
1440          case 2:
1441          {
1442
1443             png_bytep sp = row + (png_size_t)((row_width - 1) >> 2);
1444             png_bytep dp = row + (png_size_t)row_width - 1;
1445             png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
1446             for (i = 0; i < row_width; i++)
1447             {
1448                *dp = (png_byte)((*sp >> shift) & 0x03);
1449                if (shift == 6)
1450                {
1451                   shift = 0;
1452                   sp--;
1453                }
1454                else
1455                   shift += 2;
1456
1457                dp--;
1458             }
1459             break;
1460          }
1461          case 4:
1462          {
1463             png_bytep sp = row + (png_size_t)((row_width - 1) >> 1);
1464             png_bytep dp = row + (png_size_t)row_width - 1;
1465             png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
1466             for (i = 0; i < row_width; i++)
1467             {
1468                *dp = (png_byte)((*sp >> shift) & 0x0f);
1469                if (shift == 4)
1470                {
1471                   shift = 0;
1472                   sp--;
1473                }
1474                else
1475                   shift = 4;
1476
1477                dp--;
1478             }
1479             break;
1480          }
1481       }
1482       row_info->bit_depth = 8;
1483       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1484       row_info->rowbytes = row_width * row_info->channels;
1485    }
1486 }
1487 #endif
1488
1489 #if defined(PNG_READ_SHIFT_SUPPORTED)
1490 /* Reverse the effects of png_do_shift.  This routine merely shifts the
1491  * pixels back to their significant bits values.  Thus, if you have
1492  * a row of bit depth 8, but only 5 are significant, this will shift
1493  * the values back to 0 through 31.
1494  */
1495 void /* PRIVATE */
1496 png_do_unshift(png_row_infop row_info, png_bytep row, png_color_8p sig_bits)
1497 {
1498    png_debug(1, "in png_do_unshift\n");
1499    if (
1500 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1501        row != NULL && row_info != NULL && sig_bits != NULL &&
1502 #endif
1503        row_info->color_type != PNG_COLOR_TYPE_PALETTE)
1504    {
1505       int shift[4];
1506       int channels = 0;
1507       int c;
1508       png_uint_16 value = 0;
1509       png_uint_32 row_width = row_info->width;
1510
1511       if (row_info->color_type & PNG_COLOR_MASK_COLOR)
1512       {
1513          shift[channels++] = row_info->bit_depth - sig_bits->red;
1514          shift[channels++] = row_info->bit_depth - sig_bits->green;
1515          shift[channels++] = row_info->bit_depth - sig_bits->blue;
1516       }
1517       else
1518       {
1519          shift[channels++] = row_info->bit_depth - sig_bits->gray;
1520       }
1521       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
1522       {
1523          shift[channels++] = row_info->bit_depth - sig_bits->alpha;
1524       }
1525
1526       for (c = 0; c < channels; c++)
1527       {
1528          if (shift[c] <= 0)
1529             shift[c] = 0;
1530          else
1531             value = 1;
1532       }
1533
1534       if (!value)
1535          return;
1536
1537       switch (row_info->bit_depth)
1538       {
1539          case 2:
1540          {
1541             png_bytep bp;
1542             png_uint_32 i;
1543             png_uint_32 istop = row_info->rowbytes;
1544
1545             for (bp = row, i = 0; i < istop; i++)
1546             {
1547                *bp >>= 1;
1548                *bp++ &= 0x55;
1549             }
1550             break;
1551          }
1552          case 4:
1553          {
1554             png_bytep bp = row;
1555             png_uint_32 i;
1556             png_uint_32 istop = row_info->rowbytes;
1557             png_byte mask = (png_byte)((((int)0xf0 >> shift[0]) & (int)0xf0) |
1558                (png_byte)((int)0xf >> shift[0]));
1559
1560             for (i = 0; i < istop; i++)
1561             {
1562                *bp >>= shift[0];
1563                *bp++ &= mask;
1564             }
1565             break;
1566          }
1567          case 8:
1568          {
1569             png_bytep bp = row;
1570             png_uint_32 i;
1571             png_uint_32 istop = row_width * channels;
1572
1573             for (i = 0; i < istop; i++)
1574             {
1575                *bp++ >>= shift[i%channels];
1576             }
1577             break;
1578          }
1579          case 16:
1580          {
1581             png_bytep bp = row;
1582             png_uint_32 i;
1583             png_uint_32 istop = channels * row_width;
1584
1585             for (i = 0; i < istop; i++)
1586             {
1587                value = (png_uint_16)((*bp << 8) + *(bp + 1));
1588                value >>= shift[i%channels];
1589                *bp++ = (png_byte)(value >> 8);
1590                *bp++ = (png_byte)(value & 0xff);
1591             }
1592             break;
1593          }
1594       }
1595    }
1596 }
1597 #endif
1598
1599 #if defined(PNG_READ_16_TO_8_SUPPORTED)
1600 /* chop rows of bit depth 16 down to 8 */
1601 void /* PRIVATE */
1602 png_do_chop(png_row_infop row_info, png_bytep row)
1603 {
1604    png_debug(1, "in png_do_chop\n");
1605 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1606    if (row != NULL && row_info != NULL && row_info->bit_depth == 16)
1607 #else
1608    if (row_info->bit_depth == 16)
1609 #endif
1610    {
1611       png_bytep sp = row;
1612       png_bytep dp = row;
1613       png_uint_32 i;
1614       png_uint_32 istop = row_info->width * row_info->channels;
1615
1616       for (i = 0; i<istop; i++, sp += 2, dp++)
1617       {
1618 #if defined(PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED)
1619       /* This does a more accurate scaling of the 16-bit color
1620        * value, rather than a simple low-byte truncation.
1621        *
1622        * What the ideal calculation should be:
1623        *   *dp = (((((png_uint_32)(*sp) << 8) |
1624        *          (png_uint_32)(*(sp + 1))) * 255 + 127) / (png_uint_32)65535L;
1625        *
1626        * GRR: no, I think this is what it really should be:
1627        *   *dp = (((((png_uint_32)(*sp) << 8) |
1628        *           (png_uint_32)(*(sp + 1))) + 128L) / (png_uint_32)257L;
1629        *
1630        * GRR: here's the exact calculation with shifts:
1631        *   temp = (((png_uint_32)(*sp) << 8) | (png_uint_32)(*(sp + 1))) + 128L;
1632        *   *dp = (temp - (temp >> 8)) >> 8;
1633        *
1634        * Approximate calculation with shift/add instead of multiply/divide:
1635        *   *dp = ((((png_uint_32)(*sp) << 8) |
1636        *          (png_uint_32)((int)(*(sp + 1)) - *sp)) + 128) >> 8;
1637        *
1638        * What we actually do to avoid extra shifting and conversion:
1639        */
1640
1641          *dp = *sp + ((((int)(*(sp + 1)) - *sp) > 128) ? 1 : 0);
1642 #else
1643        /* Simply discard the low order byte */
1644          *dp = *sp;
1645 #endif
1646       }
1647       row_info->bit_depth = 8;
1648       row_info->pixel_depth = (png_byte)(8 * row_info->channels);
1649       row_info->rowbytes = row_info->width * row_info->channels;
1650    }
1651 }
1652 #endif
1653
1654 #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1655 void /* PRIVATE */
1656 png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
1657 {
1658    png_debug(1, "in png_do_read_swap_alpha\n");
1659 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1660    if (row != NULL && row_info != NULL)
1661 #endif
1662    {
1663       png_uint_32 row_width = row_info->width;
1664       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1665       {
1666          /* This converts from RGBA to ARGB */
1667          if (row_info->bit_depth == 8)
1668          {
1669             png_bytep sp = row + row_info->rowbytes;
1670             png_bytep dp = sp;
1671             png_byte save;
1672             png_uint_32 i;
1673
1674             for (i = 0; i < row_width; i++)
1675             {
1676                save = *(--sp);
1677                *(--dp) = *(--sp);
1678                *(--dp) = *(--sp);
1679                *(--dp) = *(--sp);
1680                *(--dp) = save;
1681             }
1682          }
1683          /* This converts from RRGGBBAA to AARRGGBB */
1684          else
1685          {
1686             png_bytep sp = row + row_info->rowbytes;
1687             png_bytep dp = sp;
1688             png_byte save[2];
1689             png_uint_32 i;
1690
1691             for (i = 0; i < row_width; i++)
1692             {
1693                save[0] = *(--sp);
1694                save[1] = *(--sp);
1695                *(--dp) = *(--sp);
1696                *(--dp) = *(--sp);
1697                *(--dp) = *(--sp);
1698                *(--dp) = *(--sp);
1699                *(--dp) = *(--sp);
1700                *(--dp) = *(--sp);
1701                *(--dp) = save[0];
1702                *(--dp) = save[1];
1703             }
1704          }
1705       }
1706       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1707       {
1708          /* This converts from GA to AG */
1709          if (row_info->bit_depth == 8)
1710          {
1711             png_bytep sp = row + row_info->rowbytes;
1712             png_bytep dp = sp;
1713             png_byte save;
1714             png_uint_32 i;
1715
1716             for (i = 0; i < row_width; i++)
1717             {
1718                save = *(--sp);
1719                *(--dp) = *(--sp);
1720                *(--dp) = save;
1721             }
1722          }
1723          /* This converts from GGAA to AAGG */
1724          else
1725          {
1726             png_bytep sp = row + row_info->rowbytes;
1727             png_bytep dp = sp;
1728             png_byte save[2];
1729             png_uint_32 i;
1730
1731             for (i = 0; i < row_width; i++)
1732             {
1733                save[0] = *(--sp);
1734                save[1] = *(--sp);
1735                *(--dp) = *(--sp);
1736                *(--dp) = *(--sp);
1737                *(--dp) = save[0];
1738                *(--dp) = save[1];
1739             }
1740          }
1741       }
1742    }
1743 }
1744 #endif
1745
1746 #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1747 void /* PRIVATE */
1748 png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
1749 {
1750    png_debug(1, "in png_do_read_invert_alpha\n");
1751 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1752    if (row != NULL && row_info != NULL)
1753 #endif
1754    {
1755       png_uint_32 row_width = row_info->width;
1756       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1757       {
1758          /* This inverts the alpha channel in RGBA */
1759          if (row_info->bit_depth == 8)
1760          {
1761             png_bytep sp = row + row_info->rowbytes;
1762             png_bytep dp = sp;
1763             png_uint_32 i;
1764
1765             for (i = 0; i < row_width; i++)
1766             {
1767                *(--dp) = (png_byte)(255 - *(--sp));
1768
1769 /*             This does nothing:
1770                *(--dp) = *(--sp);
1771                *(--dp) = *(--sp);
1772                *(--dp) = *(--sp);
1773                We can replace it with:
1774 */
1775                sp-=3;
1776                dp=sp;
1777             }
1778          }
1779          /* This inverts the alpha channel in RRGGBBAA */
1780          else
1781          {
1782             png_bytep sp = row + row_info->rowbytes;
1783             png_bytep dp = sp;
1784             png_uint_32 i;
1785
1786             for (i = 0; i < row_width; i++)
1787             {
1788                *(--dp) = (png_byte)(255 - *(--sp));
1789                *(--dp) = (png_byte)(255 - *(--sp));
1790
1791 /*             This does nothing:
1792                *(--dp) = *(--sp);
1793                *(--dp) = *(--sp);
1794                *(--dp) = *(--sp);
1795                *(--dp) = *(--sp);
1796                *(--dp) = *(--sp);
1797                *(--dp) = *(--sp);
1798                We can replace it with:
1799 */
1800                sp-=6;
1801                dp=sp;
1802             }
1803          }
1804       }
1805       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1806       {
1807          /* This inverts the alpha channel in GA */
1808          if (row_info->bit_depth == 8)
1809          {
1810             png_bytep sp = row + row_info->rowbytes;
1811             png_bytep dp = sp;
1812             png_uint_32 i;
1813
1814             for (i = 0; i < row_width; i++)
1815             {
1816                *(--dp) = (png_byte)(255 - *(--sp));
1817                *(--dp) = *(--sp);
1818             }
1819          }
1820          /* This inverts the alpha channel in GGAA */
1821          else
1822          {
1823             png_bytep sp  = row + row_info->rowbytes;
1824             png_bytep dp = sp;
1825             png_uint_32 i;
1826
1827             for (i = 0; i < row_width; i++)
1828             {
1829                *(--dp) = (png_byte)(255 - *(--sp));
1830                *(--dp) = (png_byte)(255 - *(--sp));
1831 /*
1832                *(--dp) = *(--sp);
1833                *(--dp) = *(--sp);
1834 */
1835                sp-=2;
1836                dp=sp;
1837             }
1838          }
1839       }
1840    }
1841 }
1842 #endif
1843
1844 #if defined(PNG_READ_FILLER_SUPPORTED)
1845 /* Add filler channel if we have RGB color */
1846 void /* PRIVATE */
1847 png_do_read_filler(png_row_infop row_info, png_bytep row,
1848    png_uint_32 filler, png_uint_32 flags)
1849 {
1850    png_uint_32 i;
1851    png_uint_32 row_width = row_info->width;
1852
1853    png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
1854    png_byte lo_filler = (png_byte)(filler & 0xff);
1855
1856    png_debug(1, "in png_do_read_filler\n");
1857    if (
1858 #if defined(PNG_USELESS_TESTS_SUPPORTED)
1859        row != NULL  && row_info != NULL &&
1860 #endif
1861        row_info->color_type == PNG_COLOR_TYPE_GRAY)
1862    {
1863       if(row_info->bit_depth == 8)
1864       {
1865          /* This changes the data from G to GX */
1866          if (flags & PNG_FLAG_FILLER_AFTER)
1867          {
1868             png_bytep sp = row + (png_size_t)row_width;
1869             png_bytep dp =  sp + (png_size_t)row_width;
1870             for (i = 1; i < row_width; i++)
1871             {
1872                *(--dp) = lo_filler;
1873                *(--dp) = *(--sp);
1874             }
1875             *(--dp) = lo_filler;
1876             row_info->channels = 2;
1877             row_info->pixel_depth = 16;
1878             row_info->rowbytes = row_width * 2;
1879          }
1880       /* This changes the data from G to XG */
1881          else
1882          {
1883             png_bytep sp = row + (png_size_t)row_width;
1884             png_bytep dp = sp  + (png_size_t)row_width;
1885             for (i = 0; i < row_width; i++)
1886             {
1887                *(--dp) = *(--sp);
1888                *(--dp) = lo_filler;
1889             }
1890             row_info->channels = 2;
1891             row_info->pixel_depth = 16;
1892             row_info->rowbytes = row_width * 2;
1893          }
1894       }
1895       else if(row_info->bit_depth == 16)
1896       {
1897          /* This changes the data from GG to GGXX */
1898          if (flags & PNG_FLAG_FILLER_AFTER)
1899          {
1900             png_bytep sp = row + (png_size_t)row_width * 2;
1901             png_bytep dp = sp  + (png_size_t)row_width * 2;
1902             for (i = 1; i < row_width; i++)
1903             {
1904                *(--dp) = hi_filler;
1905                *(--dp) = lo_filler;
1906                *(--dp) = *(--sp);
1907                *(--dp) = *(--sp);
1908             }
1909             *(--dp) = hi_filler;
1910             *(--dp) = lo_filler;
1911             row_info->channels = 2;
1912             row_info->pixel_depth = 32;
1913             row_info->rowbytes = row_width * 4;
1914          }
1915          /* This changes the data from GG to XXGG */
1916          else
1917          {
1918             png_bytep sp = row + (png_size_t)row_width * 2;
1919             png_bytep dp = sp  + (png_size_t)row_width * 2;
1920             for (i = 0; i < row_width; i++)
1921             {
1922                *(--dp) = *(--sp);
1923                *(--dp) = *(--sp);
1924                *(--dp) = hi_filler;
1925                *(--dp) = lo_filler;
1926             }
1927             row_info->channels = 2;
1928             row_info->pixel_depth = 32;
1929             row_info->rowbytes = row_width * 4;
1930          }
1931       }
1932    } /* COLOR_TYPE == GRAY */
1933    else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
1934    {
1935       if(row_info->bit_depth == 8)
1936       {
1937          /* This changes the data from RGB to RGBX */
1938          if (flags & PNG_FLAG_FILLER_AFTER)
1939          {
1940             png_bytep sp = row + (png_size_t)row_width * 3;
1941             png_bytep dp = sp  + (png_size_t)row_width;
1942             for (i = 1; i < row_width; i++)
1943             {
1944                *(--dp) = lo_filler;
1945                *(--dp) = *(--sp);
1946                *(--dp) = *(--sp);
1947                *(--dp) = *(--sp);
1948             }
1949             *(--dp) = lo_filler;
1950             row_info->channels = 4;
1951             row_info->pixel_depth = 32;
1952             row_info->rowbytes = row_width * 4;
1953          }
1954       /* This changes the data from RGB to XRGB */
1955          else
1956          {
1957             png_bytep sp = row + (png_size_t)row_width * 3;
1958             png_bytep dp = sp + (png_size_t)row_width;
1959             for (i = 0; i < row_width; i++)
1960             {
1961                *(--dp) = *(--sp);
1962                *(--dp) = *(--sp);
1963                *(--dp) = *(--sp);
1964                *(--dp) = lo_filler;
1965             }
1966             row_info->channels = 4;
1967             row_info->pixel_depth = 32;
1968             row_info->rowbytes = row_width * 4;
1969          }
1970       }
1971       else if(row_info->bit_depth == 16)
1972       {
1973          /* This changes the data from RRGGBB to RRGGBBXX */
1974          if (flags & PNG_FLAG_FILLER_AFTER)
1975          {
1976             png_bytep sp = row + (png_size_t)row_width * 6;
1977             png_bytep dp = sp  + (png_size_t)row_width * 2;
1978             for (i = 1; i < row_width; i++)
1979             {
1980                *(--dp) = hi_filler;
1981                *(--dp) = lo_filler;
1982                *(--dp) = *(--sp);
1983                *(--dp) = *(--sp);
1984                *(--dp) = *(--sp);
1985                *(--dp) = *(--sp);
1986                *(--dp) = *(--sp);
1987                *(--dp) = *(--sp);
1988             }
1989             *(--dp) = hi_filler;
1990             *(--dp) = lo_filler;
1991             row_info->channels = 4;
1992             row_info->pixel_depth = 64;
1993             row_info->rowbytes = row_width * 8;
1994          }
1995          /* This changes the data from RRGGBB to XXRRGGBB */
1996          else
1997          {
1998             png_bytep sp = row + (png_size_t)row_width * 6;
1999             png_bytep dp = sp  + (png_size_t)row_width * 2;
2000             for (i = 0; i < row_width; i++)
2001             {
2002                *(--dp) = *(--sp);
2003                *(--dp) = *(--sp);
2004                *(--dp) = *(--sp);
2005                *(--dp) = *(--sp);
2006                *(--dp) = *(--sp);
2007                *(--dp) = *(--sp);
2008                *(--dp) = hi_filler;
2009                *(--dp) = lo_filler;
2010             }
2011             row_info->channels = 4;
2012             row_info->pixel_depth = 64;
2013             row_info->rowbytes = row_width * 8;
2014          }
2015       }
2016    } /* COLOR_TYPE == RGB */
2017 }
2018 #endif
2019
2020 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2021 /* expand grayscale files to RGB, with or without alpha */
2022 void /* PRIVATE */
2023 png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
2024 {
2025    png_uint_32 i;
2026    png_uint_32 row_width = row_info->width;
2027
2028    png_debug(1, "in png_do_gray_to_rgb\n");
2029    if (row_info->bit_depth >= 8 &&
2030 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2031        row != NULL && row_info != NULL &&
2032 #endif
2033       !(row_info->color_type & PNG_COLOR_MASK_COLOR))
2034    {
2035       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
2036       {
2037          if (row_info->bit_depth == 8)
2038          {
2039             png_bytep sp = row + (png_size_t)row_width - 1;
2040             png_bytep dp = sp  + (png_size_t)row_width * 2;
2041             for (i = 0; i < row_width; i++)
2042             {
2043                *(dp--) = *sp;
2044                *(dp--) = *sp;
2045                *(dp--) = *(sp--);
2046             }
2047          }
2048          else
2049          {
2050             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2051             png_bytep dp = sp  + (png_size_t)row_width * 4;
2052             for (i = 0; i < row_width; i++)
2053             {
2054                *(dp--) = *sp;
2055                *(dp--) = *(sp - 1);
2056                *(dp--) = *sp;
2057                *(dp--) = *(sp - 1);
2058                *(dp--) = *(sp--);
2059                *(dp--) = *(sp--);
2060             }
2061          }
2062       }
2063       else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2064       {
2065          if (row_info->bit_depth == 8)
2066          {
2067             png_bytep sp = row + (png_size_t)row_width * 2 - 1;
2068             png_bytep dp = sp  + (png_size_t)row_width * 2;
2069             for (i = 0; i < row_width; i++)
2070             {
2071                *(dp--) = *(sp--);
2072                *(dp--) = *sp;
2073                *(dp--) = *sp;
2074                *(dp--) = *(sp--);
2075             }
2076          }
2077          else
2078          {
2079             png_bytep sp = row + (png_size_t)row_width * 4 - 1;
2080             png_bytep dp = sp  + (png_size_t)row_width * 4;
2081             for (i = 0; i < row_width; i++)
2082             {
2083                *(dp--) = *(sp--);
2084                *(dp--) = *(sp--);
2085                *(dp--) = *sp;
2086                *(dp--) = *(sp - 1);
2087                *(dp--) = *sp;
2088                *(dp--) = *(sp - 1);
2089                *(dp--) = *(sp--);
2090                *(dp--) = *(sp--);
2091             }
2092          }
2093       }
2094       row_info->channels += (png_byte)2;
2095       row_info->color_type |= PNG_COLOR_MASK_COLOR;
2096       row_info->pixel_depth = (png_byte)(row_info->channels *
2097          row_info->bit_depth);
2098       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2099    }
2100 }
2101 #endif
2102
2103 #if defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
2104 /* reduce RGB files to grayscale, with or without alpha
2105  * using the equation given in Poynton's ColorFAQ at
2106  * <http://www.inforamp.net/~poynton/>
2107  * Copyright (c) 1998-01-04 Charles Poynton poynton at inforamp.net
2108  *
2109  *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
2110  *
2111  *  We approximate this with
2112  *
2113  *     Y = 0.21268 * R    + 0.7151 * G    + 0.07217 * B
2114  *
2115  *  which can be expressed with integers as
2116  *
2117  *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
2118  *
2119  *  The calculation is to be done in a linear colorspace.
2120  *
2121  *  Other integer coefficents can be used via png_set_rgb_to_gray().
2122  */
2123 int /* PRIVATE */
2124 png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
2125
2126 {
2127    png_uint_32 i;
2128
2129    png_uint_32 row_width = row_info->width;
2130    int rgb_error = 0;
2131
2132    png_debug(1, "in png_do_rgb_to_gray\n");
2133    if (
2134 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2135        row != NULL && row_info != NULL &&
2136 #endif
2137       (row_info->color_type & PNG_COLOR_MASK_COLOR))
2138    {
2139       png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
2140       png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
2141       png_uint_32 bc = png_ptr->rgb_to_gray_blue_coeff;
2142
2143       if (row_info->color_type == PNG_COLOR_TYPE_RGB)
2144       {
2145          if (row_info->bit_depth == 8)
2146          {
2147 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2148             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2149             {
2150                png_bytep sp = row;
2151                png_bytep dp = row;
2152
2153                for (i = 0; i < row_width; i++)
2154                {
2155                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
2156                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
2157                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
2158                   if(red != green || red != blue)
2159                   {
2160                      rgb_error |= 1;
2161                      *(dp++) = png_ptr->gamma_from_1[
2162                        (rc*red+gc*green+bc*blue)>>15];
2163                   }
2164                   else
2165                      *(dp++) = *(sp-1);
2166                }
2167             }
2168             else
2169 #endif
2170             {
2171                png_bytep sp = row;
2172                png_bytep dp = row;
2173                for (i = 0; i < row_width; i++)
2174                {
2175                   png_byte red   = *(sp++);
2176                   png_byte green = *(sp++);
2177                   png_byte blue  = *(sp++);
2178                   if(red != green || red != blue)
2179                   {
2180                      rgb_error |= 1;
2181                      *(dp++) = (png_byte)((rc*red+gc*green+bc*blue)>>15);
2182                   }
2183                   else
2184                      *(dp++) = *(sp-1);
2185                }
2186             }
2187          }
2188
2189          else /* RGB bit_depth == 16 */
2190          {
2191 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2192             if (png_ptr->gamma_16_to_1 != NULL &&
2193                 png_ptr->gamma_16_from_1 != NULL)
2194             {
2195                png_bytep sp = row;
2196                png_bytep dp = row;
2197                for (i = 0; i < row_width; i++)
2198                {
2199                   png_uint_16 red, green, blue, w;
2200
2201                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2202                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2203                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2204
2205                   if(red == green && red == blue)
2206                      w = red;
2207                   else
2208                   {
2209                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
2210                                   png_ptr->gamma_shift][red>>8];
2211                      png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2212                                   png_ptr->gamma_shift][green>>8];
2213                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2214                                   png_ptr->gamma_shift][blue>>8];
2215                      png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
2216                                   + bc*blue_1)>>15);
2217                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2218                          png_ptr->gamma_shift][gray16 >> 8];
2219                      rgb_error |= 1;
2220                   }
2221
2222                   *(dp++) = (png_byte)((w>>8) & 0xff);
2223                   *(dp++) = (png_byte)(w & 0xff);
2224                }
2225             }
2226             else
2227 #endif
2228             {
2229                png_bytep sp = row;
2230                png_bytep dp = row;
2231                for (i = 0; i < row_width; i++)
2232                {
2233                   png_uint_16 red, green, blue, gray16;
2234
2235                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2236                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2237                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2238
2239                   if(red != green || red != blue)
2240                      rgb_error |= 1;
2241                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2242                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
2243                   *(dp++) = (png_byte)(gray16 & 0xff);
2244                }
2245             }
2246          }
2247       }
2248       if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2249       {
2250          if (row_info->bit_depth == 8)
2251          {
2252 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2253             if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
2254             {
2255                png_bytep sp = row;
2256                png_bytep dp = row;
2257                for (i = 0; i < row_width; i++)
2258                {
2259                   png_byte red   = png_ptr->gamma_to_1[*(sp++)];
2260                   png_byte green = png_ptr->gamma_to_1[*(sp++)];
2261                   png_byte blue  = png_ptr->gamma_to_1[*(sp++)];
2262                   if(red != green || red != blue)
2263                      rgb_error |= 1;
2264                   *(dp++) =  png_ptr->gamma_from_1
2265                              [(rc*red + gc*green + bc*blue)>>15];
2266                   *(dp++) = *(sp++);  /* alpha */
2267                }
2268             }
2269             else
2270 #endif
2271             {
2272                png_bytep sp = row;
2273                png_bytep dp = row;
2274                for (i = 0; i < row_width; i++)
2275                {
2276                   png_byte red   = *(sp++);
2277                   png_byte green = *(sp++);
2278                   png_byte blue  = *(sp++);
2279                   if(red != green || red != blue)
2280                      rgb_error |= 1;
2281                   *(dp++) =  (png_byte)((rc*red + gc*green + bc*blue)>>15);
2282                   *(dp++) = *(sp++);  /* alpha */
2283                }
2284             }
2285          }
2286          else /* RGBA bit_depth == 16 */
2287          {
2288 #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
2289             if (png_ptr->gamma_16_to_1 != NULL &&
2290                 png_ptr->gamma_16_from_1 != NULL)
2291             {
2292                png_bytep sp = row;
2293                png_bytep dp = row;
2294                for (i = 0; i < row_width; i++)
2295                {
2296                   png_uint_16 red, green, blue, w;
2297
2298                   red   = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2299                   green = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2300                   blue  = (png_uint_16)(((*(sp))<<8) | *(sp+1)); sp+=2;
2301
2302                   if(red == green && red == blue)
2303                      w = red;
2304                   else
2305                   {
2306                      png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red&0xff) >>
2307                                   png_ptr->gamma_shift][red>>8];
2308                      png_uint_16 green_1 = png_ptr->gamma_16_to_1[(green&0xff) >>
2309                                   png_ptr->gamma_shift][green>>8];
2310                      png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue&0xff) >>
2311                                   png_ptr->gamma_shift][blue>>8];
2312                      png_uint_16 gray16  = (png_uint_16)((rc * red_1
2313                                   + gc * green_1 + bc * blue_1)>>15);
2314                      w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
2315                          png_ptr->gamma_shift][gray16 >> 8];
2316                      rgb_error |= 1;
2317                   }
2318
2319                   *(dp++) = (png_byte)((w>>8) & 0xff);
2320                   *(dp++) = (png_byte)(w & 0xff);
2321                   *(dp++) = *(sp++);  /* alpha */
2322                   *(dp++) = *(sp++);
2323                }
2324             }
2325             else
2326 #endif
2327             {
2328                png_bytep sp = row;
2329                png_bytep dp = row;
2330                for (i = 0; i < row_width; i++)
2331                {
2332                   png_uint_16 red, green, blue, gray16;
2333                   red   = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2334                   green = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2335                   blue  = (png_uint_16)((*(sp)<<8) | *(sp+1)); sp+=2;
2336                   if(red != green || red != blue)
2337                      rgb_error |= 1;
2338                   gray16  = (png_uint_16)((rc*red + gc*green + bc*blue)>>15);
2339                   *(dp++) = (png_byte)((gray16>>8) & 0xff);
2340                   *(dp++) = (png_byte)(gray16 & 0xff);
2341                   *(dp++) = *(sp++);  /* alpha */
2342                   *(dp++) = *(sp++);
2343                }
2344             }
2345          }
2346       }
2347    row_info->channels -= (png_byte)2;
2348       row_info->color_type &= ~PNG_COLOR_MASK_COLOR;
2349       row_info->pixel_depth = (png_byte)(row_info->channels *
2350          row_info->bit_depth);
2351       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
2352    }
2353    return rgb_error;
2354 }
2355 #endif
2356
2357 /* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
2358  * large of png_color.  This lets grayscale images be treated as
2359  * paletted.  Most useful for gamma correction and simplification
2360  * of code.
2361  */
2362 void PNGAPI
2363 png_build_grayscale_palette(int bit_depth, png_colorp palette)
2364 {
2365    int num_palette;
2366    int color_inc;
2367    int i;
2368    int v;
2369
2370    png_debug(1, "in png_do_build_grayscale_palette\n");
2371    if (palette == NULL)
2372       return;
2373
2374    switch (bit_depth)
2375    {
2376       case 1:
2377          num_palette = 2;
2378          color_inc = 0xff;
2379          break;
2380       case 2:
2381          num_palette = 4;
2382          color_inc = 0x55;
2383          break;
2384       case 4:
2385          num_palette = 16;
2386          color_inc = 0x11;
2387          break;
2388       case 8:
2389          num_palette = 256;
2390          color_inc = 1;
2391          break;
2392       default:
2393          num_palette = 0;
2394          color_inc = 0;
2395          break;
2396    }
2397
2398    for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
2399    {
2400       palette[i].red = (png_byte)v;
2401       palette[i].green = (png_byte)v;
2402       palette[i].blue = (png_byte)v;
2403    }
2404 }
2405
2406 /* This function is currently unused.  Do we really need it? */
2407 #if defined(PNG_READ_DITHER_SUPPORTED) && defined(PNG_CORRECT_PALETTE_SUPPORTED)
2408 void /* PRIVATE */
2409 png_correct_palette(png_structp png_ptr, png_colorp palette,
2410    int num_palette)
2411 {
2412    png_debug(1, "in png_correct_palette\n");
2413 #if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
2414     defined(PNG_READ_GAMMA_SUPPORTED) && defined(PNG_FLOATING_POINT_SUPPORTED)
2415    if (png_ptr->transformations & (PNG_GAMMA | PNG_BACKGROUND))
2416    {
2417       png_color back, back_1;
2418
2419       if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
2420       {
2421          back.red = png_ptr->gamma_table[png_ptr->background.red];
2422          back.green = png_ptr->gamma_table[png_ptr->background.green];
2423          back.blue = png_ptr->gamma_table[png_ptr->background.blue];
2424
2425          back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
2426          back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
2427          back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
2428       }
2429       else
2430       {
2431          double g;
2432
2433          g = 1.0 / (png_ptr->background_gamma * png_ptr->screen_gamma);
2434
2435          if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_SCREEN ||
2436              fabs(g - 1.0) < PNG_GAMMA_THRESHOLD)
2437          {
2438             back.red = png_ptr->background.red;
2439             back.green = png_ptr->background.green;
2440             back.blue = png_ptr->background.blue;
2441          }
2442          else
2443          {
2444             back.red =
2445                (png_byte)(pow((double)png_ptr->background.red/255, g) *
2446                 255.0 + 0.5);
2447             back.green =
2448                (png_byte)(pow((double)png_ptr->background.green/255, g) *
2449                 255.0 + 0.5);
2450             back.blue =
2451                (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2452                 255.0 + 0.5);
2453          }
2454
2455          g = 1.0 / png_ptr->background_gamma;
2456
2457          back_1.red =
2458             (png_byte)(pow((double)png_ptr->background.red/255, g) *
2459              255.0 + 0.5);
2460          back_1.green =
2461             (png_byte)(pow((double)png_ptr->background.green/255, g) *
2462              255.0 + 0.5);
2463          back_1.blue =
2464             (png_byte)(pow((double)png_ptr->background.blue/255, g) *
2465              255.0 + 0.5);
2466       }
2467
2468       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2469       {
2470          png_uint_32 i;
2471
2472          for (i = 0; i < (png_uint_32)num_palette; i++)
2473          {
2474             if (i < png_ptr->num_trans && png_ptr->trans[i] == 0)
2475             {
2476                palette[i] = back;
2477             }
2478             else if (i < png_ptr->num_trans && png_ptr->trans[i] != 0xff)
2479             {
2480                png_byte v, w;
2481
2482                v = png_ptr->gamma_to_1[png_ptr->palette[i].red];
2483                png_composite(w, v, png_ptr->trans[i], back_1.red);
2484                palette[i].red = png_ptr->gamma_from_1[w];
2485
2486                v = png_ptr->gamma_to_1[png_ptr->palette[i].green];
2487                png_composite(w, v, png_ptr->trans[i], back_1.green);
2488                palette[i].green = png_ptr->gamma_from_1[w];
2489
2490                v = png_ptr->gamma_to_1[png_ptr->palette[i].blue];
2491                png_composite(w, v, png_ptr->trans[i], back_1.blue);
2492                palette[i].blue = png_ptr->gamma_from_1[w];
2493             }
2494             else
2495             {
2496                palette[i].red = png_ptr->gamma_table[palette[i].red];
2497                palette[i].green = png_ptr->gamma_table[palette[i].green];
2498                palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2499             }
2500          }
2501       }
2502       else
2503       {
2504          int i;
2505
2506          for (i = 0; i < num_palette; i++)
2507          {
2508             if (palette[i].red == (png_byte)png_ptr->trans_values.gray)
2509             {
2510                palette[i] = back;
2511             }
2512             else
2513             {
2514                palette[i].red = png_ptr->gamma_table[palette[i].red];
2515                palette[i].green = png_ptr->gamma_table[palette[i].green];
2516                palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2517             }
2518          }
2519       }
2520    }
2521    else
2522 #endif
2523 #if defined(PNG_READ_GAMMA_SUPPORTED)
2524    if (png_ptr->transformations & PNG_GAMMA)
2525    {
2526       int i;
2527
2528       for (i = 0; i < num_palette; i++)
2529       {
2530          palette[i].red = png_ptr->gamma_table[palette[i].red];
2531          palette[i].green = png_ptr->gamma_table[palette[i].green];
2532          palette[i].blue = png_ptr->gamma_table[palette[i].blue];
2533       }
2534    }
2535 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2536    else
2537 #endif
2538 #endif
2539 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2540    if (png_ptr->transformations & PNG_BACKGROUND)
2541    {
2542       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2543       {
2544          png_color back;
2545
2546          back.red   = (png_byte)png_ptr->background.red;
2547          back.green = (png_byte)png_ptr->background.green;
2548          back.blue  = (png_byte)png_ptr->background.blue;
2549
2550          for (i = 0; i < (int)png_ptr->num_trans; i++)
2551          {
2552             if (png_ptr->trans[i] == 0)
2553             {
2554                palette[i].red = back.red;
2555                palette[i].green = back.green;
2556                palette[i].blue = back.blue;
2557             }
2558             else if (png_ptr->trans[i] != 0xff)
2559             {
2560                png_composite(palette[i].red, png_ptr->palette[i].red,
2561                   png_ptr->trans[i], back.red);
2562                png_composite(palette[i].green, png_ptr->palette[i].green,
2563                   png_ptr->trans[i], back.green);
2564                png_composite(palette[i].blue, png_ptr->palette[i].blue,
2565                   png_ptr->trans[i], back.blue);
2566             }
2567          }
2568       }
2569       else /* assume grayscale palette (what else could it be?) */
2570       {
2571          int i;
2572
2573          for (i = 0; i < num_palette; i++)
2574          {
2575             if (i == (png_byte)png_ptr->trans_values.gray)
2576             {
2577                palette[i].red = (png_byte)png_ptr->background.red;
2578                palette[i].green = (png_byte)png_ptr->background.green;
2579                palette[i].blue = (png_byte)png_ptr->background.blue;
2580             }
2581          }
2582       }
2583    }
2584 #endif
2585 }
2586 #endif
2587
2588 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
2589 /* Replace any alpha or transparency with the supplied background color.
2590  * "background" is already in the screen gamma, while "background_1" is
2591  * at a gamma of 1.0.  Paletted files have already been taken care of.
2592  */
2593 void /* PRIVATE */
2594 png_do_background(png_row_infop row_info, png_bytep row,
2595    png_color_16p trans_values, png_color_16p background
2596 #if defined(PNG_READ_GAMMA_SUPPORTED)
2597    , png_color_16p background_1,
2598    png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
2599    png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
2600    png_uint_16pp gamma_16_to_1, int gamma_shift
2601 #endif
2602    )
2603 {
2604    png_bytep sp, dp;
2605    png_uint_32 i;
2606    png_uint_32 row_width=row_info->width;
2607    int shift;
2608
2609    png_debug(1, "in png_do_background\n");
2610    if (background != NULL &&
2611 #if defined(PNG_USELESS_TESTS_SUPPORTED)
2612        row != NULL && row_info != NULL &&
2613 #endif
2614       (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
2615       (row_info->color_type != PNG_COLOR_TYPE_PALETTE && trans_values)))
2616    {
2617       switch (row_info->color_type)
2618       {
2619          case PNG_COLOR_TYPE_GRAY:
2620          {
2621             switch (row_info->bit_depth)
2622             {
2623                case 1:
2624                {
2625                   sp = row;
2626                   shift = 7;
2627                   for (i = 0; i < row_width; i++)
2628                   {
2629                      if ((png_uint_16)((*sp >> shift) & 0x01)
2630                         == trans_values->gray)
2631                      {
2632                         *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2633                         *sp |= (png_byte)(background->gray << shift);
2634                      }
2635                      if (!shift)
2636                      {
2637                         shift = 7;
2638                         sp++;
2639                      }
2640                      else
2641                         shift--;
2642                   }
2643                   break;
2644                }
2645                case 2:
2646                {
2647 #if defined(PNG_READ_GAMMA_SUPPORTED)
2648                   if (gamma_table != NULL)
2649                   {
2650                      sp = row;
2651                      shift = 6;
2652                      for (i = 0; i < row_width; i++)
2653                      {
2654                         if ((png_uint_16)((*sp >> shift) & 0x03)
2655                             == trans_values->gray)
2656                         {
2657                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2658                            *sp |= (png_byte)(background->gray << shift);
2659                         }
2660                         else
2661                         {
2662                            png_byte p = (png_byte)((*sp >> shift) & 0x03);
2663                            png_byte g = (png_byte)((gamma_table [p | (p << 2) |
2664                                (p << 4) | (p << 6)] >> 6) & 0x03);
2665                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2666                            *sp |= (png_byte)(g << shift);
2667                         }
2668                         if (!shift)
2669                         {
2670                            shift = 6;
2671                            sp++;
2672                         }
2673                         else
2674                            shift -= 2;
2675                      }
2676                   }
2677                   else
2678 #endif
2679                   {
2680                      sp = row;
2681                      shift = 6;
2682                      for (i = 0; i < row_width; i++)
2683                      {
2684                         if ((png_uint_16)((*sp >> shift) & 0x03)
2685                             == trans_values->gray)
2686                         {
2687                            *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2688                            *sp |= (png_byte)(background->gray << shift);
2689                         }
2690                         if (!shift)
2691                         {
2692                            shift = 6;
2693                            sp++;
2694                         }
2695                         else
2696                            shift -= 2;
2697                      }
2698                   }
2699                   break;
2700                }
2701                case 4:
2702                {
2703 #if defined(PNG_READ_GAMMA_SUPPORTED)
2704                   if (gamma_table != NULL)
2705                   {
2706                      sp = row;
2707                      shift = 4;
2708                      for (i = 0; i < row_width; i++)
2709                      {
2710                         if ((png_uint_16)((*sp >> shift) & 0x0f)
2711                             == trans_values->gray)
2712                         {
2713                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2714                            *sp |= (png_byte)(background->gray << shift);
2715                         }
2716                         else
2717                         {
2718                            png_byte p = (png_byte)((*sp >> shift) & 0x0f);
2719                            png_byte g = (png_byte)((gamma_table[p |
2720                              (p << 4)] >> 4) & 0x0f);
2721                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2722                            *sp |= (png_byte)(g << shift);
2723                         }
2724                         if (!shift)
2725                         {
2726                            shift = 4;
2727                            sp++;
2728                         }
2729                         else
2730                            shift -= 4;
2731                      }
2732                   }
2733                   else
2734 #endif
2735                   {
2736                      sp = row;
2737                      shift = 4;
2738                      for (i = 0; i < row_width; i++)
2739                      {
2740                         if ((png_uint_16)((*sp >> shift) & 0x0f)
2741                             == trans_values->gray)
2742                         {
2743                            *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2744                            *sp |= (png_byte)(background->gray << shift);
2745                         }
2746                         if (!shift)
2747                         {
2748                            shift = 4;
2749                            sp++;
2750                         }
2751                         else
2752                            shift -= 4;
2753                      }
2754                   }
2755                   break;
2756                }
2757                case 8:
2758                {
2759 #if defined(PNG_READ_GAMMA_SUPPORTED)
2760                   if (gamma_table != NULL)
2761                   {
2762                      sp = row;
2763                      for (i = 0; i < row_width; i++, sp++)
2764                      {
2765                         if (*sp == trans_values->gray)
2766                         {
2767                            *sp = (png_byte)background->gray;
2768                         }
2769                         else
2770                         {
2771                            *sp = gamma_table[*sp];
2772                         }
2773                      }
2774                   }
2775                   else
2776 #endif
2777                   {
2778                      sp = row;
2779                      for (i = 0; i < row_width; i++, sp++)
2780                      {
2781                         if (*sp == trans_values->gray)
2782                         {
2783                            *sp = (png_byte)background->gray;
2784                         }
2785                      }
2786                   }
2787                   break;
2788                }
2789                case 16:
2790                {
2791 #if defined(PNG_READ_GAMMA_SUPPORTED)
2792                   if (gamma_16 != NULL)
2793                   {
2794                      sp = row;
2795                      for (i = 0; i < row_width; i++, sp += 2)
2796                      {
2797                         png_uint_16 v;
2798
2799                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2800                         if (v == trans_values->gray)
2801                         {
2802                            /* background is already in screen gamma */
2803                            *sp = (png_byte)((background->gray >> 8) & 0xff);
2804                            *(sp + 1) = (png_byte)(background->gray & 0xff);
2805                         }
2806                         else
2807                         {
2808                            v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2809                            *sp = (png_byte)((v >> 8) & 0xff);
2810                            *(sp + 1) = (png_byte)(v & 0xff);
2811                         }
2812                      }
2813                   }
2814                   else
2815 #endif
2816                   {
2817                      sp = row;
2818                      for (i = 0; i < row_width; i++, sp += 2)
2819                      {
2820                         png_uint_16 v;
2821
2822                         v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2823                         if (v == trans_values->gray)
2824                         {
2825                            *sp = (png_byte)((background->gray >> 8) & 0xff);
2826                            *(sp + 1) = (png_byte)(background->gray & 0xff);
2827                         }
2828                      }
2829                   }
2830                   break;
2831                }
2832             }
2833             break;
2834          }
2835          case PNG_COLOR_TYPE_RGB:
2836          {
2837             if (row_info->bit_depth == 8)
2838             {
2839 #if defined(PNG_READ_GAMMA_SUPPORTED)
2840                if (gamma_table != NULL)
2841                {
2842                   sp = row;
2843                   for (i = 0; i < row_width; i++, sp += 3)
2844                   {
2845                      if (*sp == trans_values->red &&
2846                         *(sp + 1) == trans_values->green &&
2847                         *(sp + 2) == trans_values->blue)
2848                      {
2849                         *sp = (png_byte)background->red;
2850                         *(sp + 1) = (png_byte)background->green;
2851                         *(sp + 2) = (png_byte)background->blue;
2852                      }
2853                      else
2854                      {
2855                         *sp = gamma_table[*sp];
2856                         *(sp + 1) = gamma_table[*(sp + 1)];
2857                         *(sp + 2) = gamma_table[*(sp + 2)];
2858                      }
2859                   }
2860                }
2861                else
2862 #endif
2863                {
2864                   sp = row;
2865                   for (i = 0; i < row_width; i++, sp += 3)
2866                   {
2867                      if (*sp == trans_values->red &&
2868                         *(sp + 1) == trans_values->green &&
2869                         *(sp + 2) == trans_values->blue)
2870                      {
2871                         *sp = (png_byte)background->red;
2872                         *(sp + 1) = (png_byte)background->green;
2873                         *(sp + 2) = (png_byte)background->blue;
2874                      }
2875                   }
2876                }
2877             }
2878             else /* if (row_info->bit_depth == 16) */
2879             {
2880 #if defined(PNG_READ_GAMMA_SUPPORTED)
2881                if (gamma_16 != NULL)
2882                {
2883                   sp = row;
2884                   for (i = 0; i < row_width; i++, sp += 6)
2885                   {
2886                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
2887                      png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2888                      png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2889                      if (r == trans_values->red && g == trans_values->green &&
2890                         b == trans_values->blue)
2891                      {
2892                         /* background is already in screen gamma */
2893                         *sp = (png_byte)((background->red >> 8) & 0xff);
2894                         *(sp + 1) = (png_byte)(background->red & 0xff);
2895                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2896                         *(sp + 3) = (png_byte)(background->green & 0xff);
2897                         *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2898                         *(sp + 5) = (png_byte)(background->blue & 0xff);
2899                      }
2900                      else
2901                      {
2902                         png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
2903                         *sp = (png_byte)((v >> 8) & 0xff);
2904                         *(sp + 1) = (png_byte)(v & 0xff);
2905                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
2906                         *(sp + 2) = (png_byte)((v >> 8) & 0xff);
2907                         *(sp + 3) = (png_byte)(v & 0xff);
2908                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
2909                         *(sp + 4) = (png_byte)((v >> 8) & 0xff);
2910                         *(sp + 5) = (png_byte)(v & 0xff);
2911                      }
2912                   }
2913                }
2914                else
2915 #endif
2916                {
2917                   sp = row;
2918                   for (i = 0; i < row_width; i++, sp += 6)
2919                   {
2920                      png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp+1));
2921                      png_uint_16 g = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
2922                      png_uint_16 b = (png_uint_16)(((*(sp+4)) << 8) + *(sp+5));
2923
2924                      if (r == trans_values->red && g == trans_values->green &&
2925                         b == trans_values->blue)
2926                      {
2927                         *sp = (png_byte)((background->red >> 8) & 0xff);
2928                         *(sp + 1) = (png_byte)(background->red & 0xff);
2929                         *(sp + 2) = (png_byte)((background->green >> 8) & 0xff);
2930                         *(sp + 3) = (png_byte)(background->green & 0xff);
2931                         *(sp + 4) = (png_byte)((background->blue >> 8) & 0xff);
2932                         *(sp + 5) = (png_byte)(background->blue & 0xff);
2933                      }
2934                   }
2935                }
2936             }
2937             break;
2938          }
2939          case PNG_COLOR_TYPE_GRAY_ALPHA:
2940          {
2941             if (row_info->bit_depth == 8)
2942             {
2943 #if defined(PNG_READ_GAMMA_SUPPORTED)
2944                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
2945                    gamma_table != NULL)
2946                {
2947                   sp = row;
2948                   dp = row;
2949                   for (i = 0; i < row_width; i++, sp += 2, dp++)
2950                   {
2951                      png_uint_16 a = *(sp + 1);
2952
2953                      if (a == 0xff)
2954                      {
2955                         *dp = gamma_table[*sp];
2956                      }
2957                      else if (a == 0)
2958                      {
2959                         /* background is already in screen gamma */
2960                         *dp = (png_byte)background->gray;
2961                      }
2962                      else
2963                      {
2964                         png_byte v, w;
2965
2966                         v = gamma_to_1[*sp];
2967                         png_composite(w, v, a, background_1->gray);
2968                         *dp = gamma_from_1[w];
2969                      }
2970                   }
2971                }
2972                else
2973 #endif
2974                {
2975                   sp = row;
2976                   dp = row;
2977                   for (i = 0; i < row_width; i++, sp += 2, dp++)
2978                   {
2979                      png_byte a = *(sp + 1);
2980
2981                      if (a == 0xff)
2982                      {
2983                         *dp = *sp;
2984                      }
2985 #if defined(PNG_READ_GAMMA_SUPPORTED)
2986                      else if (a == 0)
2987                      {
2988                         *dp = (png_byte)background->gray;
2989                      }
2990                      else
2991                      {
2992                         png_composite(*dp, *sp, a, background_1->gray);
2993                      }
2994 #else
2995                      *dp = (png_byte)background->gray;
2996 #endif
2997                   }
2998                }
2999             }
3000             else /* if (png_ptr->bit_depth == 16) */
3001             {
3002 #if defined(PNG_READ_GAMMA_SUPPORTED)
3003                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3004                    gamma_16_to_1 != NULL)
3005                {
3006                   sp = row;
3007                   dp = row;
3008                   for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3009                   {
3010                      png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3011
3012                      if (a == (png_uint_16)0xffff)
3013                      {
3014                         png_uint_16 v;
3015
3016                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3017                         *dp = (png_byte)((v >> 8) & 0xff);
3018                         *(dp + 1) = (png_byte)(v & 0xff);
3019                      }
3020 #if defined(PNG_READ_GAMMA_SUPPORTED)
3021                      else if (a == 0)
3022 #else
3023                      else
3024 #endif
3025                      {
3026                         /* background is already in screen gamma */
3027                         *dp = (png_byte)((background->gray >> 8) & 0xff);
3028                         *(dp + 1) = (png_byte)(background->gray & 0xff);
3029                      }
3030 #if defined(PNG_READ_GAMMA_SUPPORTED)
3031                      else
3032                      {
3033                         png_uint_16 g, v, w;
3034
3035                         g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3036                         png_composite_16(v, g, a, background_1->gray);
3037                         w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
3038                         *dp = (png_byte)((w >> 8) & 0xff);
3039                         *(dp + 1) = (png_byte)(w & 0xff);
3040                      }
3041 #endif
3042                   }
3043                }
3044                else
3045 #endif
3046                {
3047                   sp = row;
3048                   dp = row;
3049                   for (i = 0; i < row_width; i++, sp += 4, dp += 2)
3050                   {
3051                      png_uint_16 a = (png_uint_16)(((*(sp+2)) << 8) + *(sp+3));
3052                      if (a == (png_uint_16)0xffff)
3053                      {
3054                         png_memcpy(dp, sp, 2);
3055                      }
3056 #if defined(PNG_READ_GAMMA_SUPPORTED)
3057                      else if (a == 0)
3058 #else
3059                      else
3060 #endif
3061                      {
3062                         *dp = (png_byte)((background->gray >> 8) & 0xff);
3063                         *(dp + 1) = (png_byte)(background->gray & 0xff);
3064                      }
3065 #if defined(PNG_READ_GAMMA_SUPPORTED)
3066                      else
3067                      {
3068                         png_uint_16 g, v;
3069
3070                         g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3071                         png_composite_16(v, g, a, background_1->gray);
3072                         *dp = (png_byte)((v >> 8) & 0xff);
3073                         *(dp + 1) = (png_byte)(v & 0xff);
3074                      }
3075 #endif
3076                   }
3077                }
3078             }
3079             break;
3080          }
3081          case PNG_COLOR_TYPE_RGB_ALPHA:
3082          {
3083             if (row_info->bit_depth == 8)
3084             {
3085 #if defined(PNG_READ_GAMMA_SUPPORTED)
3086                if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
3087                    gamma_table != NULL)
3088                {
3089                   sp = row;
3090                   dp = row;
3091                   for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3092                   {
3093                      png_byte a = *(sp + 3);
3094
3095                      if (a == 0xff)
3096                      {
3097                         *dp = gamma_table[*sp];
3098                         *(dp + 1) = gamma_table[*(sp + 1)];
3099                         *(dp + 2) = gamma_table[*(sp + 2)];
3100                      }
3101                      else if (a == 0)
3102                      {
3103                         /* background is already in screen gamma */
3104                         *dp = (png_byte)background->red;
3105                         *(dp + 1) = (png_byte)background->green;
3106                         *(dp + 2) = (png_byte)background->blue;
3107                      }
3108                      else
3109                      {
3110                         png_byte v, w;
3111
3112                         v = gamma_to_1[*sp];
3113                         png_composite(w, v, a, background_1->red);
3114                         *dp = gamma_from_1[w];
3115                         v = gamma_to_1[*(sp + 1)];
3116                         png_composite(w, v, a, background_1->green);
3117                         *(dp + 1) = gamma_from_1[w];
3118                         v = gamma_to_1[*(sp + 2)];
3119                         png_composite(w, v, a, background_1->blue);
3120                         *(dp + 2) = gamma_from_1[w];
3121                      }
3122                   }
3123                }
3124                else
3125 #endif
3126                {
3127                   sp = row;
3128                   dp = row;
3129                   for (i = 0; i < row_width; i++, sp += 4, dp += 3)
3130                   {
3131                      png_byte a = *(sp + 3);
3132
3133                      if (a == 0xff)
3134                      {
3135                         *dp = *sp;
3136                         *(dp + 1) = *(sp + 1);
3137                         *(dp + 2) = *(sp + 2);
3138                      }
3139                      else if (a == 0)
3140                      {
3141                         *dp = (png_byte)background->red;
3142                         *(dp + 1) = (png_byte)background->green;
3143                         *(dp + 2) = (png_byte)background->blue;
3144                      }
3145                      else
3146                      {
3147                         png_composite(*dp, *sp, a, background->red);
3148                         png_composite(*(dp + 1), *(sp + 1), a,
3149                            background->green);
3150                         png_composite(*(dp + 2), *(sp + 2), a,
3151                            background->blue);
3152                      }
3153                   }
3154                }
3155             }
3156             else /* if (row_info->bit_depth == 16) */
3157             {
3158 #if defined(PNG_READ_GAMMA_SUPPORTED)
3159                if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
3160                    gamma_16_to_1 != NULL)
3161                {
3162                   sp = row;
3163                   dp = row;
3164                   for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3165                   {
3166                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3167                          << 8) + (png_uint_16)(*(sp + 7)));
3168                      if (a == (png_uint_16)0xffff)
3169                      {
3170                         png_uint_16 v;
3171
3172                         v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
3173                         *dp = (png_byte)((v >> 8) & 0xff);
3174                         *(dp + 1) = (png_byte)(v & 0xff);
3175                         v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
3176                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3177                         *(dp + 3) = (png_byte)(v & 0xff);
3178                         v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
3179                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3180                         *(dp + 5) = (png_byte)(v & 0xff);
3181                      }
3182                      else if (a == 0)
3183                      {
3184                         /* background is already in screen gamma */
3185                         *dp = (png_byte)((background->red >> 8) & 0xff);
3186                         *(dp + 1) = (png_byte)(background->red & 0xff);
3187                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3188                         *(dp + 3) = (png_byte)(background->green & 0xff);
3189                         *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3190                         *(dp + 5) = (png_byte)(background->blue & 0xff);
3191                      }
3192                      else
3193                      {
3194                         png_uint_16 v, w, x;
3195
3196                         v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
3197                         png_composite_16(w, v, a, background_1->red);
3198                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3199                         *dp = (png_byte)((x >> 8) & 0xff);
3200                         *(dp + 1) = (png_byte)(x & 0xff);
3201                         v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
3202                         png_composite_16(w, v, a, background_1->green);
3203                         x = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
3204                         *(dp + 2) = (png_byte)((x >> 8) & 0xff);
3205                         *(dp + 3) = (png_byte)(x & 0xff);
3206                         v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
3207                         png_composite_16(w, v, a, background_1->blue);
3208                         x = gamma_16_from_1[(w & 0xff) >> gamma_shift][w >> 8];
3209                         *(dp + 4) = (png_byte)((x >> 8) & 0xff);
3210                         *(dp + 5) = (png_byte)(x & 0xff);
3211                      }
3212                   }
3213                }
3214                else
3215 #endif
3216                {
3217                   sp = row;
3218                   dp = row;
3219                   for (i = 0; i < row_width; i++, sp += 8, dp += 6)
3220                   {
3221                      png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
3222                         << 8) + (png_uint_16)(*(sp + 7)));
3223                      if (a == (png_uint_16)0xffff)
3224                      {
3225                         png_memcpy(dp, sp, 6);
3226                      }
3227                      else if (a == 0)
3228                      {
3229                         *dp = (png_byte)((background->red >> 8) & 0xff);
3230                         *(dp + 1) = (png_byte)(background->red & 0xff);
3231                         *(dp + 2) = (png_byte)((background->green >> 8) & 0xff);
3232                         *(dp + 3) = (png_byte)(background->green & 0xff);
3233                         *(dp + 4) = (png_byte)((background->blue >> 8) & 0xff);
3234                         *(dp + 5) = (png_byte)(background->blue & 0xff);
3235                      }
3236                      else
3237                      {
3238                         png_uint_16 v;
3239
3240                         png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
3241                         png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
3242                             + *(sp + 3));
3243                         png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
3244                             + *(sp + 5));
3245
3246                         png_composite_16(v, r, a, background->red);
3247                         *dp = (png_byte)((v >> 8) & 0xff);
3248                         *(dp + 1) = (png_byte)(v & 0xff);
3249                         png_composite_16(v, g, a, background->green);
3250                         *(dp + 2) = (png_byte)((v >> 8) & 0xff);
3251                         *(dp + 3) = (png_byte)(v & 0xff);
3252                         png_composite_16(v, b, a, background->blue);
3253                         *(dp + 4) = (png_byte)((v >> 8) & 0xff);
3254                         *(dp + 5) = (png_byte)(v & 0xff);
3255                      }
3256                   }
3257                }
3258             }
3259             break;
3260          }
3261       }
3262
3263       if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
3264       {
3265          row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
3266          row_info->channels--;
3267          row_info->pixel_depth = (png_byte)(row_info->channels *
3268             row_info->bit_depth);
3269          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3270       }
3271    }
3272 }
3273 #endif
3274
3275 #if defined(PNG_READ_GAMMA_SUPPORTED)
3276 /* Gamma correct the image, avoiding the alpha channel.  Make sure
3277  * you do this after you deal with the transparency issue on grayscale
3278  * or RGB images. If your bit depth is 8, use gamma_table, if it
3279  * is 16, use gamma_16_table and gamma_shift.  Build these with
3280  * build_gamma_table().
3281  */
3282 void /* PRIVATE */
3283 png_do_gamma(png_row_infop row_info, png_bytep row,
3284    png_bytep gamma_table, png_uint_16pp gamma_16_table,
3285    int gamma_shift)
3286 {
3287    png_bytep sp;
3288    png_uint_32 i;
3289    png_uint_32 row_width=row_info->width;
3290
3291    png_debug(1, "in png_do_gamma\n");
3292    if (
3293 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3294        row != NULL && row_info != NULL &&
3295 #endif
3296        ((row_info->bit_depth <= 8 && gamma_table != NULL) ||
3297         (row_info->bit_depth == 16 && gamma_16_table != NULL)))
3298    {
3299       switch (row_info->color_type)
3300       {
3301          case PNG_COLOR_TYPE_RGB:
3302          {
3303             if (row_info->bit_depth == 8)
3304             {
3305                sp = row;
3306                for (i = 0; i < row_width; i++)
3307                {
3308                   *sp = gamma_table[*sp];
3309                   sp++;
3310                   *sp = gamma_table[*sp];
3311                   sp++;
3312                   *sp = gamma_table[*sp];
3313                   sp++;
3314                }
3315             }
3316             else /* if (row_info->bit_depth == 16) */
3317             {
3318                sp = row;
3319                for (i = 0; i < row_width; i++)
3320                {
3321                   png_uint_16 v;
3322
3323                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3324                   *sp = (png_byte)((v >> 8) & 0xff);
3325                   *(sp + 1) = (png_byte)(v & 0xff);
3326                   sp += 2;
3327                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3328                   *sp = (png_byte)((v >> 8) & 0xff);
3329                   *(sp + 1) = (png_byte)(v & 0xff);
3330                   sp += 2;
3331                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3332                   *sp = (png_byte)((v >> 8) & 0xff);
3333                   *(sp + 1) = (png_byte)(v & 0xff);
3334                   sp += 2;
3335                }
3336             }
3337             break;
3338          }
3339          case PNG_COLOR_TYPE_RGB_ALPHA:
3340          {
3341             if (row_info->bit_depth == 8)
3342             {
3343                sp = row;
3344                for (i = 0; i < row_width; i++)
3345                {
3346                   *sp = gamma_table[*sp];
3347                   sp++;
3348                   *sp = gamma_table[*sp];
3349                   sp++;
3350                   *sp = gamma_table[*sp];
3351                   sp++;
3352                   sp++;
3353                }
3354             }
3355             else /* if (row_info->bit_depth == 16) */
3356             {
3357                sp = row;
3358                for (i = 0; i < row_width; i++)
3359                {
3360                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3361                   *sp = (png_byte)((v >> 8) & 0xff);
3362                   *(sp + 1) = (png_byte)(v & 0xff);
3363                   sp += 2;
3364                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3365                   *sp = (png_byte)((v >> 8) & 0xff);
3366                   *(sp + 1) = (png_byte)(v & 0xff);
3367                   sp += 2;
3368                   v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3369                   *sp = (png_byte)((v >> 8) & 0xff);
3370                   *(sp + 1) = (png_byte)(v & 0xff);
3371                   sp += 4;
3372                }
3373             }
3374             break;
3375          }
3376          case PNG_COLOR_TYPE_GRAY_ALPHA:
3377          {
3378             if (row_info->bit_depth == 8)
3379             {
3380                sp = row;
3381                for (i = 0; i < row_width; i++)
3382                {
3383                   *sp = gamma_table[*sp];
3384                   sp += 2;
3385                }
3386             }
3387             else /* if (row_info->bit_depth == 16) */
3388             {
3389                sp = row;
3390                for (i = 0; i < row_width; i++)
3391                {
3392                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3393                   *sp = (png_byte)((v >> 8) & 0xff);
3394                   *(sp + 1) = (png_byte)(v & 0xff);
3395                   sp += 4;
3396                }
3397             }
3398             break;
3399          }
3400          case PNG_COLOR_TYPE_GRAY:
3401          {
3402             if (row_info->bit_depth == 2)
3403             {
3404                sp = row;
3405                for (i = 0; i < row_width; i += 4)
3406                {
3407                   int a = *sp & 0xc0;
3408                   int b = *sp & 0x30;
3409                   int c = *sp & 0x0c;
3410                   int d = *sp & 0x03;
3411
3412                   *sp = (png_byte)(
3413                         ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
3414                         ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
3415                         ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
3416                         ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
3417                   sp++;
3418                }
3419             }
3420             if (row_info->bit_depth == 4)
3421             {
3422                sp = row;
3423                for (i = 0; i < row_width; i += 2)
3424                {
3425                   int msb = *sp & 0xf0;
3426                   int lsb = *sp & 0x0f;
3427
3428                   *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
3429                           | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
3430                   sp++;
3431                }
3432             }
3433             else if (row_info->bit_depth == 8)
3434             {
3435                sp = row;
3436                for (i = 0; i < row_width; i++)
3437                {
3438                   *sp = gamma_table[*sp];
3439                   sp++;
3440                }
3441             }
3442             else if (row_info->bit_depth == 16)
3443             {
3444                sp = row;
3445                for (i = 0; i < row_width; i++)
3446                {
3447                   png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
3448                   *sp = (png_byte)((v >> 8) & 0xff);
3449                   *(sp + 1) = (png_byte)(v & 0xff);
3450                   sp += 2;
3451                }
3452             }
3453             break;
3454          }
3455       }
3456    }
3457 }
3458 #endif
3459
3460 #if defined(PNG_READ_EXPAND_SUPPORTED)
3461 /* Expands a palette row to an RGB or RGBA row depending
3462  * upon whether you supply trans and num_trans.
3463  */
3464 void /* PRIVATE */
3465 png_do_expand_palette(png_row_infop row_info, png_bytep row,
3466    png_colorp palette, png_bytep trans, int num_trans)
3467 {
3468    int shift, value;
3469    png_bytep sp, dp;
3470    png_uint_32 i;
3471    png_uint_32 row_width=row_info->width;
3472
3473    png_debug(1, "in png_do_expand_palette\n");
3474    if (
3475 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3476        row != NULL && row_info != NULL &&
3477 #endif
3478        row_info->color_type == PNG_COLOR_TYPE_PALETTE)
3479    {
3480       if (row_info->bit_depth < 8)
3481       {
3482          switch (row_info->bit_depth)
3483          {
3484             case 1:
3485             {
3486                sp = row + (png_size_t)((row_width - 1) >> 3);
3487                dp = row + (png_size_t)row_width - 1;
3488                shift = 7 - (int)((row_width + 7) & 0x07);
3489                for (i = 0; i < row_width; i++)
3490                {
3491                   if ((*sp >> shift) & 0x01)
3492                      *dp = 1;
3493                   else
3494                      *dp = 0;
3495                   if (shift == 7)
3496                   {
3497                      shift = 0;
3498                      sp--;
3499                   }
3500                   else
3501                      shift++;
3502
3503                   dp--;
3504                }
3505                break;
3506             }
3507             case 2:
3508             {
3509                sp = row + (png_size_t)((row_width - 1) >> 2);
3510                dp = row + (png_size_t)row_width - 1;
3511                shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3512                for (i = 0; i < row_width; i++)
3513                {
3514                   value = (*sp >> shift) & 0x03;
3515                   *dp = (png_byte)value;
3516                   if (shift == 6)
3517                   {
3518                      shift = 0;
3519                      sp--;
3520                   }
3521                   else
3522                      shift += 2;
3523
3524                   dp--;
3525                }
3526                break;
3527             }
3528             case 4:
3529             {
3530                sp = row + (png_size_t)((row_width - 1) >> 1);
3531                dp = row + (png_size_t)row_width - 1;
3532                shift = (int)((row_width & 0x01) << 2);
3533                for (i = 0; i < row_width; i++)
3534                {
3535                   value = (*sp >> shift) & 0x0f;
3536                   *dp = (png_byte)value;
3537                   if (shift == 4)
3538                   {
3539                      shift = 0;
3540                      sp--;
3541                   }
3542                   else
3543                      shift += 4;
3544
3545                   dp--;
3546                }
3547                break;
3548             }
3549          }
3550          row_info->bit_depth = 8;
3551          row_info->pixel_depth = 8;
3552          row_info->rowbytes = row_width;
3553       }
3554       switch (row_info->bit_depth)
3555       {
3556          case 8:
3557          {
3558             if (trans != NULL)
3559             {
3560                sp = row + (png_size_t)row_width - 1;
3561                dp = row + (png_size_t)(row_width << 2) - 1;
3562
3563                for (i = 0; i < row_width; i++)
3564                {
3565                   if ((int)(*sp) >= num_trans)
3566                      *dp-- = 0xff;
3567                   else
3568                      *dp-- = trans[*sp];
3569                   *dp-- = palette[*sp].blue;
3570                   *dp-- = palette[*sp].green;
3571                   *dp-- = palette[*sp].red;
3572                   sp--;
3573                }
3574                row_info->bit_depth = 8;
3575                row_info->pixel_depth = 32;
3576                row_info->rowbytes = row_width * 4;
3577                row_info->color_type = 6;
3578                row_info->channels = 4;
3579             }
3580             else
3581             {
3582                sp = row + (png_size_t)row_width - 1;
3583                dp = row + (png_size_t)(row_width * 3) - 1;
3584
3585                for (i = 0; i < row_width; i++)
3586                {
3587                   *dp-- = palette[*sp].blue;
3588                   *dp-- = palette[*sp].green;
3589                   *dp-- = palette[*sp].red;
3590                   sp--;
3591                }
3592                row_info->bit_depth = 8;
3593                row_info->pixel_depth = 24;
3594                row_info->rowbytes = row_width * 3;
3595                row_info->color_type = 2;
3596                row_info->channels = 3;
3597             }
3598             break;
3599          }
3600       }
3601    }
3602 }
3603
3604 /* If the bit depth < 8, it is expanded to 8.  Also, if the
3605  * transparency value is supplied, an alpha channel is built.
3606  */
3607 void /* PRIVATE */
3608 png_do_expand(png_row_infop row_info, png_bytep row,
3609    png_color_16p trans_value)
3610 {
3611    int shift, value;
3612    png_bytep sp, dp;
3613    png_uint_32 i;
3614    png_uint_32 row_width=row_info->width;
3615
3616    png_debug(1, "in png_do_expand\n");
3617 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3618    if (row != NULL && row_info != NULL)
3619 #endif
3620    {
3621       if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
3622       {
3623          png_uint_16 gray = (png_uint_16)(trans_value ? trans_value->gray : 0);
3624
3625          if (row_info->bit_depth < 8)
3626          {
3627             switch (row_info->bit_depth)
3628             {
3629                case 1:
3630                {
3631                   gray = (png_uint_16)(gray*0xff);
3632                   sp = row + (png_size_t)((row_width - 1) >> 3);
3633                   dp = row + (png_size_t)row_width - 1;
3634                   shift = 7 - (int)((row_width + 7) & 0x07);
3635                   for (i = 0; i < row_width; i++)
3636                   {
3637                      if ((*sp >> shift) & 0x01)
3638                         *dp = 0xff;
3639                      else
3640                         *dp = 0;
3641                      if (shift == 7)
3642                      {
3643                         shift = 0;
3644                         sp--;
3645                      }
3646                      else
3647                         shift++;
3648
3649                      dp--;
3650                   }
3651                   break;
3652                }
3653                case 2:
3654                {
3655                   gray = (png_uint_16)(gray*0x55);
3656                   sp = row + (png_size_t)((row_width - 1) >> 2);
3657                   dp = row + (png_size_t)row_width - 1;
3658                   shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
3659                   for (i = 0; i < row_width; i++)
3660                   {
3661                      value = (*sp >> shift) & 0x03;
3662                      *dp = (png_byte)(value | (value << 2) | (value << 4) |
3663                         (value << 6));
3664                      if (shift == 6)
3665                      {
3666                         shift = 0;
3667                         sp--;
3668                      }
3669                      else
3670                         shift += 2;
3671
3672                      dp--;
3673                   }
3674                   break;
3675                }
3676                case 4:
3677                {
3678                   gray = (png_uint_16)(gray*0x11);
3679                   sp = row + (png_size_t)((row_width - 1) >> 1);
3680                   dp = row + (png_size_t)row_width - 1;
3681                   shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
3682                   for (i = 0; i < row_width; i++)
3683                   {
3684                      value = (*sp >> shift) & 0x0f;
3685                      *dp = (png_byte)(value | (value << 4));
3686                      if (shift == 4)
3687                      {
3688                         shift = 0;
3689                         sp--;
3690                      }
3691                      else
3692                         shift = 4;
3693
3694                      dp--;
3695                   }
3696                   break;
3697                }
3698             }
3699             row_info->bit_depth = 8;
3700             row_info->pixel_depth = 8;
3701             row_info->rowbytes = row_width;
3702          }
3703
3704          if (trans_value != NULL)
3705          {
3706             if (row_info->bit_depth == 8)
3707             {
3708                sp = row + (png_size_t)row_width - 1;
3709                dp = row + (png_size_t)(row_width << 1) - 1;
3710                for (i = 0; i < row_width; i++)
3711                {
3712                   if (*sp == gray)
3713                      *dp-- = 0;
3714                   else
3715                      *dp-- = 0xff;
3716                   *dp-- = *sp--;
3717                }
3718             }
3719             else if (row_info->bit_depth == 16)
3720             {
3721                sp = row + row_info->rowbytes - 1;
3722                dp = row + (row_info->rowbytes << 1) - 1;
3723                for (i = 0; i < row_width; i++)
3724                {
3725                   if (((png_uint_16)*(sp) |
3726                      ((png_uint_16)*(sp - 1) << 8)) == gray)
3727                   {
3728                      *dp-- = 0;
3729                      *dp-- = 0;
3730                   }
3731                   else
3732                   {
3733                      *dp-- = 0xff;
3734                      *dp-- = 0xff;
3735                   }
3736                   *dp-- = *sp--;
3737                   *dp-- = *sp--;
3738                }
3739             }
3740             row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
3741             row_info->channels = 2;
3742             row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
3743             row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
3744                row_width);
3745          }
3746       }
3747       else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_value)
3748       {
3749          if (row_info->bit_depth == 8)
3750          {
3751             sp = row + (png_size_t)row_info->rowbytes - 1;
3752             dp = row + (png_size_t)(row_width << 2) - 1;
3753             for (i = 0; i < row_width; i++)
3754             {
3755                if (*(sp - 2) == trans_value->red &&
3756                   *(sp - 1) == trans_value->green &&
3757                   *(sp - 0) == trans_value->blue)
3758                   *dp-- = 0;
3759                else
3760                   *dp-- = 0xff;
3761                *dp-- = *sp--;
3762                *dp-- = *sp--;
3763                *dp-- = *sp--;
3764             }
3765          }
3766          else if (row_info->bit_depth == 16)
3767          {
3768             sp = row + row_info->rowbytes - 1;
3769             dp = row + (png_size_t)(row_width << 3) - 1;
3770             for (i = 0; i < row_width; i++)
3771             {
3772                if ((((png_uint_16)*(sp - 4) |
3773                   ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
3774                   (((png_uint_16)*(sp - 2) |
3775                   ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
3776                   (((png_uint_16)*(sp - 0) |
3777                   ((png_uint_16)*(sp - 1) << 8)) == trans_value->blue))
3778                {
3779                   *dp-- = 0;
3780                   *dp-- = 0;
3781                }
3782                else
3783                {
3784                   *dp-- = 0xff;
3785                   *dp-- = 0xff;
3786                }
3787                *dp-- = *sp--;
3788                *dp-- = *sp--;
3789                *dp-- = *sp--;
3790                *dp-- = *sp--;
3791                *dp-- = *sp--;
3792                *dp-- = *sp--;
3793             }
3794          }
3795          row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
3796          row_info->channels = 4;
3797          row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
3798          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3799       }
3800    }
3801 }
3802 #endif
3803
3804 #if defined(PNG_READ_DITHER_SUPPORTED)
3805 void /* PRIVATE */
3806 png_do_dither(png_row_infop row_info, png_bytep row,
3807     png_bytep palette_lookup, png_bytep dither_lookup)
3808 {
3809    png_bytep sp, dp;
3810    png_uint_32 i;
3811    png_uint_32 row_width=row_info->width;
3812
3813    png_debug(1, "in png_do_dither\n");
3814 #if defined(PNG_USELESS_TESTS_SUPPORTED)
3815    if (row != NULL && row_info != NULL)
3816 #endif
3817    {
3818       if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
3819          palette_lookup && row_info->bit_depth == 8)
3820       {
3821          int r, g, b, p;
3822          sp = row;
3823          dp = row;
3824          for (i = 0; i < row_width; i++)
3825          {
3826             r = *sp++;
3827             g = *sp++;
3828             b = *sp++;
3829
3830             /* this looks real messy, but the compiler will reduce
3831                it down to a reasonable formula.  For example, with
3832                5 bits per color, we get:
3833                p = (((r >> 3) & 0x1f) << 10) |
3834                   (((g >> 3) & 0x1f) << 5) |
3835                   ((b >> 3) & 0x1f);
3836                */
3837             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3838                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3839                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3840                (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3841                ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3842                (PNG_DITHER_BLUE_BITS)) |
3843                ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3844                ((1 << PNG_DITHER_BLUE_BITS) - 1));
3845
3846             *dp++ = palette_lookup[p];
3847          }
3848          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3849          row_info->channels = 1;
3850          row_info->pixel_depth = row_info->bit_depth;
3851          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3852       }
3853       else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
3854          palette_lookup != NULL && row_info->bit_depth == 8)
3855       {
3856          int r, g, b, p;
3857          sp = row;
3858          dp = row;
3859          for (i = 0; i < row_width; i++)
3860          {
3861             r = *sp++;
3862             g = *sp++;
3863             b = *sp++;
3864             sp++;
3865
3866             p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
3867                ((1 << PNG_DITHER_RED_BITS) - 1)) <<
3868                (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
3869                (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
3870                ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
3871                (PNG_DITHER_BLUE_BITS)) |
3872                ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
3873                ((1 << PNG_DITHER_BLUE_BITS) - 1));
3874
3875             *dp++ = palette_lookup[p];
3876          }
3877          row_info->color_type = PNG_COLOR_TYPE_PALETTE;
3878          row_info->channels = 1;
3879          row_info->pixel_depth = row_info->bit_depth;
3880          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,row_width);
3881       }
3882       else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
3883          dither_lookup && row_info->bit_depth == 8)
3884       {
3885          sp = row;
3886          for (i = 0; i < row_width; i++, sp++)
3887          {
3888             *sp = dither_lookup[*sp];
3889          }
3890       }
3891    }
3892 }
3893 #endif
3894
3895 #ifdef PNG_FLOATING_POINT_SUPPORTED
3896 #if defined(PNG_READ_GAMMA_SUPPORTED)
3897 static int png_gamma_shift[] =
3898    {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
3899
3900 /* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
3901  * tables, we don't make a full table if we are reducing to 8-bit in
3902  * the future.  Note also how the gamma_16 tables are segmented so that
3903  * we don't need to allocate > 64K chunks for a full 16-bit table.
3904  */
3905 void /* PRIVATE */
3906 png_build_gamma_table(png_structp png_ptr)
3907 {
3908   png_debug(1, "in png_build_gamma_table\n");
3909   if(png_ptr->gamma != 0.0)
3910   {
3911    if (png_ptr->bit_depth <= 8)
3912    {
3913       int i;
3914       double g;
3915
3916       if (png_ptr->screen_gamma > .000001)
3917          g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
3918       else
3919          g = 1.0;
3920
3921       png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
3922          (png_uint_32)256);
3923
3924       for (i = 0; i < 256; i++)
3925       {
3926          png_ptr->gamma_table[i] = (png_byte)(pow((double)i / 255.0,
3927             g) * 255.0 + .5);
3928       }
3929
3930 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
3931     defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
3932       if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
3933       {
3934
3935          g = 1.0 / (png_ptr->gamma);
3936
3937          png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
3938             (png_uint_32)256);
3939
3940          for (i = 0; i < 256; i++)
3941          {
3942             png_ptr->gamma_to_1[i] = (png_byte)(pow((double)i / 255.0,
3943                g) * 255.0 + .5);
3944          }
3945
3946
3947          png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
3948             (png_uint_32)256);
3949
3950          if(png_ptr->screen_gamma > 0.000001)
3951             g = 1.0 / png_ptr->screen_gamma;
3952          else
3953             g = png_ptr->gamma;   /* probably doing rgb_to_gray */
3954
3955          for (i = 0; i < 256; i++)
3956          {
3957             png_ptr->gamma_from_1[i] = (png_byte)(pow((double)i / 255.0,
3958                g) * 255.0 + .5);
3959
3960          }
3961       }
3962 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
3963    }
3964    else
3965    {
3966       double g;
3967       int i, j, shift, num;
3968       int sig_bit;
3969       png_uint_32 ig;
3970
3971       if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
3972       {
3973          sig_bit = (int)png_ptr->sig_bit.red;
3974          if ((int)png_ptr->sig_bit.green > sig_bit)
3975             sig_bit = png_ptr->sig_bit.green;
3976          if ((int)png_ptr->sig_bit.blue > sig_bit)
3977             sig_bit = png_ptr->sig_bit.blue;
3978       }
3979       else
3980       {
3981          sig_bit = (int)png_ptr->sig_bit.gray;
3982       }
3983
3984       if (sig_bit > 0)
3985          shift = 16 - sig_bit;
3986       else
3987          shift = 0;
3988
3989       if (png_ptr->transformations & PNG_16_TO_8)
3990       {
3991          if (shift < (16 - PNG_MAX_GAMMA_8))
3992             shift = (16 - PNG_MAX_GAMMA_8);
3993       }
3994
3995       if (shift > 8)
3996          shift = 8;
3997       if (shift < 0)
3998          shift = 0;
3999
4000       png_ptr->gamma_shift = (png_byte)shift;
4001
4002       num = (1 << (8 - shift));
4003
4004       if (png_ptr->screen_gamma > .000001)
4005          g = 1.0 / (png_ptr->gamma * png_ptr->screen_gamma);
4006       else
4007          g = 1.0;
4008
4009       png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
4010          (png_uint_32)(num * png_sizeof (png_uint_16p)));
4011
4012       if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
4013       {
4014          double fin, fout;
4015          png_uint_32 last, max;
4016
4017          for (i = 0; i < num; i++)
4018          {
4019             png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4020                (png_uint_32)(256 * png_sizeof (png_uint_16)));
4021          }
4022
4023          g = 1.0 / g;
4024          last = 0;
4025          for (i = 0; i < 256; i++)
4026          {
4027             fout = ((double)i + 0.5) / 256.0;
4028             fin = pow(fout, g);
4029             max = (png_uint_32)(fin * (double)((png_uint_32)num << 8));
4030             while (last <= max)
4031             {
4032                png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4033                   [(int)(last >> (8 - shift))] = (png_uint_16)(
4034                   (png_uint_16)i | ((png_uint_16)i << 8));
4035                last++;
4036             }
4037          }
4038          while (last < ((png_uint_32)num << 8))
4039          {
4040             png_ptr->gamma_16_table[(int)(last & (0xff >> shift))]
4041                [(int)(last >> (8 - shift))] = (png_uint_16)65535L;
4042             last++;
4043          }
4044       }
4045       else
4046       {
4047          for (i = 0; i < num; i++)
4048          {
4049             png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
4050                (png_uint_32)(256 * png_sizeof (png_uint_16)));
4051
4052             ig = (((png_uint_32)i * (png_uint_32)png_gamma_shift[shift]) >> 4);
4053             for (j = 0; j < 256; j++)
4054             {
4055                png_ptr->gamma_16_table[i][j] =
4056                   (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4057                      65535.0, g) * 65535.0 + .5);
4058             }
4059          }
4060       }
4061
4062 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
4063     defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
4064       if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
4065       {
4066
4067          g = 1.0 / (png_ptr->gamma);
4068
4069          png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
4070             (png_uint_32)(num * png_sizeof (png_uint_16p )));
4071
4072          for (i = 0; i < num; i++)
4073          {
4074             png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
4075                (png_uint_32)(256 * png_sizeof (png_uint_16)));
4076
4077             ig = (((png_uint_32)i *
4078                (png_uint_32)png_gamma_shift[shift]) >> 4);
4079             for (j = 0; j < 256; j++)
4080             {
4081                png_ptr->gamma_16_to_1[i][j] =
4082                   (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4083                      65535.0, g) * 65535.0 + .5);
4084             }
4085          }
4086
4087          if(png_ptr->screen_gamma > 0.000001)
4088             g = 1.0 / png_ptr->screen_gamma;
4089          else
4090             g = png_ptr->gamma;   /* probably doing rgb_to_gray */
4091
4092          png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
4093             (png_uint_32)(num * png_sizeof (png_uint_16p)));
4094
4095          for (i = 0; i < num; i++)
4096          {
4097             png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
4098                (png_uint_32)(256 * png_sizeof (png_uint_16)));
4099
4100             ig = (((png_uint_32)i *
4101                (png_uint_32)png_gamma_shift[shift]) >> 4);
4102             for (j = 0; j < 256; j++)
4103             {
4104                png_ptr->gamma_16_from_1[i][j] =
4105                   (png_uint_16)(pow((double)(ig + ((png_uint_32)j << 8)) /
4106                      65535.0, g) * 65535.0 + .5);
4107             }
4108          }
4109       }
4110 #endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
4111    }
4112  }
4113 }
4114 #endif
4115 /* To do: install integer version of png_build_gamma_table here */
4116 #endif
4117
4118 #if defined(PNG_MNG_FEATURES_SUPPORTED)
4119 /* undoes intrapixel differencing  */
4120 void /* PRIVATE */
4121 png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
4122 {
4123    png_debug(1, "in png_do_read_intrapixel\n");
4124    if (
4125 #if defined(PNG_USELESS_TESTS_SUPPORTED)
4126        row != NULL && row_info != NULL &&
4127 #endif
4128        (row_info->color_type & PNG_COLOR_MASK_COLOR))
4129    {
4130       int bytes_per_pixel;
4131       png_uint_32 row_width = row_info->width;
4132       if (row_info->bit_depth == 8)
4133       {
4134          png_bytep rp;
4135          png_uint_32 i;
4136
4137          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4138             bytes_per_pixel = 3;
4139          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4140             bytes_per_pixel = 4;
4141          else
4142             return;
4143
4144          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4145          {
4146             *(rp) = (png_byte)((256 + *rp + *(rp+1))&0xff);
4147             *(rp+2) = (png_byte)((256 + *(rp+2) + *(rp+1))&0xff);
4148          }
4149       }
4150       else if (row_info->bit_depth == 16)
4151       {
4152          png_bytep rp;
4153          png_uint_32 i;
4154
4155          if (row_info->color_type == PNG_COLOR_TYPE_RGB)
4156             bytes_per_pixel = 6;
4157          else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4158             bytes_per_pixel = 8;
4159          else
4160             return;
4161
4162          for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
4163          {
4164             png_uint_32 s0   = (*(rp  ) << 8) | *(rp+1);
4165             png_uint_32 s1   = (*(rp+2) << 8) | *(rp+3);
4166             png_uint_32 s2   = (*(rp+4) << 8) | *(rp+5);
4167             png_uint_32 red  = (png_uint_32)((s0+s1+65536L) & 0xffffL);
4168             png_uint_32 blue = (png_uint_32)((s2+s1+65536L) & 0xffffL);
4169             *(rp  ) = (png_byte)((red >> 8) & 0xff);
4170             *(rp+1) = (png_byte)(red & 0xff);
4171             *(rp+4) = (png_byte)((blue >> 8) & 0xff);
4172             *(rp+5) = (png_byte)(blue & 0xff);
4173          }
4174       }
4175    }
4176 }
4177 #endif /* PNG_MNG_FEATURES_SUPPORTED */